Three 之 Animation 初印象

Animation 初印象

動畫效果

animation1

播放動畫需要基本元素

AnimationMixer

一個對象所有動作的管理者

用於場景中特定對象的動畫的播放器。一個對象可能有多個動作,Mixer 是用來管理所有動作的,它可以調度出對象的某個動作進行操控,如 mixer = new THREE.AnimationMixer(obj); mixer 就能管理 obj 對象的所有動畫了。擁有 mixer 後,在 animate 函數中進行更新操作,用於更新該對象目前的狀態。 mixer 可以讓這個對象同時播放多個動作,因此需要在每幀中執行 update 方法

AnimationClip

一個對象的一個動作

動畫剪輯(AnimationClip)是一個可重用的關鍵幀軌道集,它代表動畫。

AnimationAction

用來管理單個動作,讓這個動作開始暫停等等

AnimationActions 用來調度存儲在 AnimationClips 中的動畫。說明: AnimationAction的大多數方法都可以鏈式調用

使用方法

  1. 載入一個對象,載入這個對象對應的 mixer 用於管理所有動作

mixer = new THREE.AnimationMixer(obj);

  1. 載入出一個 action,用於處理單個(clip)動畫集,並進行播放

mixer.clipAction(obj.animations[0]).play();

上文提到過 action 是可以鏈式操作了,clipAction 方法返回一個 action 對象

  1. 在每一幀中更新對象的狀態

mixer.update(delta);

實際程式碼

export function AnimationCommin() {
  const content = useRef();

  const scene = new THREE.Scene();
  scene.background = new THREE.Color(0xbfe3dd);
  const pointLight = new THREE.PointLight(0xffffff, 0.6);
  pointLight.position.set(150, 150, 150);
  scene.add(pointLight);
  scene.add(new THREE.AmbientLight(0xffffff, 2));
  const clock = new THREE.Clock();

  let mixer;

  useEffect(() => {
    const canvas = content.current;
    const renderer = new THREE.WebGLRenderer({ antialias: true, canvas });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(canvas.clientWidth, canvas.clientHeight);

    const stats = new Stats();
    canvas.appendChild(stats.dom);

    const camera = new THREE.PerspectiveCamera(
      40,
      canvas.clientWidth / canvas.clientHeight,
      1,
      1000
    );
    camera.position.set(200, 200, 200);

    const controls = new OrbitControls(camera, canvas);
    controls.update();

    const loader = new FBXLoader();
    loader.load("/RumbaDancing.fbx", (obj) => {
      scene.add(obj);

      mixer = new THREE.AnimationMixer(obj);
      mixer.clipAction(obj.animations[0]).play();
    });

    animate();

    function animate() {
      requestAnimationFrame(animate);

      const delta = clock.getDelta();

      if (mixer) mixer.update(delta);

      controls.update();

      stats.update();

      renderer.render(scene, camera);
    }
  });
  return <canvas ref={content} />;
}

Tags: