Python
maya

【MAYA】インスタンスについてのまとめメモ#1

MAYAのインスタンスという機能について、プログラムで扱ってみたら、予想と違う挙動を取ったりしたので混乱しないようにまとめておく。なお、MAYA2018 + MacOS Sierra という環境で調査を進めています。 OSをSierraにいつあげたんだっけ。。

インスタンスとは

基本的には、Flashのシンボル:インスタンスやフォトショのスマートオブジェクトのように、実態を共有したコピーのようなもの。個別の存在がメッシュ形状をいじると全てに変形が適用されたりする。なのだが。

インスタンスの作り方と基本的な挙動

 2018-01-03 1.12.27.png
ノードを選択して 特殊な複製 のオプションからジオメトリタイプをインスタンスにして適用。グループ化のパラメータの違いはよくわからず。作成されたノードの名前は連番で自動で作られる。

プログラムの場合、選択状態を作らなくてもインスタンスが作れる。

pm.instance('node名')

 2018-01-03 1.13.15.png
メッシュのトランスフォームを選択してインスタンス化した場合、形状は一緒だが、位置や大きさ・回転を別の状態にできるノードが作られる。トランスフォームノードが別でメッシュが同じと言うこと。

 2018-01-03 1.13.46.png

メッシュは同じなので片方を変形すると両方の形状が変わる。アウトライナで確認すると同じメッシュノードがぶら下がっているのがわかる。ここまでよし。違和感ない。

作成時の挙動

 2018-01-03 1.16.10.png
一度グループ化したものをインスタンスにした場合、トランスフォームもインスタンスとなった。

 2018-01-03 1.16.37.png
トランスフォームの移動は両者に適用される。

グループもトランスフォームなので、選択しているトランスフォームはコピーされて中身のツリーがインスタンスとなる挙動に見える。ライトやカメラでも同じ挙動となった。(カメラ2台として動くかどうかは未確認)

ただし、メッシュを直接選択している場合は親トランスフォームがコピーされてメッシュがインスタンス化される模様。トランスフォームがない場合どうなるのか?その辺をオプションパラメータで調整できるのか?要調査。

インスタンスの細かい挙動詳細

 2018-01-03 1.14.17.png
マテリアルを変更した場合、両方のマテリアルが変更されそうなもんだが、そうではなく、片方だけ変わる。マテリアルの紐付けがトランスフォーム側にある訳でもない。これは一体?

ノードグラフで確認してみる。

 2018-01-03 14.03.30_.png
まずインスタンスがない場合。シェイプからシェーディンググループ(=マテリアル)へと関連付けがある。トランスフォームとマテリアルの関連はない。

 2018-01-03 3.19.51.png
インスタンスを作成してみた場合。マテリアルへの関連付けが2本ある。 そして、よく見ると インスタンスグループ なる配列アトリビュートの数が増えている。これがインスタンスの正体か。そしてデフォルトでもインスタンスは1つだけ存在する、と言う状態であるらしい。

 2018-01-03 3.21.57.png
片方に違うマテリアルを設定した場合。なるほど、インスタンスグループごとに違うマテリアルに関連が付いている。

 2018-01-03 3.23.23.png
マテリアルのフェイスアサインを行なった場合。属性が増えていたり、自分に戻ってくる属性があったりして、ちょっとオエって感じ。しかしこれはフェイスアサインが複雑であると言う問題なので、今の所は、両者あわせて使うと管理が大変になりそうだという認識程度にしておく。

ノードのパス

 2018-01-03 3.24.44.png
メッシュそれぞれを選択した時のスクリプトログを確認すると、ノード名がフルパス(ロングネーム)で表されるように変化している事に気づく。同じ名前が2つあるので区別するために必要になると言うことはわかる。

meshes = pm.ls(type='mesh')
for m in meshes:
    print(m.longName())

# 出力: |pCube1|pCubeShape1

しかしlsコマンドで一覧を得ると1つしかヒットしない。まあ実態は1つなのでこれもわかる。

t1 = pm.PyNode('pCube1')
s1 = t1.getShape()
t2 = pm.PyNode('pCube2')
s2 = t2.getShape()

print(s1.longName())
print(s2.longName())
print(s1 == s2)

# 出力: |pCube1|pCubeShape1
# 出力: |pCube2|pCubeShape1
# 出力: False

トランスフォームを別々に取得して子供のメッシュを確認すると、この場合は別物が取得できている。PyNodeオブジェクトとしては別物となる。この時、あるPyNodeオブジェクトがどのインスタンスグループ番号所属なのか知るにはどうすればいいんだろう?

s = pm.PyNode('pCube2|pCubeShape1')
info = dir(s)
for mem in info:
    if 'instance' in str(mem).lower():
        print (mem)

# 以下、出力 
#_getAssociatedColorSetInstances
#_getAssociatedUVSetInstances
#getInstances
#getOtherInstances
#instanceCount
#instanceNumber
#isColorSetPerInstance
#isInstanceOf
#isInstanceable
#isInstanced
#isInstancedAttribute
#isUVSetPerInstance
#setInstanceable

インスタンスぽい名前のメンバーを抜き出してみたら結構あった。これを調べてみよう。

疑問点・TODO

  • インスタンス作成オプションのグループ化の設定の違いについて調べる
  • トランスフォームを介さないインスタンス化ができるのか?
  • カメラ・ライトのインスタンスはちゃんとした挙動をするのか?
  • プログラムでインスタンスの扱い

全部対応とは言わないが、宿題は以上。