天天看點

使用threejs實作模型爆炸效果

使用threejs實作模型爆炸效果

這個效果是以mesh為機關進行位置偏移,具體代碼如下:

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>modelLoader</title>
</head>
<style>
    body {
        color: #000;
        font-family:Monospace;
        font-size:13px;
        text-align:center;
        font-weight: bold;

        background-color: #fff;
        margin: 0px;
        overflow: hidden;
    }
</style>
<body>
<input type="range" min="0" max="100" value="0" class="slider" id="myRange" style="position: absolute; top: 0; width: 350px">

<script src="../libs/three.js"></script>
<script src="../libs/OrbitControls.js"></script>


<script>

    let camera, controls, scene, renderer;

    //模型包圍盒
    var modelBox3 = new THREE.Box3();

    var meshBox3 = new THREE.Box3();


    init();
    //render(); // remove when using next line for animation loop (requestAnimationFrame)
    animate();

    function init() {

        scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xcccccc );
        //scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );

        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );

        camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000000 );
        camera.position.set( -112417.55771430256, 64121.59264444466, 23940.856823256017 );
        camera.rotation.set( -1.2178822080031084, -0.9004236436148543, -1.1313862615404136 );

        // controls

        controls = new THREE.OrbitControls( camera, renderer.domElement );

        controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
        controls.dampingFactor = 0.25;

        controls.screenSpacePanning = false;

        controls.maxPolarAngle = Math.PI / 2;

        window.addEventListener( 'resize', onWindowResize, false );

        hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.6 );
        hemiLight.color.setHSL( 0.6, 1, 0.6 );
        hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
        hemiLight.position.set( 0, 50, 0 );
        scene.add( hemiLight );

        var ambient = new THREE.AmbientLight(0x9a9a9a );
        scene.add(ambient);

        var light = new THREE.DirectionalLight( 0xFFFFFF, 1.0 );
        light.position.set( 1, 0.5, 0.8 );

        hemiLightHelper = new THREE.HemisphereLightHelper( hemiLight, 10 );
        scene.add( hemiLightHelper );

        var loader = new THREE.ObjectLoader();

        loader.load(
            "../model/rac_advanced_sample_project.rvt.json",
            function ( obj ) {
                scene.add( obj );

                //擷取模型的包圍盒
                modelBox3.expandByObject(obj);

                //計算模型的中心點坐标,這個為爆炸中心
                var modelWorldPs = new THREE.Vector3().addVectors(modelBox3.max, modelBox3.min).multiplyScalar(0.5);

                obj.traverse(function (value) {
                    if(value.isMesh){
                        meshBox3.setFromObject(value);

                        //擷取每個mesh的中心點,爆炸方向為爆炸中心點指向mesh中心點
                        var worldPs = new THREE.Vector3().addVectors(meshBox3.max, meshBox3.min).multiplyScalar(0.5);
                        if(isNaN(worldPs.x))return;
                        //計算爆炸方向
                        value.worldDir = new THREE.Vector3().subVectors(worldPs, modelWorldPs).normalize();
                        //儲存初始坐标
                        value.userData.oldPs = value.getWorldPosition(new THREE.Vector3())
                    }
                });

                function applyScalar(scalar){

                    obj.traverse(function (value) {
                        if(!value.isMesh || !value.worldDir) return;

                        //爆炸公式
                        value.position.copy(new THREE.Vector3().copy(value.userData.oldPs).add(new THREE.Vector3().copy(value.worldDir).multiplyScalar(scalar)))
                    });

                }

                document.querySelector("#myRange").addEventListener('input', function (evt) {
                    applyScalar(this.value * 500)
                })
            }
        );
        var axesHelper = new THREE.AxesHelper( 500000 );
        scene.add( axesHelper );
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
    }

    function animate() {
        requestAnimationFrame( animate );
        controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
        render();
    }

    function render() {
        renderer.render( scene, camera );
    }
</script>
</body>
</html>
           

運作效果如下:

使用threejs實作模型爆炸效果

繼續閱讀