【问题标题】:How to load '.obj' with multiple '.mtl' files in Three.js如何在 Three.js 中加载带有多个“.mtl”文件的“.obj”
【发布时间】:2017-06-13 14:05:51
【问题描述】:

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

我找不到这样的示例,因此我尝试通过加载所有 mtl、创建 MultiMaterial 和加载 obj 来混合 MultiMaterial(is no longer supported by threejs) 文档和 webgl_loader_obj_mtl 中的示例:

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)

我做错了什么以及如何正确地做到这一点?

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    我觉得这里有些问题。

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

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

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

    它的参数 materials 的类型是 THREE.MTLLoader.MaterialCreator。因此,loadedMaterials 是一个由 THREE.MTLLoader.MaterialCreator 元素组成的数组,而要创建 THREE.MultiMaterial (no longer supported by 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);
        }); 
    }
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2017-10-04
      • 2013-07-16
      • 1970-01-01
      • 2014-03-24
      • 2014-10-03
      • 1970-01-01
      • 2018-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多