'ThreeJs does not render my objects after putting them in a list
So I had some code and when I refactored it no longer shows anything. I don't get any error in the console so I don't really have much to go on. As far as I can tell this code should produce identical output to the working instance but it doesn't. Here's the broken code.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="http://threejs.org/build/three.min.js"></script>
<script>var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var objects = [
{
name : "earth",
geometry : new THREE.SphereGeometry(1, 32, 32),
material : new THREE.MeshPhongMaterial(),
mesh : new THREE.Mesh(this.geometry, this.material),
init : function(scene){
console.log("Wtf");
this.mesh.position.set(0,0,0);
//this.material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
scene.add(this.mesh);
console.log("ugh");
},
animate : function(t){this.mesh.position.set(0+t/100,0+t/100,0+t/100);}
},
{
name : "satellite",
geometry : new THREE.SphereGeometry(0.1, 32, 32),
material : new THREE.MeshPhongMaterial(),
mesh : new THREE.Mesh(this.geometry, this.material),
init : function(scene){
console.log("Wtf");
this.mesh.position.set(1.5,0,0);
//this.material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
scene.add(this.mesh);
console.log("ugh");
},
animate : function(t){this.mesh.position.set(1.5+t/100,0+t/100,0+t/100);}
}];
objects.forEach(object => object.init(scene));
var light = new THREE.HemisphereLight(0xf6e86d, 0x404040, 0.5);
scene.add(light);
camera.position.x = 0;
camera.position.y = -5;
camera.position.z = 0;
camera.lookAt(new THREE.Vector3( 0, 0, 0));
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
And here's the working example.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="http://threejs.org/build/three.min.js"></script>
<script>var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var earth_geometry = new THREE.SphereGeometry(1, 32, 32);
var earth_material = new THREE.MeshPhongMaterial();
var earth_mesh = new THREE.Mesh(earth_geometry, earth_material);
earth_mesh.position.set(0,0,0);
//earth_material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
scene.add(earth_mesh);
var satellite_geometry = new THREE.SphereGeometry(0.1, 32, 32);
var satellite_material = new THREE.MeshPhongMaterial();
var satellite_mesh = new THREE.Mesh(satellite_geometry, satellite_material);
satellite_mesh.position.set(1.5,0,0);
//satellite_material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
scene.add(satellite_mesh);
var light = new THREE.HemisphereLight(0xf6e86d, 0x404040, 0.5);
scene.add(light);
camera.position.x = 0;
camera.position.y = -5;
camera.position.z = 0;
camera.lookAt(new THREE.Vector3( 0, 0, 0));
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
I've tried brining the scene.add out of the init function and just doing it manually with scene.add(object[0].mesh) and changing objects to const and let but none of that helps.
Solution 1:[1]
The issue is here:
mesh : new THREE.Mesh(this.geometry, this.material),
The instantiation is evaluated as a property on that object and is not called inside a function. Therefore this will refer to the global context, or the parent window in this case, which does not have "geometry" or "material" properties defined. this only changes when inside a function, to refer to the object of which that function is a property (or whatever the caller binds it to, if applicable.)
Without refactoring your code, the easiest fix would be to instantiate the geometry and material on the same line as the mesh as you pass those in, like this:
mesh : new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32), new THREE.MeshPhongMaterial()),
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ajdhefley |
