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

时间:2017-01-27 19:30:57

标签: javascript three.js

我想加载引用多个cube.obj文件的cube_*.mtl文件,而这些文件又使用纹理图像*.pngall resources)。加载多个mtl而不是一个mtl的原因是能够动态加载具有相同几何但不同材质的对象。

我无法找到这样的示例所以我尝试在MultiMaterial(is no longer supported by threejs)文档和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 :(得分:0)

我认为这里存在一些问题。

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

因此,当MTL未完全加载时,您正在加载OBJ文件。您需要在作为 mtlLoader.load()上的参数传递的回调函数内加载OBJ文件。看看你提到的example

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

其论点材料的类型为 THREE.MTLLoader.MaterialCreator 。因此, loadedMaterials THREE.MTLLoader.MaterialCreator 元素的数组,为了创建THREE.MultiMaterial (no longer supported by threejs),您需要一个THREE.Material元素数组

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

执行此操作的一种方法(代码 NOT 已测试):

首先,我们需要一个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);
    }); 
}

希望它有所帮助!