简体   繁体   English

Three.js操纵ObjLoader中的对象

[英]Three.js Manipulate an object from ObjLoader

I am trying to manipulate (eg change position, scale, rotation) an object loaded using OBJLoader in Three.js. 我试图操纵(例如更改位置,缩放,旋转)在Three.js中使用OBJLoader加载的对象。 While this is easy to do so once, I cannot work out how to do this when I want eg during the animate loop, or anywhere outside of the initial load callback. 虽然这很容易做到这一点,但是当我想要时,例如在动画循环期间,或者在初始加载回调之外的任何地方,我都无法解决这个问题。

Here is my code: 这是我的代码:

function loadObj( path, name )
{
    var obj;
    var mtlLoader = new THREE.MTLLoader();
    mtlLoader.setPath( path );
    mtlLoader.load( name+".mtl", function( materials ) {
        materials.preload();

        var objLoader = new THREE.OBJLoader();
        objLoader.setMaterials( materials );
        objLoader.setPath( path );
        objLoader.load( name+".obj", function( object ) {
            obj = object;
            obj.position.x = 20;
            scene.add( obj );
        });
    });
    return obj;
}

var myObj = loadObj( "assets/", "test" );

myObj.position.y = 20;

The key points to note here are: 这里要注意的关键点是:

  • I can load it and manipulate it within the loop fine, and no errors are raised; 我可以加载它并在循环内操作它,并且不会出现错误;
  • If I do the above, I'll get an error on the last line, which states: Cannot read property 'position' of undefined . 如果我执行上述操作,我将在最后一行收到错误,其中指出: Cannot read property 'position' of undefined
  • This error remains if I define obj outside the function (as a global), and then reference it accordingly. 如果我在函数外定义obj (作为全局),然后相应地引用它,则此错误仍然存​​在。

I've tried similar code with the JSON loader, to the same results (I am able to manipulate it within the load, but not afterwards). 我已经尝试了与JSON加载器类似的代码,得到了相同的结果(我能够在加载中操作它,但之后却没有)。

Loaders in THREE.js are asynchronous, so the best way around this is to simply use a Promise , or use the new await. THREE.js中的THREE.js是异步的,因此最好的方法是简单地使用Promise ,或使用新的await。 Heres the promise implementation. 继承人承诺实施。 I simply wrapped all the THREE.js loader code inside the promise and call resolve at the end. 我只是将所有THREE.js加载器代码包含在promise中,并在最后调用resolve Then just use .then to execute whenever the asynchronous request is done. 然后只要异步请求完成就使用.then执行。

 function loadObj( path, name ){ var progress = console.log; return new Promise(function( resolve, reject ){ var obj; var mtlLoader = new THREE.MTLLoader(); mtlLoader.setPath( path ); mtlLoader.load( name + ".mtl", function( materials ){ materials.preload(); var objLoader = new THREE.OBJLoader(); objLoader.setMaterials( materials ); objLoader.setPath( path ); objLoader.load( name + ".obj", resolve, progress, reject ); }, progress, reject ); }); } // This way you can use as many .then as you want var myObjPromise = loadObj( "assets/", "test" ); myObjPromise.then(myObj => { scene.add( myObj ); myObj.position.y = 20; }); 

Update Corrected a little mistake where it would reject while onProgress . 更新纠正了在onProgress reject一个小错误。 My Bad, read the THREE.js docs again and noticed that the order of load is url, onSuccess, onProgress, onError , so the final should be url, resolve, () => {}, reject . 我的坏,再次阅读THREE.js文档并注意到load的顺序是url, onSuccess, onProgress, onError ,所以final应该是url, resolve, () => {}, reject

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM