简体   繁体   English

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

[英]How to load '.obj' with multiple '.mtl' files in Three.js

I would like to load cube.obj file which references multiple cube_*.mtl files, which in turn use texture images *.png ( all resources ). 我想加载引用多个cube_*.mtl cube.obj文件的cube.obj文件,该文件又使用纹理图像*.png所有资源 )。 The reason to load multiple mtl's instead of one is to be able dynamically load objects with the same geometry but different materials. 加载多个mtl而不是一个的原因是能够动态加载具有相同几何形状但材料不同的对象。

I couldn't find such example so I tried to mix examples in MultiMaterial(is no longer supported by threejs) documentation and webgl_loader_obj_mtl by loading all mtl's, creating MultiMaterial , and loading obj: 我找不到这样的示例,因此我尝试通过加载所有mtl,创建MultiMaterial并加载obj来混合MultiMaterial(不再受threejs支持)文档和webgl_loader_obj_mtl中MultiMaterial

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

But this doesn't work, exception is thrown: 但这不起作用,抛出异常:

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)

What am I doing wrong and how to do that properly? 我在做错什么以及如何正确做?

I think there are some problems here. 我认为这里有些问题。

1) THREE.MTLLoader .load behaves as a "non blocking" function. 1) THREE.MTLLoader .load表现为“非阻塞”功能。

Thus, you are loading the OBJ files when the MTL ones are not still loaded completely. 因此,当MTL文件尚未完全加载时,您正在加载OBJ文件。 You need to load the OBJ files inside the callback function passed as argument on mtlLoader.load() . 您需要在作为参数传递给mtlLoader.load()的回调函数中加载OBJ文件。 Look the example you have mentioned. 看一下您提到的示例

2) About the mtlLoader.load callback function passed as argument: 2)关于作为参数传递的mtlLoader.load回调函数:

Its argument, materials , is of type THREE.MTLLoader.MaterialCreator . 它的参数materialTHREE.MTLLoader.MaterialCreator类型。 In consequence, loadedMaterials is an array of THREE.MTLLoader.MaterialCreator elements and, for create a THREE.MultiMaterial (no longer supported by threejs) , you need an array of THREE.Material elements. 因此, loadedMaterialsTHREE.MTLLoader.MaterialCreator元素的数组,并且要创建THREE.MultiMaterial(不再受threejs支持) ,需要一个THREE.Material元素数组。

Besides, MultiMaterial is used for assigning many materials to one object (one material per object's face), and not for "optionally" selecting a material for an object ( MultiMaterial Cube example ). 此外,MultiMaterial用于将多个材质分配给一个对象(每个对象的一个​​面一个材质),而不是用于“可选地”选择对象的材质( MultiMaterial Cube示例 )。


One approach for doing this (code NOT tested): 这样做(代码测试)的一种方法:

First, we'll need an LoadingManager : 首先,我们需要一个LoadingManager

var manager = new THREE.LoadingManager();

This is for assert that all MTL's have been loaded before load an OBJ: 这是为了断言在装入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);
    }
};

And we load all MTL's: 我们加载所有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);
    }); 
}

Hope it helps! 希望能帮助到你!

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

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