13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Three.jsAdvent Calendar 2019

Day 20

Three.jsを用いたモデルのアニメーション切り替えを簡単にした話

Last updated at Posted at 2019-12-20

この記事は、Three.js Advent Calendar 2019 20日目の記事です。

Kapture 2019-12-21 at 2.23.03.gif

AnimationMixerが扱いづらい :smiling_imp:

Three.js内でglTFなどを読み込んでアニメーションさせる場合、AnimationMixerを使用して徐々にモーションが変わるようにするには以下のようなコードを書くことになります。

const loader = new THREE.GLTFLoader();
loader.load('assets/zensuke.gltf', (gltf) {
  scene.add(gltf.scene)
  const mixer = new THREE.AnimationMixer(gltf.scene)
  const actionA = mixer.clipAction(gltf.animations[0])
  const actionB = mixer.clipAction(gltf.animations[1])
  let actionAWeight = 0
  let actionBWeight = 1
  mixer.play()

  function tick() {
    requestAnimationFrame(tick);
    
    // ↓適当です。AとBのWeightが入替わるような処理
    actionAWeight += 0.01
    actionBWeight -= 0.01

    // ...省略...

    actionA.setEffectiveWeight(actionAWeight)
    actionB.setEffectiveWeight(actionBWeight)
    
    renderer.render(scene, camera);
  }
})

各Actionのweightを調整するために冗長でとてもわかりにくいコードに仕上がりました。厳密にweightのバリデーションを追加するともっと複雑になります。

もっと簡潔にアニメーションを切り替えたい :pray:

上のような面倒をしなくてもなめらかにモーションが切り替わってくれるだけでいいので、以下の3点だけ指定すればアニメーションが切り替わるようなツールが欲しい。。。 :cry:

  • 次のアニメーション名
  • 切り替わりにかかる時間
  • ループするかどうか

また作ってみました

ということで utsuroi というツールを作ってみました。

簡単な使用例

import { Manipulator } from 'utsuroi'
 
let manipulator;
 
// Load asset
var loader = new THREE.GLTFLoader();
loader.load('assets/model.gltf', (gltf) {
  scene.add(gltf.scene)

  // アニメーションの操作者を作成
  manipulator = new Manipulator(gltf.scene, gltf.animations); 

  // 初期状態として再生したいアニメーション名を指定
  manipulator.play('Rest Pose', true);
});

毎フレームに update メソッドを実行することを忘れないでください

function tick() {
  requestAnimationFrame(tick);
  manipulator.update(); // これをしないとweightの更新がされない
}

tick();

アニメーションを切り替える

glTFに含まれているアニメーション名を指定することで切り替えられます

// manipulator.to('アニメーション名', 切り替えにかかる時間ms, ループするか否か);
manipulator.to('Walk', 200, true);

アニメーションを止める

manipulator.pause();

ちなみにBlenderからglTF書き出した時の設定はは以下になります。NLAスタックに登録がされていないと gltf.animations にアニメーション情報が入ってこないので注意です。

スクリーンショット 2019-12-21 1.37.32.png

まとめ

とてもシンプルになり簡単に切り替えが可能になりました。アニメーションに特にこだわりが無い方や、とりあえずアニメーションを確認したい方におすすめです。ぜひ使ってみてください :smile:

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?