CG・コンテンツ制作
SUITE USERS NOTES
Maya;Python で Rig用 ICON を作ろう!!
Maya; Let's Make a Rig ICON with Python
(Used Maya 2012, 2014, 2015)
プロローグ;Prologue
キャラクターアニメーション用の制御Rigの作成において、
見易い、理解しやすい、便利だ、とアニメーターに思わせるような工夫を施す事も
キャラクターセットアップの重要な作業です。
(実はセットアップしている側としては、間違った事をされないように・・と考えていたりしますが・・・)

そこで、てっとりばやく、良い表示物が欲しい・・となった場合、Softimageでは良くNullの表示形状を変更させて使っていました。
Mayaでは、色々なシーンを見ていくと、なんとなく似たような形の表示物を多く使っていることに気が付くことでしょう。
これらはカーブなのですが、その複数のShapeノードを1つに結合して使用したり、Shapeノードを他のものに移し変えて使う、ということも可能なのです。

今回は、良く使えそうなカーブ形状を見真似して作成し、
便利なツールと合わせてまとめたものをPython で構築した例、
として紹介します。

なお、このサイトで掲載している事例の決まり事ですが、
使用に関しては自己責任でよろしくお願い申し上げます。
(Maya2012、2014、2015で動作確認しています)

Please use it as your own risk.
PS
一部カカーブの形状やスクリプトは既に公開されている
ユーザーさんの記述を参考にさせて頂いた部分も含まれています。
ありがたく使わせて頂きました、よろしくお願いします。

Some custom shapes and scripts are refer to what was shown
formaly by users . Great thanks .
Windows7 Professional 64Bit、Intel Core i7-3930K(3.20GHz,6コア/12スレッド)
メモリ16GB、NVIDIA GeForce GTX560 Ti 2GB(メモリ2GB)
maya07_01

ritaro_ml



カーブについて;結合
まずはカーブについて。
作成>CVカーブツールオプションを開くと、カーブの設定画面が表示されます。
カーブの次数 の設定では、当然○ 1 一次が直線になり、○ 3 三次が曲線になります。
maya07_02
このcurve Pythonコマンド の説明で見ると、次数とはdegree(d)のことであり、デフォルトが3 だとわかります。

curvehttp://help.autodesk.com/cloudhelp/2015/JPN/Maya-Tech-Docs/CommandsPython/curve.html

ついでに、スクリプトでカーブを描くには以下のデータが必要だとも気が付きます。

degree(d)カーブの次数。既定は 3 です。(だいたい1か3です。)
目に見えるカーブスパンを作成するには、次数に 1 を足した数のカーブ ポイントが必要です。
たとえば、3 次カーブには、4 個のポイントを配置する必要があります。
point(p)ポイントの x、y、z の位置
knot(k)ノットベクトルにあるノットの値。ノット値ごとに 1 フラグ。

また、アトリビュートエディタでカーブ情報を見ると、
形式次数コンポーネントの表示項目に□CVの表示等があり、全てにチェックを入れると下図のような表示になります。
maya07_03
と、ここで最も重要な点にも気が付いたと思いますが、カーブの形状データはShapeデータであるという点です。
maya07_04
アウトライナーディスプレイ> [レ] シェイプにチェックを入れてシェープノードを表示させると
curveShapeはTransformノードの子という階層構造になっています。
シェープだけ削除すると表示するものが無くなってしまいます。
また気が付くのは、シェープ情報の親を変えることによってカーブを1つの表示物として扱えるようになる、という点です。
なので、カーブの結合とはparent コマンドで行うことになります。

Locatorに正方形のシェープをくっ付けるには、以下の手順で行います。
maya07_05
正方形のカーブを用意し、トランスフォームのフリーズヒストリの削除(編集>種類ごとに削除>ヒストリ)をしておきます。
正方形のシェープを選択、続いて Ctrl + で Locatorのグループノード を選択します。

import maya.cmds as cmds

cmds.parent(relative=True, shape=True)

を実行します。すると、正方形の形がついたLocator になります。

この方法はJointにも有効で、下図のような 選択用のカーブシェープが付いたJoint を作ることも出来ます。
回転方向にロックを付けておくと ICON表示 と 操作 が関連して見えて、アニメーションを付ける時に理解しやすいJointになります。
(Jointの方向と くっ付けたCurveShapeの方向は、くっ付けた後にカーブシェイプの頂点を回転させて見た目に合わせています。)
maya07_06
★追加情報;カーブの長さ
カーブの長さが分る簡単なコマンドをご紹介しておきます。

最初、カーブを選択するとその名前が確認できます。その名前をarclenというコマンドに渡してみると 長さ が分ります。

arclenhttp://help.autodesk.com/cloudhelp/2015/JPN/Maya-Tech-Docs/CommandsPython/arclen.html

import maya.cmds as cmds

print cmds.arclen( 'curve1' )

3.56455588253
maya07_07



ICONの作成;カーブのモデリング
あまりMayaのモデリングについては記述して来てませんが、
カーブの作成で面白い方法がありましたのでちょっと紹介します。

ポリゴンの球を作成し、分割数を30ぐらいにしておき、X軸に90度回転させておきます。
この球を選択した状態で、上のメニューアイコンから 磁石の絵 [ライブサーフェイスなし]ってなっているボタンをクリックします。
すると[ pSphere はライブです。] という表示が出て、球面がカーブを描く際の下敷きになります。
maya07_08
後は、カーブのシェルフで左から3番目のEPカーブツールでカーブを球面上に描いていきます。
maya07_09
左右対称の円形矢印に仕上げます。
maya07_10
回転や移動など編集をした後は、
移動/回転/スケールのフリーズ(修正>トランスフォームのフリーズ)履歴の削除(編集>種類ごとに削除>ヒストリ)をしておきます。
必ずこの2つをやってからデータ化をします。

では次は、出来たカーブ矢印をデータ化してみましょう。



カーブのデータ化;値の取得
今度は、作成したカーブから必要なデータを取得して、最初に紹介したcurve コマンドを使ってカーブを再生成をしてみます。
必要なデータとは、degree(d)=次数、point(p)=ポイントの x、y、zの位置、knot(k)=ノットベクトルにあるノットの値です。

カーブをデータから生成する時のコマンドの書き方は、

cmds.curve(name='作成されるカーブの名前',d=次数,p=ポイントのx、y、z の位置, k=ノットベクトルにあるノットの値)
です。
では、先程作成した円形矢印カーブを使って、各データを取得してみましょう。

1.degree(d) 値の取得;一旦、カーブを選択してみると、このカーブの名前がcurve1だと分ります。
矢印カーブcurve1を選択した状態で以下を実行します。

cmds.getAttr( 'curve1.degree' )

# 結果: 3 # 

2.point(p) 値の取得;いっぺんに取得出来る書き方があります。結構いっぱい出ます。

cmds.getAttr( 'curve1.cv[*]' )

# 結果: [
(-1.1112534999848538, 2.4959175586702926, 0.14370895922185412), 
(-0.9331233132338141, 2.563328364756063, 0.14413296666402145), 
(-0.5768629397317305, 2.698149976927584, 0.1449809815483553), 
・・・ 
(-1.111253499984741, 2.4959175586700435, 0.14370895922183932)] # 

3.knot(k) 値の取得;これはエラーが表示されることもあります。既に同名の Node がある場合など。

その場合でも最後の行を、もう一回実行すると表示したりします。それでもダメな場合は、新しいシーンで試すなどします。

cmds.createNode( 'curveInfo' )
cmds.connectAttr( 'curveShape1.worldSpace', 'curveInfo1.inputCurve' )  
cmds.getAttr( 'curveInfo1.knots[*]' )

# 警告: 'curveShape1.worldSpace[0]' はすでに 'curveInfo1.inputCurve' に接続されています。 # 
# エラー: line 1: RuntimeError: file <maya console> line 2: Maya コマンド エラー # 

cmds.getAttr( 'curveInfo1.knots[*]' )

# 結果: 
[0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 
17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 26.0, 26.0] # 

以上で必要なデータはそろいました。
これを curve コマンドに組み込めばカーブが再生されるはずです。

cmds.curve(name='curve1',d=3,
    p=[(-1.1112534999848538, 2.4959175586702926, 0.14370895922185412),
        (-0.9331233132338141, 2.563328364756063, 0.14413296666402145),
        (-0.5768629397317305, 2.698149976927584, 0.1449809815483553),
        (0.010468042431126258, 2.74599266393373, 0.13862096096210494),
        (0.534990774046297, 2.7106081667485182, 0.16278902069019613),
        (1.2578118068473458, 2.4460833696756445, 0.07247680151801067),
        (1.1012887244926626, 2.4805608419678893, 0.4095576178332147),
        (0.9317770264436573, 2.443702620948175, 0.8666246868009936),
        (1.621582714787527, 2.231512788715753, 0.388169951654192),
        (2.11211977631732, 1.7474728230878585, 0.15802746641556129),
        (2.112113816590134, 1.7474710878882356, -0.15802606206936842),
        (1.6215977326470483, 2.2315179949867296, -0.3881769734764182),
        (0.9317229139545076, 2.4436835328118143, -0.8665980042262186),
        (1.1014901552208554, 2.4806305603810714, -0.4096566117686963),
        (1.257060193799814, 2.445825017900337, -0.07210768771421013),
        (0.5377957915342638, 2.7115718590149593, -0.16416648211247603),
        (-4.190341508384234e-07, 2.7423962511790343, -0.13348022857389805),
        (-0.5377941153976628, 2.7115719418108557, -0.16416635892297352),
        (-1.2570603382320027, 2.445824686716671, -0.07210818047221686),
        (-1.101485531234036, 2.4806318015364774, -0.40965467456429844),
        (-0.931736256758382, 2.4436788944682974, -0.8666050817499987),
        (-1.6215425469082625, 2.2315367306180405, -0.3881506009657419),
        (-2.112315494940899, 1.7474022077243718, -0.15812447493121792),
        (-2.1113625278628154, 1.747729603006845, 0.15839465566800492),
        (-1.6244014485670313, 2.230554546101922, 0.3867996966988733),
        (-0.9212536182159592, 2.447280240913892, 0.8717386960102025),
        (-1.1405579010411544, 2.4672086056127878, 0.3904711209107791),
        (-1.1210216336702121, 2.4863479076509583, 0.22596301311815253),
        (-1.111253499984741, 2.4959175586700435, 0.14370895922183932)],
    k=[0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 
        14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 26.0, 26.0])

実行すると、おお、再生されました!!
maya07_11
でも、うまくいかない時もあります。それは円みたいに閉じたカーブだったりします(この時は次数が1)
その時は、なんと、円のカーブを生成する Mel コマンドを実行しているのです。

mel.eval('CreateNURBSCircle')
mel.eval('DeleteHistory')
o_selected = cmds.ls(sl=True)[0]
o_size = cmds.intSliderGrp('set_size', q=True, value=True)
cmds.xform(o_selected, scale=(o_size, o_size, o_size) )
cmds.makeIdentity( apply=True )



Size設定項目を共通化するGUI ;Python
さて、今回は カーブだけが作られるツールを省みて、それに改善点を入れて Python で作り込む、をしています。
必要になるであろう機能としては、サイズの数値を最初に設定してその大きさで生成させたい、色設定バーをきちんと対応させたい、
カーブの種類は後でも簡単に増やせるような単純なボタンにしたい(その方が起動も速い)、
ある程度のカーブの種類は分類するタブを設けたい、回転やミラーが出来るツールを用意したい・・などがありました。

苦労して作っている色設定バーの構築ウラバナについては、
Maya;Pythonでカスタム・ハイパーグラフを作ろう!!カラーのスクロールバーと色設定;Pythonをご覧ください。

今回用意した GUI は少し凝っていて面白い作りになっています。
気が付いた方も居るかと思いますが、タブが並んでいる上にもボタン等を設定している、というところです。
この設定のおかげで、各タブ共通のツールを用意することが出来ました。

tabLayoutコマンドのPythonドキュメントの例を見てみます。

tabLayouthttp://help.autodesk.com/cloudhelp/2015/JPN/Maya-Tech-Docs/CommandsPython/arclen.html

import maya.cmds as cmds

cmds.window( widthHeight=(200, 150) )
form = cmds.formLayout()
tabs = cmds.tabLayout(innerMarginWidth=5, innerMarginHeight=5)
cmds.formLayout( form, edit=True, attachForm=((tabs, 'top', 0), (tabs, 'left', 0), (tabs, 'bottom', 0), (tabs, 'right', 0)) )

child1 = cmds.rowColumnLayout(numberOfColumns=2)
cmds.button()
cmds.button()
cmds.button()
cmds.setParent( '..' )

child2 = cmds.rowColumnLayout(numberOfColumns=2)
cmds.button()
cmds.button()
cmds.button()
cmds.setParent( '..' )

cmds.tabLayout( tabs, edit=True, tabLabel=((child1, 'One'), (child2, 'Two')) )

cmds.showWindow()

formLayout の中にtabLayoutであるtabsを位置を決めて配置していて、
後から(下から2行目)tabLabelとしてタブ表示部分の
child1、child2であるrowColumnLayoutを設定しています。
記述が前後している上に入り組んでいて、簡単な編集で思い通りになりにくいです。

また、formLayoutを使うとボタン等を細かく位置指定することができるのですが、逆に自由度を奪います。

そこで、formLayoutを使わないで、もっと簡単にタブの配置設定が出来る方法を模索してみます。
maya07_12

import maya.cmds as cmds

window = cmds.window(title='ri Rig ICONs',sizeable=True, topLeftCorner=[200, 200], widthHeight=(420,300))
tabs = cmds.tabLayout(innerMarginWidth=5,innerMarginHeight=5)

tab_cl1 = cmds.columnLayout('  One  ',width=420,height=150,adjustableColumn=True)

cmds.text(label='One',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.scrollLayout(childResizable = 1)
cmds.rowColumnLayout(numberOfColumns=4)

cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')

cmds.setParent('..')
cmds.setParent('..')
cmds.setParent('..')
tab_cl2 = cmds.columnLayout('  Two  ',width=420,height=150,adjustableColumn=True)

cmds.text(label='Two',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.rowColumnLayout(numberOfColumns=4)
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')


cmds.columnLayout('  Three  ',width=420,height=150,adjustableColumn=True)
cmds.text(label='Tools For ICONs',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.rowColumnLayout(numberOfColumns=4)
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')

cmds.setParent(tabs)

cmds.showWindow()

今度はどうでしょうか?

スクリプトの見た目も簡単そうなのに、かなり面白いGUIが作成出来ます。
setParentを多用しているところがポイントで、これを減らしたり増やしたりすると
見た目の変わったGUIを色々と作り出すことが出来ます。
maya07_14
maya07_13
最後から2行目に、cmds.setParent(tabs)という記述があることに注目してください。
このカッコ内の設定でtabsが親だって指定しているので、ここをタブじゃないものに設定すれば、それが一番上に来ます。
そこでボタンの配列を設定したcolumnLayoutを一番上に配置してみます。

window = cmds.window(title='ri Rig ICONs',sizeable=True, topLeftCorner=[200, 200], widthHeight=(420,300))

top_w = cmds.columnLayout('  set size  ',width=400,height=50,adjustableColumn=False)
cmds.rowColumnLayout(numberOfColumns=4)
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.setParent('..')

tabs = cmds.tabLayout(innerMarginWidth=5,innerMarginHeight=5)

tab_cl1 = cmds.columnLayout('  One  ',width=420,height=150,adjustableColumn=True)

cmds.text(label='One',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.scrollLayout(childResizable = 1)
cmds.rowColumnLayout(numberOfColumns=4)

cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')

cmds.setParent('..')
cmds.setParent('..')
cmds.setParent('..')
tab_cl2 = cmds.columnLayout('  Two  ',width=420,height=150,adjustableColumn=True)

cmds.text(label='Two',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.rowColumnLayout(numberOfColumns=4)
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Triangle',width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')

cmds.setParent('..')
cmds.setParent('..')
cmds.columnLayout('  Three  ',width=420,height=150,adjustableColumn=True)
cmds.text(label='Tools For ICONs',width=400,bgc=[0.2,0.2,0.2],align='center' )
cmds.rowColumnLayout(numberOfColumns=4)
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')
cmds.button(label='Shikaku',height=35,width=100,bgc=[0.3,0.3,0.3],annotation='Ue Sankaku')

cmds.setParent(top_w)

cmds.showWindow()

最後から2行目をcmds.setParent(top_w)と変えて、
最初から2行目に top_w の内容である4つのボタンが入ったcolumnLayoutを指定しています。
すると、タブ列よりも上に4つのボタンが配置することが出来ました。

今回のGUIではこのような方法で 各タブでボタン表示部分を変えても
共通で使用する サイズ変更機能 が用意できるレイアウトを作成してみました。
maya07_15




ツール解説
ツールの説明を記述しておきます。

maya07_16
Sizeは右のスライダーを動かしても、直接記入しても設定出来
ボタンを押してカーブが作成される時にそのサイズで作成されます。

Immediate [] はデフォルトでオフになっています。
これをオンにすると、選択されたカーブがスライダーでサイズ変更できます。
選択したものはスライダーでサイズ変更するので、
通常はオフの方が安全でしょう。

[Freeze SRT] は選択状態のカーブを移動/回転/縮尺フリーズします。

2D / 3D / Arrows / Others タブには
それぞれに分類されたカーブ生成ボタンが並びます。

Tools タブ 内には以下のツールがあります。

[MergeCurves] は複数のカーブを1つにまとめます。
次数が異なるもの、階層構造になっているものはマージできません。

[Center Pivot] はピボットの位置を修正します。

Mirrorは各軸を中心にミラーします。
Rotateは各軸に90度ずつ回転します。

Select Colorは選択しているものの色をスライダーで変更します。
[SelColorToSelected] は選択しているものをスライダーの色に変更します。
これは便利で、階層構造選択しているものを一発で色変更出来たりします。



ri_rig_icons.py
という訳でRig用ICON作成ツールri_rig_icons.pyを公開します。
(Pyファイルは シェルフにボタン登録するか、プルダウンメニューに登録して実行します。エントリポイントは、ri_rig_icons_menuです。)

import ri_rig_icons ri_rig_icons.ri_rig_icons_menu()

あくまでも自己責任でお使いください。 use as your own risk.


Rig用ICON作成ツール
(Maya2012,2014,2015)

ri_rig_icons.zip 15.1 KB  2015/02/08 現在



という訳で、次回は... What's Next ...
乞う、ご期待!!Stay tuned ..
戻る 次へ

Twitter

ページの先頭へ