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>
相关文章
相关标签/搜索