アニメーションブレンディング
babylon-mmdは、フレーム完璧なアニメーションブレンディングをサポートするMmdCompositeAnimationアニメーションコンテナを提供します。
babylon-mmdはframe perfectなアニメーションブレンディングを提供するようになりました
ユーザーの入力によってダンスの次の内容を変更することが可能で、正確なタイミングを決めることができるので、リズムゲームを取り入れたQTEアニメーションコンテンツを作ることができると思われます。 pic.twitter.com/ZCRZU9YVMW
— noname0310 (@noname20310)
November 14, 2023
このビデオは、Composite Animationを使用して2人用のダンスアニメーションを1つのMMDモデルで交互に再生する例を示しています。
クレジット:
- モデル:
- YYB Hatsune Miku_10th by YYB
- YYB Miku Default edit by YYB / HB-Squiddy / FreezyChan-3Dreams
- YYB miku Crown Knight by YYB / Pilou la baka
- モーション by srs / ATY
- カメラ by 小紋
- ミュージック:
- 君にとって by Wonder-K
Babylon.jsのAnimationGroupでMMDアニメーションを再生することにより、Babylon.jsのアニメーションブレンディング機能も使用できます。
ただし、このセクションではAnimationGroupについては説明しません。AnimationGroupを使用してMMDアニメーションを再生する方法については、Use Babylon.js Animation Runtimeドキュメントを参照してください。
MMD Composite Animation
MmdCompositeAnimationは、複数のMMD Animationを1つとしてバンドルして管理するアニメーションコンテナです。
各アニメーションは、開始フレームと終了フレームの情報を含むMmdAnimationSpanオブジェクトとして管理されます。
以下は、2つのMmdAnimationオブジェクトを1つのMmdCompositeAnimationにバンドルするサンプルコードです:
const compositeAnimation = new MmdCompositeAnimation("composite");
const duration = Math.max(mmdAnimation1.endFrame, mmdAnimation2.endFrame);
const animationSpan1 = new MmdAnimationSpan(mmdAnimation1, undefined, duration, 0, 1);
const animationSpan2 = new MmdAnimationSpan(mmdAnimation2, undefined, duration, 0, 1);
compositeAnimation.addSpan(animationSpan1);
compositeAnimation.addSpan(animationSpan2);
この場合、両方のアニメーションがフレーム0から開始し、durationフレームまで再生されます。
MMD Animation Span
MmdAnimationSpanコンストラクタは以下の通りです:
new MmdAnimationSpan(animation: MmdBindableAnimation, startFrame?: number, endFrame?: number, offset?: number, weight?: number): MmdAnimationSpan
animation:MmdAnimationやMmdModelAnimationContainerなど、カメラやモデルにバインド可能なアニメーションコンテナstartFrame:アニメーションが開始するフレーム(デフォルト:animation.startFrame)endFrame:アニメーションが終了するフレーム(デフォルト:animation.endFrame)offset:このSpanがComposite Animationで開始するフレーム(デフォルト:0)weight:アニメーションブレンディングに使用される重み(デフォルト:1)
MmdCompositeAnimationは複数のAnimationSpanオブジェクトを管理し、各AnimationSpanはアニメーション再生中に動的に追加または削除できます。
MMD Composite Animationメソッド
MmdCompositeAnimationクラスは以下のメソッドを提供します:
addSpan(span: MmdAnimationSpan): void:MmdAnimationSpanを追加します。removeSpan(span: MmdAnimationSpan): void:MmdAnimationSpanを削除します。removeSpanFromIndex(index: number): void:インデックスでMmdAnimationSpanを削除します。get startFrame(): number:このComposite Animationの開始フレームを返します。get endFrame(): number:このComposite Animationの終了フレームを返します。get spans(): readonly MmdAnimationSpan[]:現在登録されているすべてのMmdAnimationSpanオブジェクトを返します。
MMD Animation Spanトランジション
MmdAnimationSpanは、weightプロパティを通じてアニメーションブレンディングに使用される重みを設定できます。さらに、MmdAnimationSpanの開始と終了にtransitionフレームを設定して、アニメーション開始時に重みが0から1に、または終了時に1から0に変化することをスムーズに制御する便利機能が提供されています。
この目的のために、MmdAnimationSpanクラスは以下のプロパティを提供します:
MmdAnimationSpan.easeInFrameTime:アニメーション開始時に重みが0から1に変化するフレーム数を設定します。MmdAnimationSpan.easeOutFrameTime:アニメーション終了時に重みが1から0に変化するフレーム数を設定します。MmdAnimationSpan.easingFunction:重み変化に使用されるイージング関数を設定します。デフォルトはnullで、この場合線形変化が適用されます。
例えば、MMDアニメーションは30fpsで再生されるため、easeInFrameTimeとeaseOutFrameTimeの両方を30に設定すると、アニメーション開始時と終了時にそれぞれ1秒間重みが変化します。
以下は、easeInFrameTimeとeaseOutFrameTimeの両方を30に設定してトランジションを適用するサンプルコードです:
const animationSpan = new MmdAnimationSpan(mmdAnimation1);
animationSpan.easeInFrameTime = 30;
animationSpan.easeOutFrameTime = 30;
const easingFunction = new BezierCurveEase(0.7, 0.01, 0.3, 0.99);
animationSpan.easingFunction = easingFunction;
compositeAnimation.addSpan(animationSpan);
MMD Composite Runtime Animation
MmdCompositeAnimationも、他のMMDアニメーションコンテナと同様にMmdCameraやMmdModelにバインディングして使用できます。バインディングのために、アニメーション評価とバインディングを担当するランタイムをインポートする必要があります。
import "babylon-mmd/esm/Runtime/Animation/mmdCompositeRuntimeCameraAnimation";
import "babylon-mmd/esm/Runtime/Animation/mmdCompositeRuntimeModelAnimation";
その後、MmdCameraやMmdModelのcreateRuntimeAnimationメソッドを使用してMmdCompositeAnimationをバインディングできます。
const camera: MmdCamera = ...;
const model: MmdModel = ...;
const compositeAnimationHandle: MmdRuntimeAnimationHandle = camera.createRuntimeAnimation(compositeAnimation);
const compositeAnimationHandle: MmdRuntimeAnimationHandle = model.createRuntimeAnimation(compositeAnimation);
制限事項
MMD Composite Animationは、複数のアニメーションをブレンディングする際に、プロパティパスから評価結果に直接アクセスしてそれらを読み書きします。
そのため、MmdWasmRuntimeが提供するWASM側でのアニメーション評価など、アニメーション評価とプロパティへの実際の適用の間に遅延がある機能とは互換性がありません。
例えば、MmdWasmRuntimeModelAnimationを使用してMmdWasmAnimationを評価し、WASM側でアニメーション評価を実行する場合、MmdCompositeAnimationとのブレンディングはサポートされません。
代わりに、MmdRuntimeModelAnimationを使用してMmdWasmAnimationを評価する場合、MmdCompositeAnimationとのブレンディングは可能です。
サンプルコード
サンプルコードはcompositeAnimationTestScene.tsで確認できます。
このサンプルコードでは、UIを通じて重みを調整でき、静的に設定されたフレーム番号に従って2つのアニメーションが交互に再生される様子を見ることができます。