Three.js Управляет объектом из ObjLoader - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь манипулировать (например, изменять положение, масштаб, вращение) объектом, загруженным с использованием OBJLoader в Three.js. Хотя это легко сделать один раз, я не могу понять, как это сделать, когда я хочу, например, во время цикла анимации или в любом месте за пределами начального обратного вызова загрузки.

Вот мой код:

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;

Здесь следует отметить следующие ключевые моменты:

  • Я могу загрузить его и манипулировать им в пределах цикла, без ошибок;
  • Если я сделаю вышеизложенное, в последней строке я получу сообщение об ошибке: 1011 *.
  • Эта ошибка сохраняется, если я определяю obj вне функции (как глобальную), а затем ссылаюсь на нее соответствующим образом.

Я пробовал подобный код с загрузчиком JSON, к тем же результатам (я могу манипулировать им в нагрузке, но не после).

1 Ответ

0 голосов
/ 04 мая 2018

Загрузчики в THREE.js являются асинхронными, поэтому лучший способ обойти это просто использовать Promise или использовать новое ожидание. Вот обещание реализации. Я просто завернул весь код загрузчика THREE.js в обещание и в конце позвонил resolve. Затем просто используйте .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;
  
});

Обновление Исправлена ​​небольшая ошибка, из-за которой reject пока onProgress. Плохо, прочитал еще раз документы THREE.js и заметил, что порядок load равен url, onSuccess, onProgress, onError, поэтому финал должен быть url, resolve, () => {}, reject.

...