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 不要でブラウザだけで完結するのが実用的ですね。ありがとうございました。