2017-01-27 42 views
5

chciałbym załadować cube.obj plik, który odwołuje się do wielu cube_*.mtl plików, który z kolei obrazy użycie tekstury *.png (all resources). Powodem załadowania wielu mtl zamiast jednego jest możliwość dynamicznego ładowania obiektów o tej samej geometrii, ale różnych materiałach.Jak załadować „.obj” z wielu plików „.mtl” w Three.js

nie mogłem znaleźć takich przykładów tak próbowałem mieszać przykłady w MultiMaterial dokumentacji i webgl_loader_obj_mtl ładując wszystkie MTL, tworząc MultiMaterial i ładowanie obj:

var resources = 'cube/'; 
var materialsToLoad = [ 
    'cube_red.mtl', 
    'cube_green.mtl', 
    'cube_blue.mtl' 
]; 

var loadedMaterials = []; 

var mtlLoader = new THREE.MTLLoader(); 
mtlLoader.setPath(resources); 
for (var i = 0; i < materialsToLoad.length; i++) { 
    mtlLoader.load(materialsToLoad[i], function(materials) { 
     materials.preload(); 
     loadedMaterials.push(materials); 
    }); 
} 

var multi = new THREE.MultiMaterial(loadedMaterials); 
var objLoader = new THREE.OBJLoader(); 
objLoader.setPath(resources); 
objLoader.setMaterials(multi); // #1 
objLoader.load('cube.obj', function (object) { 
    scene.add(object); 
}); 

Ale to nie zadziała, to wyjątek wyrzucony:

Uncaught TypeError: this.materials.create is not a function 
at THREE.OBJLoader.parse (OBJLoader.js:684) 
at OBJLoader.js:50 
at XMLHttpRequest.<anonymous> (three.min.js:619) 

Co robię źle i jak to zrobić właściwie?

Odpowiedz

0

Myślę, że są tutaj pewne problemy.

1) THREE.MTLLoader .load zachowuje się jak funkcja "nie blokowania".

W ten sposób ładujesz pliki OBJ, gdy te MTL nie są jeszcze całkowicie załadowane. Musisz załadować pliki OBJ wewnątrz funkcji zwrotnej przekazanej jako argument na mtlLoader.load(). Spójrz na wspomniane example.

2) O mtlLoader.load funkcji zwrotnej przechodzi jako argument:

argumencie materiałów jest typu THREE.MTLLoader.MaterialCreator. W konsekwencji, loadedMaterials jest tablicą elementów THREE.MTLLoader.MaterialCreator, a do utworzenia THREE.MultiMaterial potrzebna jest tablica elementów THREE.Material.

Poza tym materiał MultiMaterial służy do przypisania wielu materiałów do jednego obiektu (jeden materiał na twarz obiektu), a nie do "opcjonalnego" wyboru materiału dla obiektu (MultiMaterial Cube example).


Jednym podejściem do wykonywania tej (kod NIE testowane):

Po pierwsze, będziemy potrzebować LoadingManager:

var manager = new THREE.LoadingManager(); 

To dla twierdzić, że wszystkie MTL zostały załadowane przed załadowaniem OBJ:

manager.onLoad = function() { 
    /* 
     At this point, all MTL's have been loaded. 
     We will load an OBJ with the first material option 
     (for example), if it exists. 
    */ 

    if (loadedMaterials.length > 0) { 
     var objLoader = new THREE.OBJLoader(); 
     objLoader.setPath(resources); 
     objLoader.setMaterials(loadedMaterials[0]); // First material 
     objLoader.load('cube.obj', function (object) { 
     scene.add(object); 
    } 
}; 

Załadujemy wszystkie MTL:

var mtlLoader = new THREE.MTLLoader(manager); 
mtlLoader.setPath(resources); 
for (var i = 0; i < materialsToLoad.length; i++) { 
    mtlLoader.load(materialsToLoad[i], function(materials) { 
     materials.preload(); 
     loadedMaterials.push(materials); 
    }); 
} 

Mam nadzieję, że pomoże!