Skip to content

一、 解析外部模型变形动画目标数据

1. 加载查看模型变形动画数据

  • 加载完三维模型后,通过console.log(geometry.morphTargets)可以在浏览器控制台查看模型的变形数据。
javascript
// 通过加载器JSONLoader加载变形动画模型文件./人/umich_ucs.json
const loader = new THREE.JSONLoader();
loader.load("./人/umich_ucs.json", function(geometry, materials) {
  // console.log(geometry);
  // console.log(materials);
  // 通过平均面法线来计算顶点法线,效果更光滑
  geometry.computeVertexNormals();
  const mesh = new THREE.Mesh(geometry, materials[0]);
  // 材质对象开启渲染目标
  mesh.material.morphTargets = true
  mesh.rotateX(-Math.PI / 2);
  mesh.position.y = -50;
  scene.add(mesh); //插入到场景中
  // 查看变形目标数据
  console.log(geometry.morphTargets);
})
  • 可以在代码中给网格模型的.morphTargetInfluences属性赋予不同的值,测试人的胖瘦变化。
    javascript
      // 变胖
      mesh.morphTargetInfluences[0] = 1;
    javascript
      // 变瘦
      mesh.morphTargetInfluences[4] = 1;

2. 滚动条调节人胖瘦

skin-04.gif

vue
<div id="app">
  <div class="block" style="display:inline;width:500px">
    <el-slider v-model="time" show-input :max=1 :step=0.01></el-slider>
  </div>
</div>
  • 通过vue.js把网格模型Mesh.morphTargetInfluences属性和滚动条进行绑定, 只要滚动条改变就可以同步改变mesh.morphTargetInfluences属性值, mesh.morphTargetInfluences属性值改变,人的胖瘦自然跟着改变。
    javascript
    const loader = new THREE.JSONLoader(); //创建加载器
    loader.load("./人/umich_ucs.json", function(geometry, materials) {
      // 通过平均面法线来计算顶点法线,效果更光滑
      geometry.computeVertexNormals();
      const mesh = new THREE.Mesh(geometry, materials[0]);
      // 材质对象开启渲染目标
      mesh.material.morphTargets = true
      mesh.rotateX(-Math.PI / 2);
      mesh.position.y = -50;
      scene.add(mesh); //插入到场景中
      //实例化vue
      vm = new Vue({
        el: "#app",
        data: {
          time: 0,
        },
        watch: {
          time: function(value) {
            mesh.morphTargetInfluences[0] = value; // 变胖
            // mesh.morphTargetInfluences[4] = value; // 变瘦
          }
        },
      })
    })

3. 鸟飞行变形动画

skin-05.gif

  • 通过混合器AnimationMixer获取模型中的变形动画关键帧数据然后进行播放。
javascript
const loader = new THREE.JSONLoader(); //创建加载器
const mixer = null; //声明一个混合器变量
loader.load("./鸟/flamingo.json", function(geometry) {
  // console.log(geometry);
  const material = new THREE.MeshPhongMaterial({
    morphTargets: true,
    vertexColors: THREE.FaceColors,
  });
  // 通过平均面法线来计算顶点法线,效果更光滑
  geometry.computeVertexNormals();
  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh); //插入到场景中
  // 创建一个混合器,播放网格模型模型的变形动画
  mixer = new THREE.AnimationMixer(mesh);
  // geometry.animations[0]:获得剪辑对象clip
  const AnimationAction=mixer.clipAction(geometry.animations[0]);
  // AnimationAction.timeScale = 0.5; //默认1,可以调节播放速度
  // AnimationAction.loop = THREE.LoopOnce; //不循环播放
  // AnimationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
  AnimationAction.play();//播放动画
})
  • 在渲染函数中,通过时钟类Clock获得两次渲染的时间间隔, 然后执行mixer.update();传递给混合器AnimationMixer
    javascript
    // 创建一个时钟对象Clock
    const clock = new THREE.Clock();
    // 渲染函数
    function render() {
      renderer.render(scene, camera); //执行渲染操作
      requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
      //clock.getDelta()方法获得两帧的时间间隔
      // 更新混合器相关的时间
      mixer.update(clock.getDelta());
    }
    render();

Released under the MIT License.