Melだけでクォータニオンを簡単に使う方法

クリーク・アンド・リバー社 COYOTE CG STUDIO テクニカルチームの戦国時代の先を見つめていたと思う武将は徳川家康、戦国大好き人間の中林です。

今回はクォータニオンの話だけど、クォータニオンの中身の話ではありません。ぶっちゃっけ、僕はアーティスト側からテクニカルアーティストになったのでそんな難しい理論は理解できません。
欲しいのはクォータニオンの結果だけです。
それでも、オイラー角とクォータニオンの関係を知っていることを前提の内容になっています。

pythonを使えばOpenMayaを利用してクォータニオンの変換した結果を入手できますが、今回はMelのみで使う方法です。

そもそものキッカケは?

ことの始まりはMayaで作成したカメラの軌道をUnityで再現したいとのアーティストからの依頼でした。
当時のUnity2017以前は再現するのに
➀Mayaでカメラに適当なモデルをコンストレイント
➁Mayaでモデルのモーションをフルベイク
➂Mayaからアニメ付きFBXをエクスポート
➃UnityでFBXをインポート
➄インポートしたキャラの子供にカメラをぶら下げる

がクォータニオンも何も使わなくていいのでこちらからすると楽なのですが、アーティストとして考えるとなんでダミーでモデルを作らなければいけないとか、Unityでカメラの親にモデルがある状況が嫌とか、手数が多いとかで嫌われました。
アーティストの立場で考えると繰り返し確認をするのにこの作業は大変です。そこでFBXを使わないでカメラを再現するのにクォータニオンの力が必要になりました。
※GTMF2019 「最新 Unity FBXExporter + Timeline の Maya/MotionBuilder ワークフロー」
 ダイキン工業株式会社
こちらのセッション内の情報だけど、Unity2018.1以降はカメラのFBXインポートが格段に楽になっています。

Melコマンドにクォータニオン関連が(たぶん)ない

たぶんと逃げ道を作ってますが、Melのオンラインマニュアルで「quaternion」で検索をかけても出てこないので僕の知る限りではありません。
少なくとも簡単に調べられて出てくるクォータニオンを扱うMelコマンドは見つからないです。
これではタイトルに矛盾してないか? 否、矛盾していません。コマンドが無くてもクォータニオンを簡単に扱う裏技があるからです。
それはノードを利用することです。

ノードにはクォータニオン関連がある


ノードエディタなどでノードをクォータニオンで検索すると様々なノードが出てきます。日本語版だと「オイラーからクォータニオンに」や「クォータニオンからオイラーに」と分かりやすいところから様々なノードがあります。
そして、ノードならMelから簡単にノードをつなげたり、アトリビュートに値を代入できたりします。

Melからノードの作成例

string $quatNodeList[];
$quatNodeList[0] = `shadingNode -asUtility eulerToQuat`;    // オイラー角⇒クォータニオン
$quatNodeList[1] = `shadingNode -asUtility eulerToQuat`;    // オイラー角⇒クォータニオン
$quatNodeList[2] = `shadingNode -asUtility quatProd`;       // クォータニオンの合成
$quatNodeList[3] = `shadingNode -asUtility quatToEuler`;    // クォータニオン⇒オイラー角

// ノードの接続
connectAttr -f ($quatNodeList[0]+".outputQuat") ($quatNodeList[2]+".input1Quat");
connectAttr -f ($quatNodeList[1]+".outputQuat") ($quatNodeList[2]+".input2Quat");
connectAttr -f ($quatNodeList[2]+".outputQuat") ($quatNodeList[3]+".inputQuat");

// アトリビュートの設定
setAttr ($quatNodeList[1] + ".inputRotateX") 180;

~様々な処理~

delete $quatNodeList;    // 最後にノードを削除する

こちらは上図のノードのつながりをMelで再現したものです。やっていることはノードを作成してアトリビュートをつなげているだけです。
あとは用途に応じてオブジェクトの角度のノードをつなげれば欲しい結果を入手していることです。
少し工夫をしてるところは、使い終わった後はゴミノードとして残ってしまうので、まとめて消せるようにノード名をリスト化していることです。

ノードを利用してMelでクォータニオンを簡単に使う

結論はこちらですね。ノードを利用すれば純粋なMelだけでもクォータニオンの結果を入手できます。
Melで調べていてクォータニオンで詰まった人はこの方法を試してみてください。

そして、ノードに詳しい人はMelで諦めてた処理がノードを利用するとできると気付いていただければ幸いです。

Author: 中林 伸和