【threejs效果:模型炸开】以钢铁侠obj模型为例

已被阅读 3095 次 | 文章分类:javascript | 2022-05-29 20:42

threejs实现模型炸开的效果

1 效果如下

/net/upload/image/20220529/99ad8512bc5d49948a005ac8d1b27068.png

/net/upload/image/20220529/6412e89b94174e14a9fe542d03fa520a.png

2 基本原理

首先加载一个obj模型;然后遍历obj模型的所有children mesh;按一定比例改变每个子mesh的中心点位置即可;

爆炸代码:

                                            
function modelExplode(num){
        // 模型世界中心
        var modelWorldCenter=new THREE.Vector3(0,0,0);//.addVectors(box.max,box.min).multiplyScalar(0.5);//模型中心坐标
        // 定义盒子
        var childBox=new THREE.Box3();
        // 遍历场景所有元素
        scene.traverse(function(child){
            // 如果元素是mesh
            if(child.isMesh){
                childBox.setFromObject(child);
                debugger;
                var childCenter=new THREE.Vector3().addVectors(childBox.max,childBox.min).multiplyScalar(0.5);
                if(isNaN(childCenter.x))return;
                child.childCenter=new THREE.Vector3().subVectors(childCenter,modelWorldCenter).normalize();
                if(!child.isMesh || !child.childCenter) return;
                // 爆炸公式:更改mesh位置
                child.position.copy(child.childCenter).multiplyScalar(num);
            }
        });
    }
                                            
                                        

3 全部代码

                                            
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(1940, 650, 850 );
    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);
    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 指定材质的资源路径
            mtlLoader.resourcePath=path;
            mtlLoader.path=path;
            // 3 加载材质文件
            mtlLoader.load(mtlName,function(materials){
                // 材质预加载
                materials.preload();
                // 4 定义 obj加载器
                var objLoader=new OBJLoader();
                // 5 设置 材质
                objLoader.setMaterials(materials);
                // 6 设置 obj模型资源路径
                objLoader.setPath(path);
                // 7 加载 obj模型文件
                objLoader.load(objName,function(obj){
                    console.log("obj.children",obj.children)
                    obj.position.y=10;
                    obj.scale.set(10, 10, 10);
                    scene.add(obj);
                    modelExplode(200)
                })
                
            })
        }catch(e){
            console.error('解析失败',e);
        }
        
    }
    function modelExplode(num){
        // 模型世界中心
        var modelWorldCenter=new THREE.Vector3(0,0,0);//.addVectors(box.max,box.min).multiplyScalar(0.5);//模型中心坐标
        // 定义盒子
        var childBox=new THREE.Box3();
        // 遍历场景所有元素
        scene.traverse(function(child){
            // 如果元素是mesh
            if(child.isMesh){
                childBox.setFromObject(child);
                debugger;
                var childCenter=new THREE.Vector3().addVectors(childBox.max,childBox.min).multiplyScalar(0.5);
                if(isNaN(childCenter.x))return;
                child.childCenter=new THREE.Vector3().subVectors(childCenter,modelWorldCenter).normalize();
                if(!child.isMesh || !child.childCenter) return;
                // 爆炸公式:更改mesh位置
                child.position.copy(child.childCenter).multiplyScalar(num);
            }
        });
    }
                                            
                                        

亦可以根据range滑动条交互的方式,改变爆炸的幅度

                                            
let scaleDom=document.getElementById('scale');
    scaleDom.ondragend=function(num){
        modelExplode(scaleDom.value)
    }
                                            
                                        

/net/upload/image/20220529/5f9d4dc1-cacc-42cc-8af1-7efad874232c.gif

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

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