Three.js 對模型多個動畫切換展現(fbx)

來源 :https://blog.csdn.net/qq_30100043/article/details/80087471javascript

簡介

上一節本想直接告終動畫這一章。最後一想,沒有作過模型動畫切換的案例。就此,再加一章,關於模型多個動畫之間如何切換的問題。css

案例實現

案例查看地址:http://www.wjceo.com/blog/threejs/2018-04-25/153.htmlhtml

首先,咱們須要先將模型導入,以前案例已經講過如何導入,這裏就不贅述。java

//加載模型
var loader = new THREE.FBXLoader(); loader.load("/lib/models/fbx/Naruto.fbx", function (mesh) { mesh.position.y += 100; scene.add(mesh); });
 
 

導入模型之後,咱們須要查看當前模型的動畫的長度,也就是mesh.animations的長度,若是隻有一個長度,表明只有一個動畫,若是有多個,就是多個動畫的模型。而後咱們須要遍歷mesh.animations數組,爲每一個動畫建立一個action,做爲後面調用:web

mixer = mesh.mixer = new THREE.AnimationMixer(mesh); var actions = []; //全部的動畫數組
for(var i=0; i<mesh.animations.length; i++){ actions[i] = mixer.clipAction(mesh.animations[i]); }

 

在切換動畫的時候,咱們須要作的就是,將當前的全部的action除去須要播放的那個action所有暫停動畫播放,讓須要播放的哪個動畫調用play()事件:canvas

gui["action"+i] = function () { for(var j=0; j<actions.length; j++){ if(j === i){ actions[j].play(); } else{ actions[j].stop(); } } }; animations.add(gui, "action"+i);

 

這樣,咱們就實現了對模型的動畫切換。數組

案例代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css"> html, body { margin: 0; height: 100%; } canvas { display: block; } </style>
</head>

<body onload="draw();">
</body>
<script src="https://cdn.bootcss.com/three.js/91/three.min.js"></script>
<script src="/lib/js/libs/inflate.min.js"></script>
<script src="/lib/js/loaders/FBXLoader.js"></script>
<script src="/lib/js/controls/OrbitControls.js"></script>
<script src="https://cdn.bootcss.com/stats.js/r17/Stats.min.js"></script>
<script src="https://cdn.bootcss.com/dat-gui/0.7.1/dat.gui.min.js"></script>
<script src="/lib/js/Detector.js"></script>

<script>
    var renderer, camera, scene, gui, light, stats, controls, meshHelper, mixer, action,datGui; var clock = new THREE.Clock(); function initRender() { renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0xeeeeee); renderer.shadowMap.enabled = true; //告訴渲染器須要陰影效果
 document.body.appendChild(renderer.domElement); } function initCamera() { camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000); camera.position.set(100, 200, 300 ); } function initScene() { scene = new THREE.Scene(); scene.background = new THREE.Color( 0xa0a0a0 ); scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 ); } //初始化dat.GUI簡化試驗流程
    function initGui() { //聲明一個保存需求修改的相關數據的對象
        gui = { helper:true //模型輔助線
 }; datGui = new dat.GUI(); //將設置屬性添加到gui當中,gui.add(對象,屬性,最小值,最大值)
 datGui.add(gui, "helper").onChange(function (e) { meshHelper.visible = e; }) } function initLight() { scene.add(new THREE.AmbientLight(0x444444)); light = new THREE.DirectionalLight(0xffffff); light.position.set(0, 200, 100 ); light.castShadow = true; light.shadow.camera.top = 180; light.shadow.camera.bottom = -100; light.shadow.camera.left = -120; light.shadow.camera.right = 120; //告訴平行光須要開啓陰影投射
        light.castShadow = true; scene.add(light); } function initModel() { //輔助工具
        var helper = new THREE.AxesHelper(50); scene.add(helper); // 地板
        var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0xffffff, depthWrite: false } ) ); mesh.rotation.x = - Math.PI / 2; mesh.receiveShadow = true; scene.add( mesh ); //添加地板割線
        var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 ); grid.material.opacity = 0.2; grid.material.transparent = true; scene.add( grid ); //加載模型
        var loader = new THREE.FBXLoader(); loader.load("/lib/models/fbx/Naruto.fbx", function (mesh) { console.log(mesh); //添加骨骼輔助
            meshHelper = new THREE.SkeletonHelper(mesh); scene.add(meshHelper); //設置模型的每一個部位均可以投影
            mesh.traverse( function ( child ) { if ( child.isMesh ) { child.castShadow = true; child.receiveShadow = true; } } ); //AnimationMixer是場景中特定對象的動畫播放器。當場景中的多個對象獨立動畫時,能夠爲每一個對象使用一個AnimationMixer
            mixer = mesh.mixer = new THREE.AnimationMixer(mesh); //mixer.clipAction 返回一個能夠控制動畫的AnimationAction對象 參數須要一個AnimationClip 對象
            //AnimationAction.setDuration 設置一個循環所須要的時間,當前設置了一秒
            //告訴AnimationAction啓動該動做
            //action = mixer.clipAction(mesh.animations[0]);
            //action.play();

            var actions = []; //全部的動畫數組
            var animations = datGui.addFolder("animations"); for(var i=0; i<mesh.animations.length; i++){ createAction(i); } function createAction(i){ actions[i] = mixer.clipAction(mesh.animations[i]); gui["action"+i] = function () { for(var j=0; j<actions.length; j++){ if(j === i){ actions[j].play(); } else{ actions[j].stop(); } } }; animations.add(gui, "action"+i); } //添加暫停全部動畫的按鍵
            gui.stop = function(){ for(var i=0; i<actions.length; i++){ actions[i].stop(); } }; datGui.add(gui, "stop"); mesh.position.y += 100; scene.add(mesh); }); } //初始化性能插件
    function initStats() { stats = new Stats(); document.body.appendChild(stats.dom); } function initControls() { controls = new THREE.OrbitControls(camera, renderer.domElement); //設置控制器的中心點
        //controls.target.set( 0, 100, 0 );
        // 若是使用animate方法時,將此函數刪除
        //controls.addEventListener( 'change', render );
        // 使動畫循環使用時阻尼或自轉 意思是否有慣性
        controls.enableDamping = true; //動態阻尼係數 就是鼠標拖拽旋轉靈敏度
        //controls.dampingFactor = 0.25;
        //是否能夠縮放
        controls.enableZoom = true; //是否自動旋轉
        controls.autoRotate = false; controls.autoRotateSpeed = 0.5; //設置相機距離原點的最遠距離
        controls.minDistance = 1; //設置相機距離原點的最遠距離
        controls.maxDistance = 2000; //是否開啓右鍵拖拽
        controls.enablePan = true; } function render() { var time = clock.getDelta(); if (mixer) { mixer.update(time); } controls.update(); } //窗口變更觸發的函數
    function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function animate() { //更新控制器
 render(); //更新性能插件
 stats.update(); renderer.render(scene, camera); requestAnimationFrame(animate); } function draw() { //兼容性判斷
        if (!Detector.webgl) Detector.addGetWebGLMessage(); initGui(); initRender(); initScene(); initCamera(); initLight(); initModel(); initControls(); initStats(); animate(); window.onresize = onWindowResize; } </script>
</html>
相關文章
相關標籤/搜索