Step 03:Quaternionについて考える
ここまで、オイラー回転を使って補助骨の制御について考えてきました。しかし、オイラー回転をリグ制御に用いることの問題については前回の記事で触れた通り、直感的でわかりやすく操作しやすい反面、補助骨の制御には不向きです。
実際、このように挙動が暴れる場合もあって、運用には注意が必要です。
結局挙動が暴れる箇所を手作業で直す、などということになってしまうと、アニメーションの工数をいたずらに増やしてしまうことにもなりかねません。
そこで、Quaternionという回転制御の概念について少し踏み込んでみたいと思います。オイラー回転は「どの軸にどれくらい回ったか」という説明ですが、
Quaternionは、「どっちを向いていて、どれくらい捻じれているか」で、現在の姿勢を説明しています。
このように、オイラー回転に対してQuaternionは姿勢をダイレクトに説明しているので、補助骨制御の面ではQuaternionの方が向いている感じがしますね。
また、オイラー回転はX、Y、Z軸の3つが回転して現在の姿勢にいたるのに対し、Quaternionは「四元数」という「複素数」を拡張した1つの値による1回の回転で現在の姿勢にいたります。そのため、Quaternionにはオイラー回転にあるような「回転順序」の概念が必要ありません。
この点においても、補助骨制御やリギングにおいてはQuaternionを積極活用していきたいところです。
Step 04:Quaternionでの回転計算
では、Quaternionを使った回転制御について考えてみます。
オイラー回転では、回転加算は足し算だったのに対して......
Quaternionはかけ算で回転加算を考えます。
なので、例えばpolyConeノードに対して回転Aの後に回転Bをさせたい場合は、回転AのQuaternionに回転BのQuaternionをかけ、polyConeノードに接続すれば良いのです。
試しにノードエディタで接続を作ってみます。
locatorA、locatorBのオイラー回転をeulerToQuatノードを使ってQuaternionに変換し、
quatProdノードを使ってそれぞれのQuaternionをかけ算します。
quatToEulerノードを使ってQuaternionを再度Eulerに戻し、polyConeノードに接続すると、
このように、ノードAの回転の後にノードBの影響を受けていることがわかります。
では、回転加算がかけ算ならば、回転を打ち消したい場合は?
逆数をかければ良いのです。
QuatInvertノードでQuaternionを逆数にすることができます。試しに先ほどのlocatorAのQuaternionをQuatInvertノードに接続し、逆数にしてみます。
すると......
このように、回転Aを回転Bから打ち消した結果がpolyConeノードに流し込まれていることがわかります。ちなみにQuatInvertノードによって取得されたQuaternionは、逆Quaternionとも呼ばれます。
Step 05:実装
さて、ここまでで行なった設計を最初の手首ジョイントに適用してみましょう。まず、手首のBendを取得するノードを構築します。
今回は純粋にジョイントの回転成分のみを扱いたいので、ジョイントのrotateのみをcomposeMatrixノードに接続してMatrixを生成しています。次にBend回転をQuaternionに変換しますが、axisAngleToQuatノードを使うと、回転軸と角度情報からQuaternionを計算することができます。
Bend回転を取得しているangleBetweenノードからAxisとAngle情報をaxisAngleToQuatに接続して、Quaternionに変換します。
続いて、このQuaternionをQuatInvertノードに接続して逆Quaternionに変換しておきます。
次に、手首自身のEuler回転をeulerToQuatノードに接続してQuaternionに変換します。
QuatProdノードを作成して、手首のQuaternionにBendの逆Quaternionをかけ算します。
これでRollのQuaternionが抽出できたはずです。
さて、ここで緩衝のためにRoll成分のうち半分くらいを取り出したいところです。オイラーに変換した後、値を半分にしても良いのですが、ここではquatSlerpノードを使ってみます。
quatSlerpノードは2つのQuaternionの入力に対して、指定の係数でSlerp補間をかけることができるノードで、平たく言うと、0%のときはQuaternionAを返し、100%のときはQuaternion Bを返し、50%のときは半分を返すというもので、pairBlendノードやコンストレイントのウェイト値のように使うことができます。
ひとまずquatSlerpノードを生成し、input1とinput2両方にRollのQuaternionを接続します。
次に、input1からQuaternionの接続をカットします。
これで最初の値、すなわち規定値=無回転の状態の値をinput1に残すことができます。
そして、大体半分くらいのRollになるように、Tの値に「0.5」を入力しておきます。
結果のQuaternionをquatToEulerノードに接続してオイラー回転に変換し出力の値を補助骨のrotationに接続します。
結果を見ると...
できました! ハラショー!