为什么只有添加到loader.load回调函数内的场景中才会显示从JSONLoader到THREE.js导入的几何体?

时间:2015-08-13 18:03:44

标签: javascript three.js

我有一个three.js代码,可以从blender导入几何体并将其显示在three.js上。为了有效地显示它,我必须将网格添加到加载器回调函数内的场景中。 这有效:

var loader = new THREE.JSONLoader();
var testGeometry; //global variable
loader.load( "sample.js", function( geometry ) {
        testGeometry= new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0xffcaff, specular: 0x505050, shininess: 100 } ) );
    scene.add( testGeometry);
} );

由于testGeometry是一个全局变量,我希望下面的代码也能正常工作:

var loader = new THREE.JSONLoader();
var testGeometry; //global variable
loader.load( "sample.js", function( geometry ) {
    testGeometry= new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0xffcaff, specular: 0x505050, shininess: 100 } ) );
    } );
scene.add( testGeometry);

但事实并非如此。我需要在我的代码中进一步将此网格添加到另一个Object3D,然后将其添加到场景中。有关如何使其工作的任何想法?我想我在这里遗漏了一些关于全局变量和回调的基本内容...... 谢谢!

1 个答案:

答案 0 :(得分:0)

它在第二个示例中不起作用的原因是因为回调仅在加载文件之后异步执行。当您调用load时,回调不会立即执行,并且加载在完成之前不会阻塞。因此,当您致电scene.addGeometry时,testGeometry尚未初始化,因此您将undefined值传递给它。

在你的第一个例子中它起作用,因为正在从回调内部执行.addGeometry调用。

如果你只想将它添加到场景中,那么将它放在回调中更容易,而不必在代码中的其他地方处理可能未初始化的全局:

var loader = new THREE.JSONLoader();
loader.load( "sample.js", function( geometry ) {
    var testGeometry = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0xffcaff, specular: 0x505050, shininess: 100 } ));
    scene.add( testGeometry);
});

修改1 承诺

处理这种情况的一种常见方法是使用ES6中标准的Promises,并且可以使用QBluebird等库轻松填充。

注意这里我是承诺的ES6规范,大多数库应该符合这种语法:

var geometryPromise = new Promise(function(resolve, reject) {
  loader.load("sample.js", function(geometry) {
    resolve(new THREE.Mesh(geometry, phongMaterial));
  });
});

//Now your value can never be undefined
//The then handler only gets executed when the promise is resolved.
geometryPromise.then(function(geo) { scene.addGeometry(geo); });
geometryPromise.then(/*Do more stuff it will use the same value*/);