Avaturn アバターに Mixamo 歩行アニメーションをリターゲット:Blender CLI から Three.js ランタイムまで
写真から作った Avaturn アバター(GLB)に Mixamo の歩行アニメーションを適用する方法を3段階で解説。Blender 5.0 CLI での変換、Node.js での比較検証、Three.js ランタイムでのブラウザ完結型リターゲットまで、試行錯誤の記録。
threejsjavascriptblendermixamovrreact-three-fiber3d
台本(フルテキスト)
動画の掛け合いを書き起こしたものです。音声を再生しづらい場合はこちらをお読みください。
オープニング
- Avaturn アバターに Mixamo 歩行アニメーションをリターゲット
- Blender CLI・Node.js・Three.js の 3 段階で解説
- はう
- こんにちは。今日は Avaturn アバターに Mixamo のアニメーションを適用する話を教えてもらいます。
- めたん
- はい。写真から作った Avaturn のアバターに歩行アニメーションを付けるため、Mixamo のアニメーションをリターゲットした記録です。
- はう
- Avaturn のアバターには歩行アニメーションが付いていないんですか?
- めたん
- 待機の Idle アニメーションは付いていますが、歩行は含まれていません。VR 空間で歩かせるには別途用意する必要があります。
- はう
- リターゲットというのは何ですか?
- めたん
- あるキャラクター向けに作られたアニメーションを、別のキャラクターに適用し直すことです。Avaturn と Mixamo は同じ Humanoid 骨格を使いますが、ボーン名が異なるため変換が必要です。
ボーン名の違いと Rest Pose の問題
- Mixamo の mixamorig: プレフィックスを外すだけで名前が一致
- Rest pose の差が姿勢の崩れを引き起こす
- はう
- ボーン名の違いはどんなものですか?
- めたん
- Mixamo は「mixamorig:Hips」のようにプレフィックスが付いています。Avaturn は「Hips」だけで、プレフィックスを外すだけで名前が一致します。
- はう
- 名前を変えるだけでは動かないんですか?
- めたん
- 最初はそれだけで動くと思っていましたが、アバターが完全に消えてしまいました。rest pose、つまり初期姿勢のボーン回転が両者で異なるのが原因です。
- はう
- 具体的にどれくらい違うんですか?
- めたん
- Hips ボーンで約 90 度の差があります。Mixamo の rest pose は約 90 度回転しているのに対し、Avaturn はほぼ無回転です。この差がスケルトン全体を破壊していました。
Blender 5.0 CLI でのリターゲット
- Blender 5.0 で Action API が刷新。fcurves はレイヤー構造に
- 体幹ボーン全体の補正をスキップするのが最終的な解
- はう
- Blender でのリターゲットはどういう流れですか?
- めたん
- Mixamo モデルを読み込んでアニメーションデータを抽出し、Avaturn モデルに rest pose の差分を補正しながら適用します。その後 NLA トラックに配置してエクスポートします。
- はう
- 試行錯誤した失敗はどんなものがありましたか?
- めたん
- 全ボーンに rest pose 補正を適用したら仰向けで歩く、Hips だけスキップしたら猫背になる、と順に問題が出ました。最終的に Hips・Spine・Neck・Head の体幹全体をスキップするのが解決策でした。
- はう
- Blender 5.0 で API が変わったとのことでしたが?
- めたん
- アニメーション API が大幅に刷新されました。従来の action.fcurves が使えなくなり、action.layers[0].strips[0].channelbags[0].fcurves というレイヤー構造になりました。
Node.js での比較検証
- GLB を直接パースして Blender 版とランタイム版を数値比較
- 四肢は完全一致、Hips のみ ~90° の差
- はう
- Node.js での検証は何のためにやったんですか?
- めたん
- Blender 版と Three.js ランタイム版の差分を目視確認ではなく数値で特定するためです。GLB ファイルを直接パースしてクォータニオン値を比較しました。
- はう
- 比較で何が分かりましたか?
- めたん
- 四肢のボーンはクォータニオン値が Mixamo と完全に一致していました。つまり四肢はリネームだけで正しく動きます。Hips だけが約 90 度の差がありました。
- はう
- Hips の差はなぜ生じるんですか?
- めたん
- Blender の GLB インポーターが Y-up と Z-up の座標変換を適用するためです。エクスポート時に逆変換が入るので、往復で Hips の回転値が変わります。
Three.js ランタイムでブラウザ完結
- Hips のみ 90° X 回転の座標系補正、四肢はリネームのみ
- position トラックは除外(Mixamo は cm、Avaturn は m 単位)
- はう
- 最終的に Three.js でどうやって実装したんですか?
- めたん
- Hips だけ 90 度 X 回転の座標系補正を適用し、四肢はリネームのみ。position と scale のトラックは完全に除外します。これだけでブラウザ内で完結します。
- はう
- position トラックを除外するのはなぜですか?
- めたん
- Mixamo は cm 単位、Avaturn は m 単位で約 100 倍の差があります。そのまま適用するとアバターが巨大化します。
- はう
- Idle から歩行に切り替えるときはどうしますか?
- めたん
- 即時切替すると点滅が起きます。Three.js の MathUtils.lerp で毎フレーム 10% ずつ重みを変化させることで、滑らかにクロスフェードします。
まとめ
- 四肢はリネームのみ、Hips のみ座標系補正
- position トラック除外・lerp クロスフェードがポイント
- はう
- 今日のまとめをお願いします。
- めたん
- 判明した事実は 4 点です。四肢はリネームだけで動く。Hips のみ 90 度 X 回転の補正が必要。position トラックは単位差で除外が必須。Idle と歩行の切替は lerp でクロスフェード。
- はう
- デバッグで GLB を直接パースして数値比較したのは効果的でしたね。
- めたん
- ブラウザで目視確認を繰り返すより、数値で差分を特定する方が確実でした。同じ問題に遭遇した場合の参考になれば良いと思います。
- はう
- Blender 不要でブラウザだけで完結するのが実用的ですね。ありがとうございました。