【问题标题】:How to add a material (.mtl) to an object (.obj) using three.js?如何使用three.js将材质(.mtl)添加到对象(.obj)?
【发布时间】:2020-02-15 09:50:19
【问题描述】:

我已经成功地从网上找到的 sn-p 代码中获得了一个 .obj 文件,以使用three.js 显示,我根据自己的需要进行了调整。但我现在尝试添加 .mtl 材质文件,但遇到了问题。

我尝试了一些方法,但似乎没有任何效果。我是 three.js 的新手,所以肯定在这里误解了一些东西......

这是我正在使用的当前代码,可以很好地显示我的 .obj 文件:

var renderer, scene, camera, Nefertiti;

var ww = window.innerWidth,
    wh = window.innerHeight;

function init(){

    renderer = new THREE.WebGLRenderer({canvas : document.getElementById('scene')});
    renderer.setSize(ww,wh);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(50,ww/wh, 0.1, 10000 );
    camera.position.set(0,0,500);
    scene.add(camera);

    //Add a light in the scene
    directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
    directionalLight.position.set( 0, 0, 350 );
    directionalLight.lookAt(new THREE.Vector3(0,0,0));
    scene.add( directionalLight );

    //Load the obj file
    loadOBJ();
}

var loadOBJ = function(){

    //Manager from ThreeJs to track a loader and its status
    var manager = new THREE.LoadingManager();
    //Loader for Obj from Three.js
    var loader = new THREE.OBJLoader( manager );

    //Launch loading of the obj file, addNefertitiInScene is the callback when it's ready 
    loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);

};

var addNefertitiInScene = function(object){
    Nefertiti = object;
    //Move the Nefertiti in the scene
    Nefertiti.scale.set(0.7,0.7,0.7);
    Nefertiti.rotation.x = 0.5;
    Nefertiti.rotation.y = 5.5;
    Nefertiti.rotation.z = 0.2;
    Nefertiti.position.y = -40;
    Nefertiti.position.z = 1;
    //Go through all children of the loaded object and search for a Mesh
    object.traverse( function ( child ) {
        //This allow us to check if the children is an instance of the Mesh constructor
        if(child instanceof THREE.Mesh){
            child.material.color = new THREE.Color(0XFFFFFF);
            //Sometimes there are some vertex normals missing in the .obj files, ThreeJs will compute them
            child.geometry.computeVertexNormals();
        }
    });
    //Add the 3D object in the scene
    scene.add(Nefertiti);

    var canvas = renderer.domElement;
canvas.addEventListener('mousemove', onMouseMove);

function animate() {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
}
animate();

function onMouseMove(event) {
  Nefertiti.rotation.y += event.movementX * 0.001;
     Nefertiti.rotation.x += event.movementY * 0.0005;
}
};


init();

这是我尝试添加的 sn-p 以加载不起作用的 mtl 文件(我只是缩短了到 /mypath/ 的实际路径以保持此处的整洁)

var loadOBJ = function(){

    var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/mypath/' );
mtlLoader.setPath( '/mypath/' );
var url = "/mypath/Nefertiti-3d.mtl";
mtlLoader.load( url, function( materials ) {

    materials.preload();

    //Manager from ThreeJs to track a loader and its status
    var manager = new THREE.LoadingManager();
    //Loader for Obj from Three.js
    var loader = new THREE.OBJLoader( manager );

    loader.setMaterials( materials );
    loader.setPath( '/mypath/' );

    //Launch loading of the obj file, addNefertitiInScene is the callback when it's ready 
    loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);

    object.position.y = - 95;
        scene.add( object );

    }, onProgress, onError );


};

通过研究,我可以看到材料必须有一个网格才能工作,但我无法从任何文档中弄清楚如何正确实现它。

如果能在我的代码中添加 mtl 文件,我们将不胜感激!!

** 编辑 **

所以我根据 Mugen87 的建议将代码的 sn-p 更改为以下内容:

var loadOBJ = function(){

var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( '/mypath/' );
var url = "/mypath/Nefertiti-3d.mtl";
mtlLoader.load( url, function( materials ) {

materials.preload();

//Manager from ThreeJs to track a loader and its status
var manager = new THREE.LoadingManager();
//Loader for Obj from Three.js
var loader = new THREE.OBJLoader( manager );

loader.setMaterials( materials );
loader.setPath( '/mypath/' );

//Launch loading of the obj file, addNefertitiInScene is the callback when it's ready 
loader.load( '/mypath/Nefertiti-3d.obj', addNefertitiInScene);

}, onProgress, onError );


};

我还包含了three.js 示例中的MTLLoader.js(我不确定这是否正确,我发现很难找到这方面的信息)并且在控制台中收到以下错误:

Uncaught SyntaxError: Cannot use import statement outside a module

(index):136 Uncaught TypeError: THREE.MTLLoader is not a constructor
    at loadOBJ ((index):136)
    at init ((index):132)
    at (index):199
loadOBJ @ (index):136
init @ (index):132
(anonymous) @ (index):199

有什么想法吗?我在代码中的 MTL 有什么问题吗?

【问题讨论】:

    标签: javascript object three.js mtl-file


    【解决方案1】:
    object.position.y = - 95;
    scene.add( object );
    

    我想你已经从official OBJ/MTL example 复制了两行代码,对吧?不幸的是,它们在这里没有意义,因为objectundefined。请记住,addNefertitiInScene 是您的 onLoad() 回调,负责将加载的对象添加到场景中。

    此外,mtlLoader.setBaseUrl( '/mypath/' ); 应该不是必需的。该方法在很久以前就被删除了。

    还要确保使用浏览器的开发工具实际加载了 MTL 文件。

    three.js R109

    【讨论】:

    • 感谢您的回复,非常感谢。我将使用所做的更改以及我现在遇到的错误来编辑我的原始帖子,看看是否有机会获得更多帮助
    • 你能说明你是如何导入MTLLoader的吗? Cannot use import statement outside a module 通常表示您以错误的方式使用 ES6 模块。
    • 我从示例中的 GitHub 文件中复制了 MTLLoader.js:github.com/mrdoob/three.js/blob/dev/examples/js/loaders/… 这就是我加载所有脚本的方式:
    • 您能否确保使用与OBJLoaderMTLLoader 版本匹配的three.js 版本?如果您使用具有如此旧的three.js 版本(R85)的最新加载程序类,那就不好了。请改用此网址 threejs.org/build/three.jsthreejs.org/examples/js/loaders/MTLLoader.js
    • 无论如何,尝试将您的完整代码共享为 git 存储库。然后我可以在我的系统上调试问题。
    猜你喜欢
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2019-01-18
    • 2017-07-17
    相关资源
    最近更新 更多