已被阅读 4248 次 | 文章分类:javascript | 2022-05-29 20:42
threejs实现模型炸开的效果
1 效果如下
                                                     
                                                
                                                     
                                                
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)
    }
                                            
                                        
                                                
                                                     
                                                
QQ:3410192267 | 技术支持 微信:popstarqqsmall
Copyright ©2017 xiaobaigis.com . 版权所有 鲁ICP备17027716号