我想加载引用多个cube.obj
文件的cube_*.mtl
文件,而这些文件又使用纹理图像*.png
(all 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)
我做错了什么以及如何正确地做到这一点?
答案 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);
});
}
希望它有所帮助!