如何在 Three.js 中加载带有多个“.mtl"文件的“.obj" [英] How to load '.obj' with multiple '.mtl' files in Three.js

查看:93
本文介绍了如何在 Three.js 中加载带有多个“.mtl"文件的“.obj"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to load cube.obj file which references multiple cube_*.mtl files, which in turn use texture images *.png (all resources). The reason to load multiple mtl's instead of one is to be able dynamically load objects with the same geometry but different materials.

我找不到这样的例子,所以我试图在 MultiMaterial(is noThreejs 不再支持) 文档和 webgl_loader_obj_mtl 通过加载所有 mtl,创建 MultiMaterial,并加载 obj:

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:

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 表现为非阻塞"功能.

1) THREE.MTLLoader.load behaves as a "non blocking" function.

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

Thus, you are loading the OBJ files when the MTL ones are not still loaded completely. You need to load the OBJ files inside the callback function passed as argument on mtlLoader.load(). Look the example you have mentioned.

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

2) About the mtlLoader.load callback function passed as argument:

它的参数 materials 属于 THREE.MTLLoader.MaterialCreator 类型.因此,loadedMaterials 是一个 THREE.MTLLoader.MaterialCreator 元素的数组,用于创建一个 THREE.MultiMaterial(不再支持threejs),需要三个.Material 元素.

Its argument, materials, is of type THREE.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.

此外,MultiMaterial 用于将多种材质分配给一个对象(每个对象的面一个材质),而不是用于可选地"为对象选择材质 (MultiMaterial Cube 示例).

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).

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

One approach for doing this (code NOT tested):

首先,我们需要一个 LoadingManager:

First, we'll need an LoadingManager:

var manager = new THREE.LoadingManager();

这是为了断言在加载 OBJ 之前已经加载了所有 MTL:

This is for assert that all MTL's have been loaded before load an 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);
    }
};

然后我们加载所有 MTL:

And we load all MTL's:

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

希望有帮助!

这篇关于如何在 Three.js 中加载带有多个“.mtl"文件的“.obj"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆