Maya

quaternionの知識を使わずに捻りを扱ったツイストジョイントを作成してみよう

はじめに

こんにちは。モノリスソフト テクニカルアーティストの広森です。

今回はMayaで「リグ初心者」の方に向けたツイストジョイントを作成する手順を書いてみようと思います。

ツイストジョイントを例に記載していますが、考え方は色々な場所で使用できる方法です。応用ができるので無駄にはさせません。

"quaternion" "三角関数" "Matrix"など頭を痛くさせてしまう用語は本文では出てきませんので安心してお読みください。

この記事を読むことで得られる内容

  • 単純な回転値の参照ではないツイストジョイントや補助骨が作れるようになる。
  • オイラー回転の問題点について理解する。
  • リグなどでつまずいた際の考え方。

ツイストジョイントとは?って方や、今からツイストジョイントを始めて挑戦するよ!!って方向け

この部分ではこの記事で出てくる以下のワードについて説明します。既にご存知の方は読み飛ばして頂ければと思います。

  • ツイストジョイントとは?
  • multiplyDivideとは?Node Editorとは?

ツイストジョイントとは?

ツイストジョイントとは以下の画像をご覧ください。

tech_06_02.pngのサムネイル画像

少ないジョイントのみでスキニングをしてしまうとポリゴンが極端に細くなってしまいます。この細くなる状態を緩和するためにジョイントを追加します。

また、特定の回転だけの影響を受けたい場合にも設定をします。

multiplyDivideとは?Node Editorとは?

multiplyDivideとはこの記事で使われる計算ノードの一種です。Mayaでリギングを行う際に使用したり、マテリアルで色を加工したい場合に使用することが出来ます。

Mayaの基本理念としてメッシュやジョイント、カメラやマテリアルなど全てノードで構成されています。その為、私達デザイナーでもプログラムを書く必要なく、直感的に扱えるようになっています。

対応するノードにはこのmultiplyDivideを使って値を加工することが出来ます。

このノードを紐づける事が出来る機能がNode Editorになります。

メニューバーのWindows > Node Editorから開くことが出来ます。

tech_06_03.png

開いたNode Editorでtabキーを押してmultと打ち込むと候補に"multiplyDivide"と表示されるので、クリックするとmultiplyDivideノードが作られます。

tech_06_04.pngのサムネイル画像

簡単にボタンの説明を行います。

tech_06_05.png

画像の① : ノードエディター内のノードをノードエディター上から非表示にします。ノードの削除は行いません。

画像の② : ノードエディター内に選択しているオブジェクトのノードを追加します。関連するノードも追加される場合もあります。ノードが新たに作成されるわけではありません。

画像の③ : 選択しているノードをノードエディター上から非表示にします。こちらもノードの削除は行いません。

ノードを紐づけるには、以下の画像の赤い丸で囲まれた箇所から、もう一つの赤い丸に向かってドラッグするだけで接続できます。

tech_06_06.png

もっと詳細が知りたい方は、公式のドキュメントをご確認ください。

Autodesk、ノードエディタ(Node Editor)の基本

https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2020/JPN/Maya-Basics/files/GUID-68E825E4-140B-4B4E-97AC-E1C5E0AA84A0-htm.html

事前に準備しておくもの

今回の記事で作成する箇所は、肘から手首にかけてのジョイントを想定しています。以下の画像のような階層構造で作成しておきましょう。

配置している全てのジョイントは扱いやすいように"Rotate""JointOrient"アトリビュートには0を設定してあります。

ジョイントの名前と配置は以下の画像の状態です。ネーミングルールは分かりやすいものをつけてください。

tech_06_07.png

よくある回転値のみを使ったケース

手首のジョイントである"wrist_L_JNT_00"が動いた際に"elbowTwist_L_JNT_00"が半分動いてほしいので、画像の赤線である"wrist_L_JNT_00"の"RotateX"を同じ軸方向な"elbowTwist_L_JNT_00"の"RotateX"に"multiplyDivide"で半分にした計算。つまり0.5をかけた状態で接続してみましょう。

tech_06_08.png

ノードエディタで接続して回した状態が以下の状態です。うまくねじれていそうですね。

tech_06_09.png

ただ、特定の方向では捻じれてほしい箇所が捻じれていません。

tech_06_10.png

なぜこのような現象が起こるのでしょうか。

回転値の参照では欲しい情報が得られない

3Dソフトでは2種類の回転方法があります。その片方の回転方法がオイラー回転と呼ばれる手法です。

X,Y,Zの3つの値を扱って回転表現をします。人間が扱うには直感的で分かりやすい手法ですね。ただこの回転の手法には問題があります。

以下の画像内の箱は同じ方向を向いてますので、当然回転値も同じはずです。確認してみましょう。

tech_06_11.pngのサムネイル画像

実際に確認した画像がこちらです。

tech_06_12.png

中の回転値がおかしい・・・・・見た目は一致しているのに・・・・

誤差とは言えないような膨大な数値が入っています。

今回たまたまこうなってしまっただけで、2通りだけであれば法則が見つけることが出来るかもしれません。

tech_06_13.png

またしても違う数字が入ってしまいましたね・・・・

このように、この回転方法では最終的に軸方向が同じ向きでも違う値が含まれてしまいます。鋭い方は気が付いたかもしれませんが、360度ずつ回転しているので回りきってしまい1周してしまっているのです。

今回は画像を作りやすいように360度で作成したためこのような形になりましたが、全ての回転軸でこのような現象は起こりえます。

ここに回転順序などを加えてしまうと頭が痛くなってしまいますね。

欲しい情報を得るために手を観察して要素を分解する

オイラー回転の値では欲しい情報を取得することが出来ませんでした。ここで改めて達成したい内容を考えてみましょう。

  • 手のひらを返す際に手首が適切にねじられてほしい。

ざっくりまとめるとこうなりますが、これだけでは解決の糸口が掴めないのでもう少し深く掘り下げてみましょう。

先ほど考えた達成したい内容では適切にねじられてほしい定義が曖昧なので、実際の手の状態を観察し当てはめて要素を決めてみます。

以下の画像は全て一定の方向から撮影しています。実際に自分の手の平を返しながら見てみてください。指の向きは変えないものとします。

手首のねじれる条件を明確化します。

  1. 手のひらが通常時から反対の向き(通常時から①)に回転しようとすると手首がねじられる。
  2. 画像②と画像③は手の甲を回転させてさらに手の方向を変えてみた画像です。こちらも手首がねじられる。
  3. 画像④では手の甲の方向は変わっていますが、手の甲が水平なため手首がねじられていません。

掘り下げてみた内容をまとめると以下の内容になりました。

  1. 手のひらを回転した場合手首がねじられる。
  2. 手のひらを回転せず、手のひらの向きを変えただけでは手首はねじられていない。

この2つの要素から以下の仮説が立てられそうです。

  • 手のひらの捻りを決める回転と手のひらの方向を決める回転の2種類がある。

今後の説明をスムーズにするためにこの現象に名前を付けてあげます。

手首の回転に影響を与える回転 = 捻り量

手のひらの方向を決める回転  = 方向

この2つの要素を実際のジョイントに当てはめることが出来れば、問題に対処できそうですね。

オイラー回転から方向と捻り量に分解する。その1

先ほど3つの箱を用いて説明した、「軸方向が同じ向きでも、違う値が含まれてしまう問題」について、ここで改めて確認してみましょう。

  1. 3つの回転値の組み合わせで姿勢を表現するため、回転値の組み合わせが無数に存在する。
  2. この3つの値の内1つの値を参照するだけでは欲しい情報が得られない。

現状の回転方法では、手の甲の向きと手のひらのねじれである2つの要素を、3つの数字の組み合わせの回転で表現してしまっているため抽出することが出来ません。

かと言って直感的であるオイラー回転の手法は変えたくありませんし、変更するにはMayaに独自のシステムを作らなければなりません。現実的ではありませんね。

なのでオイラー回転から2つの要素に切り分けてあげましょう。

方向を指し示す要素捻りを指し示す要素ですね。特定の軸方向にそった捻り量を抽出出来れば適切な情報を取得できそうです。

今回以下の画像でX軸の方向である赤の矢印を方向、青い矢印を捻り量としました。

▼ジョイントの方向と捻りの例

tech_06_19.png

まずは方向だけの回転を抽出してみましょう。Mayaにはデフォルトの機能で特定の位置に向かって回転させる機能がありましたね?

そうです、AimConstraint(エイムコンストレイント)ですね。

▼AimConstraintの例

tech_06_20.pngのサムネイル画像

このコンストレイントを使えば、ターゲットのオブジェクトの方向に指定した軸を向け続けることが出来ます。ターゲットが動けば自動で追従もしてくれます。

方向だけの回転はこれで抽出出来ました。

一つの回転から方向と捻り量に分解する。その2

方向の回転は抽出出来たので残りは捻りですが、以下のように捉えることが出来ます。

オイラー回転は方向の概念と捻りの概念が含まれていると説明しました。数学っぽく言うなら以下の公式です。

  • オイラー回転 = 方向 + 捻り量 

方向は決まっており、回転結果であるオイラー回転も制御される骨である"wrist_L_JNT_00"で設定するのでここも決まっています。

後は捻り量が欲しいので式を変形しましょう。以下のような形に変えられます。

  • 捻り量 = オイラー回転 - 方向

これが捻り量なります。1つの回転から2つの要素を出す方法は決められましたね。

ジョイントで実際に再現する

回転方法の切り分けの手法は決めることが出来たので、後はジョイントに割り当てる実装作業です。先ほど作成したシーンに以下のジョイントを追加します。

"wristAim_L_JNT_00"ジョイントは方向を決める、"wristRoll_L_JNT_00"ジョイントは捻り量を管理する役割があります。

位置は"wrist_L_JNT_00"全く同じ場所にそれぞれのジョイントを配置して必ず親子関係を組んでください。

▼ジョイントを追加する位置と名前

tech_06_21.png

設定し終えたらコンストレイントを設定します。

上記の画像であれば"wiristEnd_L_JNT_00"をターゲットにしてAimConstraintを"wiristAim_L_JNT_00"に設定してください。

設定する際のOptionですが必ず"World Up Type"の欄を"None"に設定して下さい。
このWorld Up Typeの欄の内容はAimConstraintの機能で特定の軸方向に向け終えた後に向けた軸をどう補正するのかのオプションになります。

シーンの向きやオブジェクトの向きを設定することも出来るのですが、今回はNoneにしておきます。
Noneにしておくことで他の軸が勝手に補正されないので、欲しい方向だけを取得することが出来ます。

"wiristRoll_L_JNT_00"の扱いですが"wirist_L_JNT_00"と全く同じ方向を向いてくれれば、ParentConstraintやOrientConstraintでもAimConstraintでも何でも良いです。

後は親子関係を設定したので勝手に差分の回転値である捻り量がオイラー回転として"wiristRoll_L_JNT_00"に設定されます。

捻り用のジョイントは半分だけ回転させたいので最初に用意していた"multiplyDivide"に"wiristRoll_L_JNT_00"の"RotateX"を接続してみて下さい。

tech_06_22.pngのサムネイル画像

実際に回転させてみましょう。1軸回転では問題なさそうです。

tech_06_23.png

2軸でも適切な挙動になりましたね。

tech_06_24.png

この構造のメリットデメリット

この構造は"quaternion"の挙動をコンストレイントを使って再現しただけなので、初心者のには扱いやすいとは思います。複雑な計算や設定も無いので欲しい捻り量がすぐに取ってこれますね。

私も検証ならこの構造を使ってリグを作成することがあります。他のソフトでも似たような設定があれば再現出来るので比較的汎用性も高いです。

しかし、この構造実はデメリットがあります。リガーの方ならお分かりかと思うのですが実は最適化された構造ではありません。

以下の要素が不要な要素です。

  • "wiristAim_L_JNT_00"、"wiristRoll_L_JNT_00"がそもそも不要なトランスフォームノードなので計算ノードで代用できる。
  • コンストレイントを使ってリグを作成しているので不要なワールド計算が入ってしまっている。

不要な要素を無くし、もっと最適化してあげたいと思うようになったら是非挑戦してみてください。

まとめ

quaternionの知識でくじけてしまった人でも扱えるようにコンストレイントのみを使ってツイストジョイントを作成してみました。

そしてツイストジョイントなどで良くある課題を解消するためのアプローチとして要素を分解し、順番に対処する方法を記載してみました。

この考え方はツイストジョイントだけでなく他の物事にも活かせるので、何かに躓いてしまった方は是非活用してみて下さい。

また、リグに対するハードルや苦手意識が少しでも払拭出来ればと思います。

参考

Autodesk、ノードエディタ(Node Editor)の基本
https://knowledge.autodesk.com/ja/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2020/JPN/Maya-Basics/files/GUID-68E825E4-140B-4B4E-97AC-E1C5E0AA84A0-htm.html

AUTHOR:広森

映像業界を経てモノリスソフトへ入社。 以来、テクニカルアーティストとして主にリギング・セットアップ関連の業務を担当。 好きな飲み物は赤ワイン。