如何在Three.js中加载具有多个'.mtl'文件的'.obj'文件

6
我想要加载cube.obj 文件,该文件引用了多个cube_*.mtl文件,而这些文件又使用纹理图像*.png(所有资源)。之所以加载多个mtl而不是一个,是为了能够动态加载具有相同几何形状但不同材质的对象。
我没有找到这样的示例,因此我尝试混合 MultiMaterial(已不再由Three.js支持) 文档和 webgl_loader_obj_mtl 示例,通过加载所有mtl、创建MultiMaterial并加载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);
});

但是这并不起作用,会抛出异常:
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)

我应该怎样做才能正确地完成任务?请指出我的错误并帮我改正。
1个回答

0

我认为这里有一些问题。

1) THREE.MTLLoader.load 表现为“非阻塞”函数。

因此,当 MTL 文件尚未完全加载时,您正在加载 OBJ 文件。您需要在传递给 mtlLoader.load() 的回调函数内部加载 OBJ 文件。请查看您提到的 示例

2) 关于传递为参数的 mtlLoader.load 回调函数:

它的参数materials是类型为THREE.MTLLoader.MaterialCreator的。因此,loadedMaterials是一个由THREE.MTLLoader.MaterialCreator元素组成的数组,而要创建 THREE.MultiMaterial(已不再受threejs支持),您需要一个由 THREE.Material元素组成的数组。

此外,MultiMaterial用于将多个材质分配给一个对象(每个对象面一个材质),而不是为对象“可选地”选择材质( MultiMaterial Cube example)。


一个实现此功能的方法(代码未经测试):
首先,我们需要一个LoadingManager
var manager = new THREE.LoadingManager();

这是为了确保在加载 OBJ 之前已经加载了所有 MTL 文件:

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);
    }
};

然后我们加载所有的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);
    }); 
}

希望它有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接