ボーンアニメーションとは
ボーンアニメーションとは、
3Dツールで骨のように連なる軸を基準として
それに合わせてメッシュをアニメーションさせる技法のことを言います。
three.jsでは主にBlenderという3Dソフトからアニメーションつきのthree.js用の3Dモデルを書き出すことで用意することができます。
Unityのようなゲームエンジンと違い、three.jsではBlenderファイルを放り込んだらパースしてくれるような便利な機能はありません。
ここがもっとやりやすければthree.jsももっと流行りそうなものなのですが・・・
three.jsでボーンアニメーションさせるのに必要なもの
Blender
Blenderとはオープンソースの3Dソフトのことで、以下のサイトから無料でダウンロードできます。
Blenderの公式サイトへ
Blender three.jsエクスポーター
エクスポーターとは3Dソフトから three.jsで使用できる3Dモデルを書き出すためのプラグインのことです。
three.jsをダウンロードした際に解凍したファイルの以下のディレクトリにあります。
three.js-master\utils\exporters\blender\addons\io_three
three.jsから3Dモデルを書き出す順序
- 1.Blenderにエクスポーターをインストール
- 2.Blenderでアニメーションモデルを用意
- 3.Blenderからthree.js用のモデルを書き出す
- 4.three.jsのjsonLoaderで書き出したモデルを読み込み、アニメーションを再生する
1.Blenderにエクスポーターをインストール
エクスポーターをBlenderにインストール
上に書いたようにthree.jsをダウンロードしたときに入っている以下のエクスポーターを、
three.js-master\utils\exporters\blender\addons\io_three
(io_threeのフォルダリごと)以下のディレクトリに配置(2.78はBlenderのバージョンですので、インストールしているバージョンによってかわります)
C:\Program Files\Blender Foundation\Blender\2.78\scripts\addons
Blenderを起動し、エクスポーターを有効化する
Blenderを起動し、左下のボタンでエディターのウィンドウタイプをUser Preferencesに変更する。
次に以下の画像上部メニューから「Add-ons」を選び、左の検索窓に「three」を入力しEnter、「Import-Export: three.js format」横のチェックボックスを入れる。
この設定を保存する場合は、下の「Save User Settings」をクリックする。こうすることでBlenderを再度立ち上げてもthree.jsのエクスポーターが有効化された状態になります。
これでthree.jsエクスポーターのインストールがされました。
2.Blenderでアニメーションモデルを用意
次にBlenderでアニメーションモデルを用意します。今回は割合します。
注意として、以下を気をつけてモデリングしてください。
書き出しエラーになったり、思ったとおりのアニメーションにならなかったり、やたら大きなサイズで書き出されてしまったり、やたら動作が重くなってしまう原因になります。
- 一つのArmatureに一つのメッシュ
- 原点は必ずx:0 y:0 z:0の位置にする
- 3DモデルのサイズはBlenderの升目以内に入るサイズにする
- ポリゴン数は5万以内程度
- IKは書き出し時に無視される
- 必ず頂点を取りこぼすことなくウェイトペイントすること
3.Blenderからthree.js用のモデルを書き出す
いよいよBlenderから3Dモデルを書き出します。
注意点としては・・・
ClearTransformする
PoseModeでボーン全てを選択後、以下の画像のようにPose→ClearTransform→Allを実行します
この工程は地味ですが、これをやらないとアニメーションがハチャメチャになることがあります。
書き出し時にObjectModeにしてメッシュを選択すること
これをやらないとエラーがでることがあります。
注意事項を読んだら早速書き出しましょう
書き出す
File→Export→Three(.json)をクリックして書き出しましょう。
書き出し設定は以下のとおりです。
※three.jsのエクスポーターはr73バージョン以降とそれ以前では違いがあります。
r73以前
r73以降
4.three.jsのjsonLoaderで書き出したモデルを読み込み、アニメーションを再生する
r73以前とr73以降ではアニメーションの実行の仕方が大幅に違い、ここが大いにはまるポイントだったりします。
r73以前
animationsというオブジェクトにアニメーションデータを格納し、play関数でアニメーションの再生をしています。
毎フレーム処理の中でTHREE.AnimationHandler.update関数を実行する必要があります。
var mesh;
var animations = {};
var jsonLoader = new THREE.JSONLoader();
var url = 'models/hellknight/hellknight.json';
jsonLoader.load(url, function( geometry, materials ){
var material = new THREE.MeshFaceMaterial( materials );
mesh = new THREE.SkinnedMesh( geometry, material );
animations[ 'animName0' ] = new THREE.Animation( mesh, geometry.animations[0] );
animations[ 'animName1' ] = new THREE.Animation( mesh, geometry.animations[1] );
animations[ 'animName0' ].play();
});
//毎フレーム処理
function animate() {
if( mesh ){
THREE.AnimationHandler.update( .03 );
}
}
setInterval( animate, 1000 / 30 );
r73以降
r73以降ではTHREE.Animationクラスが廃止され、THREE.AnimationMixerに変更されました。setEffectiveWeightはアニメーションを2つ同時に再生した場合に2つのアニメーションをどのぐらいのブレンド具合で混ぜるかを設定します。
こちらも毎フレーム処理でanimationMixer.update関数を実行する必要があります。
var clock = new THREE.Clock();
var mesh;
var animationMixer;
var jsonLoader = new THREE.JSONLoader();
var url = 'models/hellknight/hellknight.json';
jsonLoader.load(url, function( geometry, materials ){
var material = new THREE.MeshFaceMaterial( materials );
mesh = new THREE.SkinnedMesh( geometry, material );
animationMixer = new THREE.AnimationMixer( mesh );
for ( var i = 0; i < geometry.animations.length; ++ i ) {
animationMixer.clipAction( geometry.animations[ i ] );
}
animationMixer.clipAction( 'animName0' ).setEffectiveWeight( 1 ).play();
});
//毎フレーム処理
function animate() {
var delta = clock.getDelta();
if( animationMixer ){
animationMixer.update( delta );
}
}
setInterval( animate, 1000 / 30 );
編集後記
three.jsでのアニメーション再生の流れをざっと説明しました。如何でしたでしょうか。おそらく多くの人がつまづくのはBlenderとthree.jsの連携だと思います。
今までhtmlやjavaScriptだけ書いていればよかったのが、急に3Dソフトを使う必要があり、しかもそれが癖のあるBlenderとなれば少し躊躇してしまうかもしれません。
しかし、three.jsはwebGLのコードを直接書くのに比べかなり簡略化されており、それに比べればかなり楽にはなっているとは思います(シェーダーも触る必要がありませんし・・・)
3Dコンテンツを作る以上、3Dソフトとの連携はUnityなどの環境でも必ず必要になっているので、やっといて損はないかと
さくっと説明するつもりがかなり長くなってしまった・・・