マトリクスを使ったポーズ・モーションの左右反転

おはこんばんちわ。
ホラーが苦手・山本ほっさんです。
今回は、モーションアーティストさんから特に要望の多い「ミラーポーズ」や「ミラーモーション」のAutodesk Maya®における対応事例についてご紹介いたします。
しかし、左右反転だからといって、Y軸にマイナスを乗算すればいい、というだけではありません。


結果を先に

blob

私が従来採用している方法は、マトリクスを反転させてミラーしたクォータニオンを取得し、ターゲットノードに戻す、という手法です。
でもなんで?なぜそのような手法を採用したのでしょうか。


Y軸にマイナスではダメなの?

簡単に考えれば、「左右反転なだけなら、単位Y軸にマイナスを乗算すればいいんじゃ?」と発想しがち。
しかし、下の例をご覧ください。

blob

これが…

blob

ヒィッ!
この処置の例では、一応階層や骨の軸方向定義などが影響しないように、ワールド空間上の回転として、y軸回転を反転させてみたものですが…。
うーん。背骨周りはそれっぽいようにも見えますが、手足は全然ですね。
このように、Y軸にマイナスを単に乗算するだけでは理想の結果にならないことがあります。
上の例で左右反転にならなかった原因は、回転順序の関係で、必ずしもY軸での回転反転が空間上の向きの反転と同意義ではない、という点がほとんどです。

オイラー回転は「向き」を保証するものではない。

blob

Mayaがデフォルトで採用・表示しているXYZの三軸で回転を表すオイラー回転は、直感的で理解しやすく、扱いやすい利点があります。
しかし、ジンバルロックや回転順序という概念が存在し、あくまで「三軸が順番にどのように回転したか」を説明しますが、特に「向き」については、意図通りに表現しないことがあって、個人的にはあまり信用していません。


向きを厳密に指定するならクォータニオンがよい

一方で「向き」について信用できるのは、クォータニオンによる回転表現です。オイラー回転は「どの軸に何度回ったか」を表現するのに対し、クォータニオンは「どの向きを向いていて、どれくらいねじれているか」という考え方です。
イメージ的には、クォータニオンを反転して適応してあげたいですね。


反転マトリクスをかける

blob

IKリグなど、向きだけでなく位置でコントロールしているものもあります。 これらは、向きと一緒にある空間軸で反転した位置も取得したいところ。
これらを一挙に解決するために、そのノードの空間=すなわち、マトリクスをある親空間上で反転すれば、向き・位置ともに、ある軸を対称にミラーしてくれそうです。
しかし、反転マトリクスとは?
ここでは単純に考えて、例えばあるノードをYZ平面で反転したい場合、X軸方向にマイナススケールを入れればそれっぽくなります。 このことは容易に想像できると思います。
この点から、反転させたい軸にマイナススケールを入れたマトリクスを乗算してれば、それっぽくなりそうです。


実際にやってみよう

試しに、X軸にマイナススケールを入れたTransform Node のマトリクスをコードで取得してみます。

blob

import maya.cmds as mc

node = mc.createNode('transform')
mc.setAttr('%s.sx'%node,-1.0)

print mc.xform(node,q=True,ws=True,wd=True,m=True)

↓結果

[-1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

うーん。

4×4に整列すると…

-1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0

なるほど、こうなっているんですね。
マトリクスのおのおのの軸の意味合いは…

1 0 0 0 X軸の定義
0 1 0 0 Y軸の定義
0 0 1 0 Z軸の定義
0 0 0 1 移動

こうなっているので、なるほど、なんとなく合点がいきます。
ここでは簡単に、NodeEditorでのノード接続で実装してみましょう。
まず、ターゲットノードとソースノード用意して…

blob

multiMatrixにソースノードのマトリクスをつないでみます。

blob

次に、反転マトリクスを取得するためのTransfom Nodeを用意して、同様にマトリクスをつなぎます。

blob

マトリクスの要素を分解したいので、decompose Matrixノードに乗算結果をつなぎ、

blob

QuatToEulerノードに乗算結果からのクォータニオンをつなぎ、

blob

Euler結果をターゲットノードに接続してやると…

blob

このとおり!

ミラー結果

さっきのジンバルの現象も…

ハラショー!

おこらない!!
ハラショー!


まとめ

このようなシンプルなロジックであれば、様々なモーション・ポーズのミラーToolへの実装もシンプルに済みそうです。
とくに、マトリクスやクォータニオンの計算には、MayaⓇから提供されているUtility Node周りが大変便利です。
何かの参考になれば幸いです。
でわでわ。

yamamoto tomohito

COYOTE 3DCG STUDIO モーション・リグ・パイプライン系TA。 他にやる人がいないのでチームリーダーです。 三時のヒロイン…じゃない、三児の父。 パパじゃないぞ。 おとうさんだ!

投稿者記事

  1. スクリプトでAnimCurveをフィルタリング!

    2023-12-14

  2. Filedialog設定で変わる!? FBX Export挙動の話

    2023-12-07

  3. スクリプト練習に最適!
    カスタムファイルブラウザで仕事効率化!

    2021-12-24

  4. 1ボーンIKのフロアコンダクトリグを作る!

    2020-12-22

関連記事

  1. 処理負荷検証の話

    2022-12-14

  2. ブレずに伸びるSplineIKリグを作ってみる!

    2019-12-24

  3. SI WeightEditor改修記!

    2022-07-27

  4. 【PySide】QtDesignerでDrag and DropできるWidget設定

    2023-06-28

スキルレーダーチャート

テクニカルアーティスト専用
スキルレーダーチャート
どなたでも無料でご利用いただけます。

ABOUT

TECH COYOTE​

テクニカルアーティストの為のまとめサイトです。​
本サイトでは、ツール開発、業務効率化等について情報発信をしていきます。

COYOTE 3DCG STUDIO

C&R Creative Studios

RECENT TWEET

ページ上部へ戻る