【threejs基础:使用MTLLoader】加载材质OBj模型

已被阅读 4343 次 | 文章分类:javascript | 2022-05-26 00:25

介绍两种给OBJ模型添加材质的方法

1 加载obj模型

如何加载obj模型可以参考:加载obj模型

2 纹理方式(1):添加自带材质文件

这种方法适合由建模软件导出的模型;因为建模软件导出模型包含两个文件:obj文件和mtl文件

利用OBJLoader和MTLLoader加载器,分别加载他们才能保证模型跟纹理准确的显示;

/net/upload/image/20220526/c62cb050-8d42-45b9-832e-d0904ee93a4e.jpg

第一步:引入库

                                            
import * as THREE from 'three'
import { OBJLoader, MTLLoader } from 'three-obj-mtl-loader'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
                                            
                                        

第二步:初始化变量

                                            
let scene,camera,gridHelper,axes,renderer;
                                            
                                        

第四步:初始化场景

                                            
initScene();
function initScene(){
    // ---------------------------------------------------------------------
    // 场景和相机
    // ---------------------------------------------------------------------
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 100000);
    camera.position.set(1040, 250, 250 );
    camera.lookAt(0,0,0);
    // ---------------------------------------------------------------------
    // 辅助网格
    // ---------------------------------------------------------------------
    gridHelper = new THREE.GridHelper(12000, 20, 0x888888, 0x444444 );
    gridHelper.position.y = - 50;
    gridHelper.name = "Grid";
    scene.add(gridHelper);
    // ---------------------------------------------------------------------
    // 辅助坐标轴
    // ---------------------------------------------------------------------
    axes = new THREE.AxesHelper(50000);
    axes.name = "AxesHelper";
    scene.add(axes);



    //光源一定要添加,负责模型没有光 肯定是黑色
    var light = new THREE.DirectionalLight(0xffffff);//光源颜色
    light.position.set(20, 10, 1305);//光源位置
    scene.add(light);//光源添加到场景中
    // ---------------------------------------------------------------------
    // 渲染器
    // ---------------------------------------------------------------------
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    let controls = new OrbitControls(camera,renderer.domElement);
    controls.zoomSpeed=2.0;
    controls.rotateSpeed=2.0;
    animate();
    function animate() {
        requestAnimationFrame(animate);
        controls.update();
        renderer.render(scene, camera);

    }
}
                                            
                                        

第五步:初始化模型

                                            
let path="./statics/models/obj/IronMan/";
let objName="IronMan.obj";
let mtlName="IronMan.mtl";
initModel();
function initModel() {
    try{
        // 1 初始化纹理加载器
        var mtlLoader=new MTLLoader();
        // 2 设置mtl资源路径
        mtlLoader.resourcePath=path;
        mtlLoader.path=path;
        // 3 加载材质
        mtlLoader.load(mtlName,function(materials){
            materials.preload();
            // 4 加载模型
            var objLoader=new OBJLoader();
            objLoader.setMaterials(materials);
            objLoader.setPath(path);
            objLoader.load(objName,function(obj){
                obj.position.y=10;
                obj.scale.set(2, 2, 2);
                scene.add(obj);
            })
        })
    }catch(e){
        console.error('解析失败',e);
    }
    
}
                                            
                                        

这种方式添加纹理,简单规整;中间不需要去调整;能够将建模软件的模型一模一样在网页端显示即可

3 纹理方式(2):自定义模型材质

这种方式自由度比较高;可以对整个obj模型的子mesh元素设置材质;如下

情况1:给钢铁侠设置纯色材质

                                            
// 2 加载obj模型
    loader.load("./statics/models/obj/IronMan/IronMan.obj",function (loadedMesh) {
        var material = new THREE.MeshBasicMaterial({color:'red'});
        //obj模型是有无数个mesh子元素组成,所以我们可以对单个child的mesh进行操作
        loadedMesh.children.forEach(function (child,index) {
            child.material=material
            child.geometry.computeFaceNormals();
            child.geometry.computeVertexNormals();
        });
        //模型放大一倍
        loadedMesh.scale.set(1, 1, 1);
        scene.add(loadedMesh);
    });
                                            
                                        

/net/upload/image/20220526/feca9eea-7d10-4039-bd50-f6428eb42a8b.jpg

情况2:给钢铁侠设置图片纹理

                                            
// 2 加载obj模型
    loader.load("./statics/models/obj/IronMan/IronMan.obj",function (loadedMesh) {
        var material=new THREE.MeshBasicMaterial({
            map:new THREE.TextureLoader().load('./statics/imgs/floor.jpg'),
            side:THREE.DoubleSide
        });
        //obj模型是有无数个mesh子元素组成,所以我们可以对单个child的mesh进行操作
        loadedMesh.children.forEach(function (child,index) {
            child.material=material
            child.geometry.computeFaceNormals();
            child.geometry.computeVertexNormals();
        });
        //模型放大一倍
        loadedMesh.scale.set(1, 1, 1);
        scene.add(loadedMesh);
    });
                                            
                                        

/net/upload/image/20220526/6dcba9ff-69f5-49ff-a1f1-ffb282b4bdf1.jpg

情况3:给树模型设置图片纹理

/net/upload/image/20220526/26bb8e90-4fad-4692-91dc-05088a9c5f7b.jpg

情况4:给钢铁侠不同子元素设置不同纹理

                                            
// 2 加载obj模型
    loader.load("./statics/models/obj/IronMan/IronMan.obj",function (loadedMesh) {
        var material = new THREE.MeshBasicMaterial({color:'red'});
        var material1=new THREE.MeshBasicMaterial({
            map:new THREE.TextureLoader().load('./statics/imgs/floor.jpg'),
            side:THREE.DoubleSide
        });
        //obj模型是有无数个mesh子元素组成,所以我们可以对单个child的mesh进行操作
        loadedMesh.children.forEach(function (child,index) {
            if(index%2===0){
                child.material=material1
            }else{
                child.material=material
            }
            child.geometry.computeFaceNormals();
            child.geometry.computeVertexNormals();
        });
        //模型放大一倍
        loadedMesh.scale.set(1, 1, 1);
        scene.add(loadedMesh);
    });
                                            
                                        

/net/upload/image/20220526/5af084cc-96ec-45b9-b2a6-65bb83aca5b3.jpg

根据子mesh的奇偶索引顺序设置不同材质:这场景适合根据某些属性过滤设置材质

QQ:3410192267 | 技术支持 微信:popstarqqsmall

Copyright ©2017 xiaobaigis.com . 版权所有 鲁ICP备17027716号