こんにちわ、兼業クリエイターのみっつです!
今回はFBXとかで配布されてるモーションデータを、Mayaで作った自作リグにリターゲットする方法を解説していきます。
キャプチャースタジオで収録したデータがFBXしか納品されなかった!!
リグが変わった…。今までのモーションデータが…
こんな場合に役立てたらと思います。
今回はapplibotさんが公式で提供してるフリーモデルの『アプリボットリグ』を使って解説していきます。
【前提知識】FBXデータは同名なら同じ動きをする
リターゲットの前に、FBXデータの特性をちょこっと解説します。
FBXは同名のスケルトンにモーションを読み込めます。
上の動画にあるように、インポートするジョイントの名前と、インポートしたシーンに同じ名前のジョイントがあると、インポートしたデータのトランスフォームの値が適用されます。
つまり、同じ動きになる、ってことです。
試しにスケルトンのジョイント名を変更して、先程と同じデータをインポートしました。
すると動画の通り、名前が変更されたジョイントには動きが入ってない事が分かりますね。
『同じ名前で読み込むと、同じ動きをする』っていうのがFBXデータの特徴です。この特徴を使って、リグにリターゲットしていきます。
ちなみに、動画の左側に映ってるツールは『FBX Review』っていう、FBXデータを再生できるAutodesk公式ツールです。
めっちゃ便利なので使ってみてください。
【使用データ】アプリボットリグ
今回はapplibotさんが公式で提供してるフリーモデルの『アプリボットリグ』を使って解説していきます。
【準備①】走りモーションをFBX出力
モーションデータは、同梱されてる走りモーション(ab_rig_A_run.ma)をFBX出力し、『走りをキャプチャーしたデータが納品された』という体で解説していきます。
- ab_rig_A:Jnt_C_Spine1を選択
- 選択 > 階層 で階層直下も全選択します。
- ファイル > 選択項目の書き出し
- 書き出し設定は、
- 接続 > 子を含む、入力接続のチェックを外す
- ファイル名:ab_rig_A_run.fbx
- ファイルの種類:FBX export
上記の手順でアニメーションを書き出します。
【準備②】書き出したアニメーションデータを編集し再出力
書き出したデータ(ab_rig_A_run.fbx)を開くと画像のようになってるので、少し修正します。
- ab_rig_A:All_Grp等のグループノードを削除
- 『ab_rig_A:』のネームスペースを除去
上記2つの修正を加えます。
リネーム作業はCG自習部屋さんのツールがおすすめ
Maya標準のリネーマーは、置き換える文字列に空白が指定できません。それゆえに特定の文字列を除去する処理ができません。
なのでここは外部ツールを使います。
CG自習部屋さんって方が公開してる『AriRenamer』ってリネームツールがあるんですが、このツールを使えば、ネームスペースを一瞬で除去できます。
めっちゃ便利なので超おすすめですよ
【準備③】アプリボットリグの背骨を改修
アプリボットリグの背骨はちょっと特殊な作りになってるので、解説の都合上、ちょっと改修を加えてます。
改修内容は背骨にリグを追加してるだけなので、解説は割愛します。
リグに動きを流す仕組み『インポート構造』を解説
インポート構造とは…?
って感じだと思いますので、解説します。
インポート構造とは、リグに動きを流す仕組みのことです。
業界標準の呼び方かは知りませんが、私が昔いた現場でそう呼ばれてたので、今もそう呼んでます。
細かいことは気にせず、インポート構造って言葉が出てきたら、「あぁ、リグに動きを流してるのねー」くらいに思って下さい。
【インポート構造の考え方】ジョイントでリグコントローラーを動かすこと
インポート構造の考え方はシンプルで、『ジョイントでリグコントローラーを動かす』ってことです。
ジョイントで、リグコントローラーを、動かす…??
普段リグを作るときは、カーブとかでコントローラーを作り、それとジョイントをコンスト(もしくは接続)して動かす仕組みを作っていくと思います。
インポート構造ってのはその逆で、ジョイント(スケルトン)とリグコントローラーをコンストして、リグの方を動かす
って考え方です。
- 通常→リグコントローラーでスケルトンを動かしてる
- インポート構造→ジョイントでリグコントローラーを動かしてる
整理するとこんな感じですね。
インポート構造なんて、なんか小難しいように聞こえますが、ようはただのコンスト作業ですよ。普段のリグ作業の逆をやってるって思えばOKです。
【インポート構造の作り方①】モデルのスケルトンを複製
アプリボットリグの場合は、『Jnt_C_Spine1』このスケルトンを使ってリグを動かします。
『Jnt_C_Spine1』を複製し、この複製されたスケルトンをリグとコンストし、スケルトンでリグが動くようにしていきます。
【インポート構造の作り方②】ジョイントとFKコントローラーをつなぐ
ジョイントでリグを動かすというのは、例えばこんな感じで、『Jnt_C_Waist』と『Rig_C_Waist』をペアレントコンストレイントします。
そうすると『Jnt_C_Waist』を動かすことで『Rig_C_Waist』が動きますよね。これがインポート構造の基本的な考え方です。
ジョイント | リグ | コンストの種類 |
---|---|---|
Jnt_C_Waist | Rig_C_Waist | ペアレント |
Jnt_C_Spine1 | Rig_C_Spine | オリエント |
Jnt_C_Spine2 | Rig_C_Spine1(追加したリグ) | オリエント |
Jnt_C_Chest | Rig_C_Chest | オリエント |
Jnt_C_Neck | Rig_C_Neck | オリエント |
Jnt_C_Head | Rig_C_Head | オリエント |
Jnt_L/R_Clavicle | Rig_L/R_Clavicle | オリエント |
Jnt_L/R_Shoulder | Rig_L/R_Shoulder_FK | オリエント |
Jnt_L/R_Elbow | Rig_L/R_Elbow_FK | オリエント |
Jnt_L/R_Hand | Rig_L/R_Hand_FK | オリエント |
Jnt_L/R_Finger各種 | Rig_L/R_Finger各種 | オリエント |
FKコントローラーへのコンストは上記の通りです。
腕の制御はFK派、IK派の両方がいます。これはきのこたけのこ戦争くらい永遠に争い続けるでしょう…
アプリボットリグには、IK/FKのコンバートは入ってないっぽいので、どちらのリグにリターゲットするかは慎重に考えた方がいいかもですね。
コンバートの仕組みが実装されるといいですね~
【インポート構造の作り方③】ジョイントとIKコントローラーをつなぐ【疑似ポールベクター】
IKで動きを返す場合はポールベクター(極ベクイトル)の位置を求める必要があるので、ちょっと複雑です。
この作業を私は『擬似的なポールベクターを作る』って呼んでるので、ここでは疑似ポールベクターに統一しますね。
疑似ポールベクターを作る手順
- IKが使われてるジョイントチェーンの全長を測る
- 2点間をコンストして、常に膝の裏に来る場所を求める
- エイムコンストで常に膝を向く仕組みを作る
- 足首とポールベクターのコントローラーをコンスト
ざっくりの流れはこんな感じです。
順番に解説していきます。
①IKが使われてるジョイントチェーンの全長を測る
今回は足の動きをIKコントローラーに返したいので、足のジョイントで解説します。
IKが使われてるジョイントチェーン、脚の場合だと、膝上~足首がそれにあたるので、計測ツールを使い、該当の部分を測っていきます。
脚の長さ
- 膝上~足首:66.666346
- 膝上~膝:36.007076
脚の長さは上記の通りです。この数値は後ほど使いますので一旦おいておきます。
②2点間をコンストして、常に膝の裏に来る場所を求める
次に、脚をどんなに曲げても膝の裏にロケータが付いてくる仕組みを作ります。
脚を、どんなに曲げても、膝の裏に、ロケータが付いてくる…?
イメージは上の画像のように、膝を曲げて脚を前に出したり後ろに引いたり等、どんなに脚を動かしても、膝の裏にロケータが付いてくるようにします。
これも後の工程で使うので、とりあえず、「膝裏に付いてくるロケータを作るんだなぁ」くらいに思って下さい。
■手順
- ロケータを作り『IM_L_2pointCons_Loc』と名前をつける
- Jnt_L_Thigh → IM_L_2pointCons_Loc でコンスト
- Jnt_L_Ankle → IM_L_2pointCons_Loc でコンスト
- コンストのウェイトを0.5ずつにする(説明用なので後で変更予定)
まずは上の手順でロケータを作り、それぞれのコンスト作業をします。コンストしたらそれぞれのウェイトを0.5ずつ入力します。
そうすると、『IM_L_2pointCons_Loc』が常に真ん中の位置にくるようになりますね。
ほう…0.5ずつで設定すると、膝の位置よりちょっと上にくるのか…
ん~、、、って事はつまり、
0.6と0.4、かもしれないし、0.55と0.45かもしれない…ってこと?
その解釈でOKです。ただ、当てずっぽうでここの数値を入れたところで、精度の高いリターゲットはできません。
なのでここは面倒ですが、計算で求めます。
今回の場合、
- 膝上~足首(Jnt_L_Thigh~Jnt_L_Ankle):66.666346
- 膝上~膝(Jnt_L_Thigh~Jnt_L_Knee):36.007076
となってますので、数式にすると、、、
- 1:66.666346 = X:36.007076
- 66.666346x = 36.007076
- X = 36.007076/66.666346
- X = 0.5401087379230294
- Y = 1 – 0.5401087379230294
- Y = 0.4598912620769706
こんな感じになります!!これをコンストのウェイトに当てはめていくと、、、
こんな感じで、常に膝の裏にロケータがくるような仕組みができました!
カンタンですね!!!
・
・
・
・
いや、わからん!!!
って感じで当初の私はキレそうになってたので、一応解説していきます。
興味ある人は読んで下さい。
『1:66.666346 = X:36.007076』の解説
全体の長さを1(100%)とすると、今回の全長(膝上~足首まで)は66.666346です。
この状態から膝(Jnt_L_Knee)の位置を求めたいので、一旦Xとします。
先程の計測で膝上~膝の長さは36.007076と分かってるので、全長が66.666…のとき1だから、36.007…のときはいくつ?という計算式が成り立ちます。
これを一次方程式にすると、『1:66.666346 = X:36.007076』ってなります。
『1:66.666346 = X:36.007076』の計算方法
1:66.666346 = X:36.007076、こいつの右辺にあるXを左辺に移項して、
66.666346x = 36.007076ってして、
左辺をX=〇〇の形にしたいから、両辺に1/66.666346をかけて、
X = 36.007076/66.666346ってやって計算。
その値は『0.5401087379230294』となり、膝上から測った膝の位置『36.007…』は、全長の『0.540…』の場所にあると分かります。
0.540…ってことは半分よりちょっと長い場所にあるので、足首の方に若干強めに引っ張ってもらいたいな~って感じなので、足首側のウェイトを0.54を入れます。
全体のウェイトは1が最大なので、1から0.540…を引いた残りの数値を膝上のウェイトに入れればOKです。これを計算すると、
1 – 0.5401087379230294 = 0.4598912620769706 となるので、0.459…を膝上のウェイトに割り当てます。
そうするとどんなに脚を動かしても、コンストしたロケータが膝の裏についてくるようになります!
ここまでの説明を計算式でおさらいすると、
- 1:66.666346 = X:36.007076
- 66.666346x = 36.007076
- X = 36.007076/66.666346
- X = 0.5401087379230294
- Y = 1 – 0.5401087379230294
- Y = 0.4598912620769706
こうなるわけですね
割合の理屈は厳密には違うかもですが、細かい事は気にせず、感覚でOKです。
膝上が短かったら膝上側に強く、膝下が長ければ足首側に強く引っ張られせる。
そう覚えておけばOKです。
③エイムコンストで常に膝を向く仕組みを作る
最後に疑似ポールベクターの位置を求めます。
ポールベクターは膝や肘の真正面にあるので、先程求めた『IM_L_2pointCons_Loc』を使っていきます。
IM_L_2pointCons_Locは常に膝裏に付いてくるので、このロケータの目線の先には膝があり、さらにその先にはポールベクターがあります。
この考え方のもと、疑似ポールベクターの仕組みを作っていきます。
疑似ポールベクターを作る階層構造の説明
- IM_L_2pointCons_Loc(割合求めて膝に持ってきたやつ)
- IM_L_ObjectUp_Loc(エイムのオブジェクトアップ用)
- IM_L_AimVector_Loc(膝にエイムさせる用)
- IM_L_LegPole_Loc(リグのポールベクターと繋ぐ用)
疑似ポールベクターを求めるノード階層は画像の通りで、各ロケータの説明は上記の通りです。
膝裏の位置を求めたロケータ(IM_L_2pointCons_Loc)の子供にオブジェクトアップ用のロケータ(IM_L_ObjectUp_Loc)を作り、その子供にエイム用のロケータ(IM_L_AimVector_Loc)を作ります。
ObjectUp_Locは膝裏方向に-1ほど下げます。これは膝を曲げる方向を表してると思って下さい。
- ワールドアップタイプ:オブジェクトアップ
- ワールアップオブジェクト:IM_L_ObjectUp_Loc
Jnt_L_Knee → IM_L_AimVector_Loc の順で選択し、エイムコンストします。オプションは上記の通りです。
ワールアップオブジェクトに『IM_L_ObjectUp_Loc』を設定することで、このロケータを天井とすることができます。
こうすることで、脚を上に上げても『IM_L_ObjectUp_Loc』を天井としてるのでフリップが防げます。
これで常に膝方向を向くロケータが完成しました。後は接続を残すのみです。
④足首とポールベクターのコントローラーをコンスト
疑似ポールベクター用のロケータを作り、『IM_L_LegPole_Loc』とします。
コンスト関係は、
- Jnt_L_Ankle → Rig_L_Leg1_IKを、ポイントコンスト
- IM_L_LegPole_Loc → Rig_L_LegPole_IKを、ペアレントコンスト
このようにコンストしていき、脚のジョイント達でIKコントローラーが動くようにします。
以上でインポート構造の完成です!
つなぎ終わったら脚のジョイント達を回転してみて下さい。いいカンジで脚のIKコントローラーが動いてるはずです!
最後に現在の作業シーンを保存します。
インポート構造はリターゲットが終わると削除しちゃうんで、必ず別名で保存して下さい。
リターゲットに使うマスターシーンとして、バックアップしておくことをおすすめします
走りモーションを読み込んでリグにリターゲット
上記のインポート構造が作れたら、最初に用意した走りモーション(ab_rig_A_run.fbx)をインポートしてみましょう。
動画のようにFBXデータを読み込み、リグが動けば自作リグへのリターゲット完了です。
動きをリグにベイクして編集【別名保存で作業開始】
- コントローラーを全選択
- アニメーションメニューから、キー > シミュレーションのベイク処理
- インポート構造の削除
- 別名保存して作業開始
インポートの処理が終わったら、上記の手順で作業を始めましょう!
アプリボットリグは専用のピッカーを用意してくれてるので、そこからコントローラーを全選択しキーをベイク、リターゲットした動きをリグに焼き付けます。
ピッカーの導入方法とかはダウンロードデータの中の『\ab_rig_A\picker\readme_picker_20230331.txt』に入ってるので、詳細はそちらを確認してください。
ベイクが終わったらインポート構造はいらないので削除して下さい。
最後に現在の作業シーンを別名で保存しましょう。
もし上書きしちゃうとまたインポート構造を作らないといけなくなるので注意して下さい!!
インポート構造のシーンデータは、安全な場所にバックアップする事をおすすめします。
別名保存が終わったら、アニメーションの編集作業を開始します。
この一連の流れが『FBXデータから自作リグにリターゲットする』っていう工程です。
仕組み作りは面倒ですが、あると色々応用が効くので、ぜひとも活用してください。
【まとめ】IKへのリターゲットは面倒だがやる価値あり
自作リグへのリターゲットまとめ
- FBXデータは同名なら同じ動きをする
- インポート構造が重要
- FKは簡単。IKはややこしい
- インポート構造の作業シーンはバックアップ必須
以上が自作リグにFBXのモーションデータをリターゲットする流れです。
記事書いてて思いましたが、IKコントローラーへのリターゲットは、本当に面倒ですねぇ…
ここにスプラインとか入ってくると、もう厄介度が更に増しまんですよ…
今回の方法は大真面目にIKへのリターゲットをする場合ですが、簡易的には膝ジョイントの子供にするって方法もあります。
ですが、それだと動きによっては全然違う動きでリターゲットされちゃうので、どっちを使うかはケースバイケースですかね。
大量のモーションデータで、しかもアクション多めな動きとなると、面倒でも大真面目に作る方が修正箇所が減る分、アニメーションコストは削減できます。
リターゲットの仕組みはある程度ツール化もできますしね。
また、リグによってはどうやってもリターゲットできないんじゃね?って思うようなものもあります。
今回のアプリボットリグだって背骨が特殊になってたので、一部改修してますしね。
これが業務だったら、精度100%のリターゲットは諦めて8割で終わらしてますわ。
個人的には、リターゲット作業はある程度妥協も大事だと思ってます。8割くらい動きをリターゲットできてたら、さっさと編集作業に移った方がいいですよ。
自作のリグにリターゲットする目的は、アニメーションの修正やブラッシュアップをすることにあります。
元の動きを100%完全に返すことではありません。
その動きでOKならさっさとレンダリングなりゲームエンジンに書き出すなりして、パッケージングすれば良いわけですしね。
100%キレイに返せたらそりゃ気持ちいですが、それは作業者のエゴです。アニメーターやディレクターから言わせたら、「そんな細かい事はいいから、さっさとデータ渡せよ」って感じですw
自分で言うのもあれですが、リガーやTA(テクニカルアニメーター)の作業って、無いに越したことはないと思います。
アート的なクオリティを出す部分はデザイナー次第なので、可能な限り滞りなく作業者に渡すことが重要です。
自分の工程がボトルネックになり、デザイナーさんの作業時間が短くなるってことは、極力なくすようにしてます。
まずはさっさとボールを渡す。
『クイック&ダーティ』、『完璧よりも終わらせろ』精神でリターゲット作業していきましょう!
それでは、みっつでした!