2012年12月31日月曜日

SoftImageと3DSMAXのエクスプレッション/スクリプトコントローラー対照表 その1

自分が今まで色々3DDCCツールを使ってきて、毎回悩む分野の一つにコンストレイント、エクスプレッションやスクリプト等の習得がありました。

この領域はデータ作成の効率化とかに直接関係してくる部分ですが、その分ツール作者達の思想に近い部分でもあるので、ちょっと敷居が高いなと毎回思います。
スクリプトについては、最近各ツール共pythonを使う方向なので、その流れでいずれ統合できるようになって欲しいものです。
最近3DSMAXに触り始めて運良くいろいろ学べ、またいくつかGoogle先生に必死こいて教えてもらった事柄もありましたので、そういった部分をちょこちょこまとめてみます。

とりあえず今回はRigやFカーブ系で使うことの多いエクスプレッションを書こうかと思います。
どう簡潔に書くか悩んだ末にSoftimageと3dsmaxでよく使うエクスプレッション/スクリプトコントローラーの対照表を作りました。

3DSMAXのスクリプトコントローラについては無駄に長々と書いてあるように見えますが、表の後にエクスプレッションを書く時に必要な補足があるので読んでみてください。


挙動説明 SoftImage
(Expression)
3DSMAX
(ScriptController)
  • null_controllerのローカルX軸位置を動かすと
    nullのローカルX軸位置が追従する
  • dummy_controllerの親X軸位置を動かすと
    dummyの親X軸位置が追従する
null_controller.kine.local.posx pass_dummy_controller = ""
objname_dummy_controller = execute("$" + pass_dummy_controller + "pass_dummy_controller")
dependsOn objname_dummy_controller
objname_dummy_controller.inode.posInParent.x
  • null_controllerのローカルX軸回転を動かすと
    nullのローカルX軸回転が0以下で追従する
  • dummy_controllerの親X軸回転を動かすと
    nullの親X軸回転が0以下で追従する
MIN(0,null_controller.local.rotx ) pass_dummy_controller = ""
objname_dummy_controller = execute("$" + pass_dummy_controller + "pass_dummy_controller")
dependsOn objname_dummy_controller
degToRad( amax #( 0, obj_dummy_controller.inode.rotInParent.x))

//補足
1) 3DSMAXは同一シーン内で同じ名前を付けられます。(モデルIDなどで個体判別は可能です)
2) 3DSMAXでは、スクリプトコントローラーの埋め込まれたオブジェクトの挙動が、どのオブジェクトが動くと再計算されるか明示的に指定する必要があります。

3) SoftImageのローカル座標系は3DSMAXでは傾き自体はローカル座標系数値は親座標系でみます。

補足1)は Rig等で同名オブジェクトを持つ構造体を同一シーンに読み込んでくる際に厄介です。
SoftImageは名前が同一でない前提でエクスプレッションを組 めますが、3DSMAXで同じ事をやると先に読んだRigの右足を動かすと後に読んできたRigの右足まで一緒に動く等の不具合が出ます。
問題回避のために、3DSMAXではパス名リテラルを使用して個体判別を行うことができます。

補足2)はコントロールする側のオブジェクト宣言で、スクリプトコントローラ内に dependsOn $オブジェクト名 と書きます。

スクリプトコントローラでは他にも指定方法がありますが、これが一番簡単だと思います

//例示

下記構造体のr_heelの親X位置をr_heel_controllerの親X位置で動かしたい場合、スクリプトコントローラーには次のように書きます。


pass_r_heel_controller = "c_hip01/"
obj_r_heel_controller = execute("$" + pass_r_heel_controller + "r_heel_controller")
dependsOn obj_r_heel_controller
obj_r_heel_controller.inode.posInParent.x

1行目はr_heelの親までのパス名リテラルを入れる変数と捉えてください。
2行目はパス名リテラル入りのオブジェクト名です。これでオブジェクト名確定す。execute()は文字列をオブジェクト化します。
3行目はコントロールする側のオブジェクト宣言です。
4行目でスクリプトコントローラの実行部分を書きます。

ち なみにパス名リテラルはすべてを省略せずに書かねばなりません。

MAXスクリプトではこれを省略できますがスクリプトコントローラーではできません。
この構造を複数別々扱いたい場合は一番上のノード名"c_hip01"を "c_hip02"などと変更してからスクリプトコントローラ内の対象文字列もすべてそれに書き換える必要があります。
また文字列ノードはツリー全部を直書きするので、Rig等エクスプレッションを多数扱う構造体を複数同一シーン内に配置する場合
 スクリプトコントローラ内の文字列を自動で書き換えるスクリプトの支援が必須になると思います。
//



参考文献 : 
Softimage SDK プログラミング ガイド
エクスプレッションによるアニメーション
エクスプレッション関数リファレンス
3DSMAXスクリプトヘルプ
パス名リテラル
スクリプト コントローラ用 dependsOn
インタフェース : INode
文字列値
Number値
コレクションのタイプ