hii i am trying to get a sphree to render into the screen. here is my js file.
function Earth()
{
this.getEarth = init();
function init()
{
var map = {map:THREE.ImageUtils.loadTexture("images/earth_surface_2048.jpg")};
var material = new THREE.MeshBasicMaterial(map);
var geometry = new THREE.SphereGeometry(1,32,32);
return new THREE.Mesh(geometry, material);
}
function update()
{
getEarth.rotation.x += .01;
}
}
and here is the script that is in the html file
threejs is included to the page.
<script>
var renderer = null;
var scene = null;
var camera = null;
var mesh = null;
var earth = null;
$(document).ready(
function() {
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({ antialias: true } );
renderer.setSize(container.offsetWidth,container.offsetHeight);
container.appendChild(renderer.domElement)
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45,
container.offsetWidth / container.offsetHeight, 1, 4000 );
earth = new Earth();
scene.add(camera);
scene.add(earth.getEarth);
renderer.render( scene, camera );
}
);
</script>
i get no erros from the debugger, so any ideas ?
earth.getEarth is probably null or a function. I remember scene.add() silently ignoring stuff it can't take, like undefined values and so on.
How about changing var getEarth = init(); to this.getEarth = init(); so that code outside of your class scope will see that variable in your earth object. Althought I would advice against using a method-like name for a variable containing an object.
Related
I have a GLTF version 1.0 model that I am importing into Three.js using LegacyGLTFLoader.js. When I do so, everything looks good, except that the model does not receive shadows. I am guessing that this is because the imported model's material is THREE.RawShaderMaterial, which does not support receiving shadows (I think). How can I fix this so that my imported model can receive shadows?
Here is sample code:
// Construct scene.
var scene = new THREE.Scene();
// Get window dimensions.
var width = window.innerWidth;
var height = window.innerHeight;
// Construct camera.
var camera = new THREE.PerspectiveCamera(75, width/height);
camera.position.set(20, 20, 20);
camera.lookAt(scene.position);
// Construct renderer.
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);
// Construct cube.
var cubeGeometry = new THREE.BoxGeometry(10, 1, 10);
var cubeMaterial = new THREE.MeshPhongMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.translateY(15);
scene.add(cube);
// Construct floor.
var floorGeometry = new THREE.BoxGeometry(20, 1, 20);
var floorMaterial = new THREE.MeshPhongMaterial({color: 0x00ffff});
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
scene.add(floor);
// Construct light.
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 0);
light.castShadow = true;
scene.add(light);
// Construct light helper.
var lightHelper = new THREE.DirectionalLightHelper(light);
scene.add(lightHelper);
// Construct orbit controls.
new THREE.OrbitControls(camera, renderer.domElement);
// Construct GLTF loader.
var loader = new THREE.LegacyGLTFLoader();
// Load GLTF model.
loader.load(
"https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb",
function(event) {
var model = event.scene.children[0];
var mesh = model.children[0];
mesh.receiveShadow = true;
scene.add(model);
},
null,
function(event) {
alert("Loading model failed.");
}
);
// Animates the scene.
var animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
// Animate the scene.
animate();
Here are my resources:
https://dl.dropboxusercontent.com/s/y2r8bsrppv0oqp4/three.js
https://dl.dropboxusercontent.com/s/5wh92lnsxz2ge1e/LegacyGLTFLoader.js
https://dl.dropboxusercontent.com/s/1jygy1eavetnp0d/OrbitControls.js
https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb
Here is a JSFiddle:
https://jsfiddle.net/rmilbert/8tqc3yx4/26/
One way to fix the problem is to replace the instance of RawShaderMaterial with MeshStandardMaterial. To get the intended effect, you have to apply the existing texture to the new material like so:
var newMaterial = new THREE.MeshStandardMaterial( { roughness: 1, metalness: 0 } );
newMaterial.map = child.material.uniforms.u_tex.value;
You also have to compute normal data for the respective geometry so lighting can be computed correctly. If you need no shadows, the unlint MeshBasicMaterial is actually the better choice.
Updated fiddle: https://jsfiddle.net/e67hbj1q/2/
I originally had an animate function in place for my three.js scene that is loaded within an AngularJS Modal, but found that after closing the Modal, the animation keeps going, and that is unneeded since I don't require constant animation like a video game would have.
At this point, I switched it to only render when someone uses the OrbitControls to move the simple box in my example, and have an initial call to render the scene so that users can see the box instead of a big blacked out square.
However, upon initial render, the texture does not appear to be applied until I use the orbit controls and move the box, at which point they appear. This is odd, since both my initial call and the listener tied to the OrbitControls are to the same function. How do I get the initial load to show the texture?
$scope.generate3D = function () {
// 3D OBJECT - Variables
var texture0 = baseBlobURL + 'Texture_0.png';
var boxDAE = baseBlobURL + 'Box.dae';
var scene;
var camera;
var renderer;
var box;
var controls;
var newtexture;
// Update texture
newtexture = THREE.ImageUtils.loadTexture(texture0);
//Instantiate a Collada loader
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load(boxDAE, function (collada) {
box = collada.scene;
box.traverse(function (child) {
if (child instanceof THREE.SkinnedMesh) {
var animation = new THREE.Animation(child, child.geometry.animation);
animation.play();
}
});
box.scale.x = box.scale.y = box.scale.z = .2;
box.updateMatrix();
init();
// Initial call to render scene, from this point, Orbit Controls render the scene per the event listener
render();
});
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xdddddd);
//renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(500, 500);
// Load the box file
scene.add(box);
// Lighting
var light = new THREE.AmbientLight();
scene.add(light);
// Camera
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
// Rotation Controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.noZoom = false;
controls.noPan = false;
var myEl = angular.element(document.querySelector('#webGL-container'));
myEl.append(renderer.domElement);
}
function render() {
renderer.render(scene, camera);
console.log('loaded');
}
}
You are using ColladaLoader and you want to force a call to render() when the model and all the textures are loaded.
If you add the model to the scene in the loader callback, there is still a chance that even though the model has loaded, the textures may not have.
One thing you can do is add the following before instantiating the loader:
THREE.DefaultLoadingManager.onLoad = function () {
// console.log( 'everything loaded' ); // debug
render();
};
Or alternatively,
THREE.DefaultLoadingManager.onProgress = function ( item, loaded, total ) {
// console.log( item, loaded, total ); // debug
if ( loaded === total ) render();
};
three.js r.72
I'm trying to add a background to a webgl scene(Three.js). The scene contains two animated spritesheets that I created using DAZ3D and Photoshop. I've tried just about everything but to no avail, the background is either white or black. I've tried many examples on the web then either my spritesheet animator won't work or the background won't appear. I read that I need to make two scenes with two camera's, but that doesn't seem to work as well.
I really don't understand why I would need to have two scenes anyway.
<script>
// standard global variables
var container,scene,camera,renderer,controls,stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// custom global variables
var attack,defense;
init();
animate();
// FUNCTIONS
function init(){
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth,SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45,ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT,NEAR = 0.1,FAR = 1000;
var light = new THREE.PointLight(0xEEEEEE);
var lightAmb = new THREE.AmbientLight(0x777777);
camera = new THREE.PerspectiveCamera(VIEW_ANGLE,ASPECT,NEAR,FAR);
scene.add(camera);
camera.position.set(-10,30,400);
camera.lookAt(scene.position);
// RENDERER
if (Detector.webgl)
renderer = new THREE.WebGLRenderer({antialias:true});
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
container = document.getElementById('ThreeJS');
container.appendChild(renderer.domElement);
// EVENTS
THREEx.WindowResize(renderer,camera);
THREEx.FullScreen.bindKey({charCode :'m'.charCodeAt(0)});
// LIGHTS
light.position.set(20,0,20);
scene.add(light);
scene.add(lightAmb);
// BACKGROUND
var texture = THREE.ImageUtils.loadTexture('images/sky.jpg');
var backgroundMesh = new THREE.Mesh(new THREE.PlaneGeometry(2,2,0),new THREE.MeshBasicMaterial({map:texture}));
backgroundMesh.material.depthTest = false;
backgroundMesh.material.depthWrite = false;
var backgroundScene = new THREE.Scene();
var backgroundCamera = new THREE.Camera();
backgroundScene.add(backgroundCamera);
backgroundScene.add(backgroundMesh);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture('images/checkerboard.jpg');
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(10,10);
var floorMaterial = new THREE.MeshBasicMaterial({map:floorTexture,side:THREE.DoubleSide,shininess:30});
var floorGeometry = new THREE.PlaneGeometry(1000,1000);
var floor = new THREE.Mesh(floorGeometry,floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// MESHES WITH ANIMATED TEXTURES!
var attackerTexture = new THREE.ImageUtils.loadTexture('images/kitinalevel2.png');
attack = new TextureAnimator(attackerTexture,2,13,26,25); // texture,#horiz,#vert,#total,duration.
var attackerMaterial = new THREE.MeshBasicMaterial({map:attackerTexture,side:THREE.DoubleSide,transparent:true});
var attackerGeometry = new THREE.PlaneGeometry(50,50,1,1);
var attacker = new THREE.Mesh(attackerGeometry,attackerMaterial);
attacker.position.set(-5,20,350);
scene.add(attacker);
var defenderTexture = new THREE.ImageUtils.loadTexture('images/kitinalevel1.png');
defense = new TextureAnimator(defenderTexture,2,13,26,25); // texture,#horiz,#vert,#total,duration.
var defenderMaterial = new THREE.MeshBasicMaterial({map:defenderTexture,side:THREE.DoubleSide,transparent:true});
var defenderGeometry = new THREE.PlaneGeometry(50,50,1,1);
var defenderx = new THREE.Mesh(defenderGeometry,defenderMaterial);
defenderx.position.set(25,20,350);
scene.add(defenderx);
}
function animate(){
requestAnimationFrame(animate);
render();
update();
}
function update(){
var delta = clock.getDelta();
attack.update(1000 * delta);
defense.update(1000 * delta);
//controls.update();
//stats.update();
}
function render(){
renderer.autoClear = false;
renderer.clear();
renderer.render(scene,camera);
renderer.render(backgroundScene,backgroundCamera);
}
function TextureAnimator(texture,tilesHoriz,tilesVert,numTiles,tileDispDuration){
// note:texture passed by reference,will be updated by the update function.
this.tilesHorizontal = tilesHoriz;
this.tilesVertical = tilesVert;
// how many images does this spritesheet contain?
// usually equals tilesHoriz * tilesVert,but not necessarily,
// if there at blank tiles at the bottom of the spritesheet.
this.numberOfTiles = numTiles;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1 / this.tilesHorizontal,1 / this.tilesVertical);
// how long should each image be displayed?
this.tileDisplayDuration = tileDispDuration;
// how long has the current image been displayed?
this.currentDisplayTime = 0;
// which image is currently being displayed?
this.currentTile = 0;
this.update = function(milliSec){
this.currentDisplayTime += milliSec;
while(this.currentDisplayTime>this.tileDisplayDuration){
this.currentDisplayTime-=this.tileDisplayDuration;
this.currentTile++;
if (this.currentTile == this.numberOfTiles)
this.currentTile = 0;
var currentColumn = this.currentTile%this.tilesHorizontal;
texture.offset.x = currentColumn/this.tilesHorizontal;
var currentRow = Math.floor(this.currentTile/this.tilesHorizontal);
texture.offset.y = currentRow/this.tilesVertical;
}
};
}
</script>
What am I doing wrong?
Thanks in advance.
Found a solution:
renderer = new THREE.WebGLRenderer({antialias:true,alpha: true });
This will keep the background transparant, then with a little css I made the background appear.
May you help me to find out why material don't apply to mesh?
http://websaints.net/model/index2.html — loading model with THREE.MeshNormalMaterial() material — ок.
http://websaints.net/model/index.html — trying to load with texture — not ok.
I create model with makehuman.org, save model as obj and then convert obj to json with help of grunt-three-obj
I think I do everything right … but somewhere I am wrong and get err:
Uncaught TypeError: Cannot set property 'needsUpdate' of undefined
Code:
var angle = .05,
scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(63, 4/3, 0.1, 1000),
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("screen"),
antialias: true
}),
json_loader = new THREE.JSONLoader(),
model = null
json_loader.load('http://websaints.net/model/json/human.js', modelLoaded, 'http://websaints.net/model/json/');
renderer.setSize(600, 400);
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = -10;
function render() {
if(model!=null){
model.rotation.y+=.05;
}
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
function modelLoaded(geometry, materials){
model = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
model.position.z = 10;
model.position.y = -8;
scene.add(model);
camera.lookAt({x:0,y:0,z:0});
}
With all best regards. Anton.
i have small problem with initialization of camera position in three.js . I write this project in typescript. The browser console returns me : Uncaught TypeError: Cannot read property 'position' of undefined . Here is my source code in app.ts file:
///<reference path="Lib/three.d.ts">
class Rendering {
camera: THREE.PerspectiveCamera;
scene: THREE.Scene;
renderer: THREE.CanvasRenderer;
windowHalfX: number;
windowHalfY: number;
constructor() {
this.windowHalfY = window.innerHeight/2;
this.windowHalfX = window.innerWidth / 2;
}
public init() {
var container = document.createElement('div');
document.body.appendChild(container);
this.camera = new THREE.PerspectiveCamera(60, this.windowHalfX / this.windowHalfY, 1, 1000);
this.camera.position.y = 100; // HERE CONSOLE CANNOT READ POSITION PROPERTY
this.camera.position.z = 200;
this.scene = new THREE.Scene();
this.renderer = new THREE.CanvasRenderer();
this.renderer.setSize(this.windowHalfX*2, this.windowHalfY*2);
container.appendChild(this.renderer.domElement);
var cubeGeometry = new THREE.CubeGeometry(150, 150, 150);
for (var i = 0; i < cubeGeometry.faces.length; i += 2) {
var hex = Math.random() * 0xffffff;
cubeGeometry.faces[i].color.setHex(hex);
cubeGeometry.faces[i + 1].color.setHex(hex);
}
var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, overdraw: 0.5 });
var cube = new THREE.Mesh(cubeGeometry, material);
cube.position.y = 150;
this.scene.add(cube);
}
public render() {
this.camera.lookAt(this.scene.position);
this.renderer.render(this.scene, this.camera);
}
}
Any idea how to fix this error?
The main cause of this error would be that you don't have the PerspectiveCamera JavaScript available...
If you downloaded the Three.JS zip file and included three.js - this isn't everything you need on your web page.
Your best bet is to use the minified three.js file that you will find here:
http://threejs.org/build/three.min.js
This bundles all of the individual components you'll need in one minified script, including your PerspectiveCamera.