Melを今から覚えるのは抵抗があるし、行列を扱いたいのでPythonとNumpyで行こうと思う。
MelをPythonに移植したmaya.cmdではなく、PyMelを使用してみる。
PyMelはSIのpythonスクリプトのようにオブジェクトが帰ってくるので使いやすそう。
ただMaya自体よくわかっていないので習得には時間が掛かるかも。
PyMelメモ
参考PyMEL for Maya — PyMEL 1.0.7 documentatio
mtazmi-Lab: [pymel] pymel始めました
PyMEL Tips
選択したものの名前表示
from pymel.core import * #plane3を選択して実行 a = selected()[0] print a.longName() #|pPlane1|pPlane2|pPlane3 print a.name() #pPlane3 #Mayaでの名前は階層になっている
名前から選択する
from pymel.core import * select(clear=True) #選択を解除する select('|pPlane1|pPlane2|pPlane3') #選択する select('|pPlane1|pPlane2|', add=True) #追加選択する print selected() #選択されているものを表示 #[nt.Transform(u'pPlane3'), nt.Transform(u'pPlane2')]
オブジェクトをリストに追加
from pymel.core import * objList = [] #空のリスト作成 objList.append(PyNode('pPlane1')) #オブジェクトを追加 objList.append(PyNode('|pPlane1|pPlane2')) #オブジェクトを追加 #リストを表示 print objList #[nt.Transform(u'pPlane1'), nt.Transform(u'pPlane2')]
アトリビュートとメソッドの一覧
from pymel.core import * a = selected()[0] print listAttr(a) # 指定オブジェクトのアトリビュート一覧 print dir(a) # 指定オブジェクトのメソッド一覧
位置の設定と位置の取得
from pymel.core import * tf,sh = polyPlane() tf.translate.set(0,2,0) #移動値のセット tf2,sh2 = polyPlane() tf2.setParent(tf) print tf2.attr("translate").get() #アトリビュートのtranslateから位置を取得 #[0.0, -2.0, 0.0] print tf2.translate.get() #アトリビュートのtranslateから位置を取得 #[0.0, -2.0, 0.0] print tf2.getTranslation() #getTranslation()メソッドで位置を取得 #[0.0, -2.0, 0.0] print tf2.getTranslation('world') #getTranslation()メソッドで位置を取得(world) #[0.0, 0.0, 0.0] tm = tf2.getTransformation() #TransformationMatrixを取得 print tm #[[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, -2.0, 0.0, 1.0]] print tf2.getTranslation('world') #TransformationMatrixから移動値を取得 #[0.0, 0.0, 0.0]
アトリビュートの追加と取得
from pymel.core import * oTransf,oShape = polyPlane() #floatのattr追加、セット、取得 oTransf.addAttr('attr1', at='float') oTransf.setAttr('attr1', 2.0) print transf.attr1.get() #2.0 #文字列のatrr追加、セット、取得 oTransf.addAttr('attr2', dt='string') oTransf.setAttr('attr2',"aaaaa") print transf.attr2.get() #aaaaa #matrixのatrr追加、セット、取得 oTransf.addAttr('attr3', at='matrix') oTransf.setAttr('attr3', [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]) print transf.attr3.get() #[[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]] #float3のatrr追加、セット、取得 oTransf.addAttr('attr4', dt='float3') oTransf.setAttr('attr4', [1,2,3]) print transf.attr4.get() #(1.0, 2.0, 3.0) #ベクター配列のatrr追加、セット、取得 oTransf.addAttr('attr5', dt='vectorArray') oTransf.setAttr('attr5', [[1,2,3],[4,5,6],[7,8,9]]) print transf.attr5.get() #[dt.Vector([1.0, 2.0, 3.0]), dt.Vector([4.0, 5.0, 6.0]), dt.Vector([7.0, 8.0, 9.0])] #アトリビュートの存在を調べる print oTransf.hasAttr("attr5"), oTransf.hasAttr("attr100") #True False #アトリビュートの削除 oTransf.deleteAttr("attr5")
子供にする
from pymel.core import * a = PyNode('pPlane1') #親にしたいやつをオブジェクトにする b = PyNode('|pPlane1|pPlane2|pPlane3') #子供にしたいやつをオブジェクトにする a.addChild(b) print b.longName() #|pPlane1|pPlane3a
親にする
from pymel.core import * a = PyNode('pPlane1') #親にしたいやつをオブジェクトにする b = PyNode('|pPlane1|pPlane2|pPlane3') #子供をオブジェクトにする b.setParent(a) #親をセットする print b.longName() #|pPlane1|pPlane3
親を取得
from pymel.core import * a = PyNode('|pPlane1|pPlane2|pPlane3') #オブジェクトを取得 print a.getParent() #親を取得 #pPlane2 print a.getParent().getParent() #親の親を取得 #pPlane1 #ちなみにこれでも行けた print a.getParent(0) #自分を取得 #pPlane3 print a.getParent(1) #親を取得 #pPlane2 print a.getParent(2) #親の親を取得 #pPlane1 #親をすべて取得する場合はこれ parentsList = a.getAllParents() print parentsList #[nt.Transform(u'pPlane2'), nt.Transform(u'pPlane1')]
マテリアル作成と割り当て
from pymel.core import * #ランバートのマテリアルを新しく作って、一個選択されているものに割り当てる sel = selected()[0] shader , shadingEngine = createSurfaceShader("lambert") sets(shadingEngine,forceElement=sel) print shader #lambert2 print shadingEngine #lambert2SG ''' SurfaceShaderというのはSIのマテリアルのsurfaceに指すシェーダーのようなもの? [シェーダー名SG]というのは何?マテリアル? '''
使用しているマテリアルの取得
上のシーンでpPlane2に新規ランバートを割り当て、pPlane2を選択して実行したfrom pymel.core import * #シェイプで使用しているSG?というものが取得できる oShape = selected()[0].getShape() sg = oShape.outputs(type='shadingEngine') print sg[0] #lambert2SG ''' lambert2SGというのが取得できる ハイパーグラフで見るとシェイプの先にlambert2SGに繋がっているのでoutputsプロパティで取得できる。 多分SGはシェーディンググループのことで、サーフェイス、ボリュームディスプレイスを入力に持つマテリアルのこと。 シェーディングエンジンってシェーディンググループと同じこと? ''' sg = oShape.shadingGroups() print sg[0] #lambert2SG ''' これでも同じものがとれた ''' #SGが繋がっているものを取得してみる oConnections = sg[0].connections() for elem in oConnections: print elem ''' lightLinker1 materialInfo1 lightLinker1 renderPartition lambert2 pPlane3 pPlane2 ''' #SGが共有されているシェイプのトランスフォームノードも含まれている #下記はSGのサーフェイスシェーダーに接続されているものを取得する方法 print sg[0].surfaceShader.connections()[0] #lambert2
子供を取得
from pymel.core import * obj = PyNode('pPlane1') oChildren = obj.getChildren() for Child in oChildren: print Child ''' pPlaneShape1 pPlane2 pPlane3 pPlaneShape1ってなんだ? nodeTypeというのを確認 ''' for Child in oChildren: print Child.nodeType() ''' mesh transform transform pPlaneShape1はmeshというノードタイプらしい。 それ以外は mayaの場合これらも自身の子供として取得されてしまう。 なのでノードタイプでマスクする必要がある。 (getChildren()でマスク機能はないのかな?) ''' for Child in oChildren: if Child.nodeType() == "transform": print Child ''' pPlane2 pPlane3 '''
子孫を取得
#一つ選択してその子孫をノードタイプを指定して取得(ここではpPlane1選択後に実行) from pymel.core import * def getDescendants(obj,nType): oChildren = obj.getChildren() for Child in oChildren: if Child.nodeType() == nType: objList.append(Child) getDescendants(Child,nType) return objList obj = selected()[0] objList = [] print getDescendants(obj,"transform") #[nt.Transform(u'pPlane2'), nt.Transform(u'pPlane4'), nt.Transform(u'pPlane5'), nt.Transform(u'pPlane3')]
削除
複数オブジェクトの削除の例from pymel.core import * objs = [PyNode('pPlane1'),PyNode('pPlane3')] delete(objs)
matrixを作成
import pymel.core as pm m = pm.datatypes.Matrix([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]) #or m = pm.datatypes.Matrix(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)
PyMelMatrix to NumPyMatrix
import pymel.core as pm import numpy as np #PymelMatrix m = pm.datatypes.Matrix([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]) #toNymPyMatrix a = pm.datatypes.Matrix([[m[0,0],m[0,1],m[0,2],m[0,3]], [m[1,0],m[1,1],m[1,2],m[1,3]], [m[2,0],m[2,1],m[2,2],m[2,3]], [m[3,0],m[3,1],m[3,2],m[3,3]]])
NumPyメモ
NumpyをMayaのPythonで使えるようにする
[GUIDE] Numpy+Scipy for Maya Windows 64 bit
このページのリンク先のNumpyを解凍して"\ProgramFiles\Autodesk\Maya2016\Python\Lib\site-packages"に入れただけ
参考
私訳「暫定的 NumPy チュートリアル」 - naoya_t@hatenablog
良いもの。悪いもの。: SciPyの使い方: 行列演算
python/numpy - 機械学習の「朱鷺の杜Wiki
NumpyとScipy
モジュールをインポートする書き方
#安全性◎ 手間× | 都度numpy.を付ける import numpy a = numpy.array([1,2,3]) #安全性◎ 手間○ | 任意の省略文字に置き換える。この場合都度np.を付ける(よく使われている) import numpy as np a = np.array([1,2,3]) #安全性× 手間◎ | 他モジュールと名前の衝突が起こる可能性が或る from numpy import * a = array([1,2,3]) #安全性〇 手間◎ | 衝突を避けるため必要なものを部分的にしか読み込まない。 from numpy import array,linalg a = array([1,2,3]) length = norm(a)
Numpyの配列
numpy.array(リスト)from numpy import * arr = array( [0, 1, 2, 3, 4, 5] ) #0,1,2...5までの配列を作る arr = array( [0, 1, 2, 3, 4, 5], dtype=int64 ) #dtypeを指定する場合 print arr #[0 1 2 3 4 5] print len(arr) #配列の要素数 #6 print arr[3] #3番目の要素 #3 print arr[3:] #3番目以降の要素 #[3 4 5] print arr[1:4] #1番目から3番目の要素 #[1 2 3] arr[1:4] = 0,-1,100 #1番目から3番目の要素変更 print arr #[ 0 0 -1 100 4 5] print (where(arr>0,arr,3))#0より大きいものは3 #[ 3 3 3 100 4 5] print sort(arr) #ソート #[ -1 0 0 4 5 100]
NumPyの2次元配列
from numpy import * #2次元配列の作成(型の指定つき) a = array([[12,11,10,9], [8,7,6,5], [4,3,2,1]],dtype=float) print a ''' [[ 12. 11. 10. 9.] [ 8. 7. 6. 5.] [ 4. 3. 2. 1.]] ''' a = a.astype(int32) #後から型を変えることも可能 print a ''' [[12 11 10 9] [ 8 7 6 5] [ 4 3 2 1]] ''' print a.ndim #次元数 #2 print a.size #サイズ #12 print a.shape #次元の要素数 #(3L, 4L) print a.dtype #要素のデータ型 #int32 print a[0] #0行目の取得 #[12 11 10 9] print a[:,0] #0列目の取得 #[12 8 4] print a[0][0] #0行目0列目の取得 #12 print a*a #掛け算。行列の掛け算ではないので注意 ''' [[144 121 100 81] [ 64 49 36 25] [ 16 9 4 1]] ''' print sqrt(a) #平方根 ''' [[ 3.46410162 3.31662479 3.16227766 3. ] [ 2.82842712 2.64575131 2.44948974 2.23606798] [ 2. 1.73205081 1.41421356 1. ]] ''' print sort(a) #ソート ''' [[ 9 10 11 12] [ 5 6 7 8] [ 1 2 3 4]] ''' print sort(a, axis=0) #列でソート ''' [[ 4 3 2 1] [ 8 7 6 5] [12 11 10 9]] ''' print sort(sort(a), axis=0) #行でソートした後に列でソート ''' [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] ''' print sort(a, axis=None) #1次元としてでソート #[ 1 2 3 4 5 6 7 8 9 10 11 12] for i,elem in enumerate(a): #インデックスも取得できる print i,elem ''' 0 [12 11 10 9] 1 [8 7 6 5] 2 [4 3 2 1] ''' print a.sum() # 合計 #78 print a.max() # 最大値 #12 print a.min() # 最大値 #1
reshape
from numpy import * a = numpy.arange(0, 12, 1) print a #[ 0 1 2 3 4 5 6 7 8 9 10 11] print a.reshape(2, 6) ''' [[ 0 1 2 3 4 5] [ 6 7 8 9 10 11]] ''' print a.reshape(4, 3) ''' [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]] '''
Numpyでベクトル演算
配列を使うだけ。from numpy import * v1 = array( [ 1, 2, 3 ] ) v2 = array( [ 0, -1, 2 ] ) print v1 + v2 #足し算 [1 1 5] print v1 * v2 #要素の掛け算 [0 -2 6] print dot(v1,v2) #内積 4 print cross(v1,v2) #外積 [ 7 -2 -1] print linalg.norm(v1) #長さ 3.74165738677 print v1/linalg.norm(v1) #正規化 [ 0.26726124 0.53452248 0.80178373]
行列はmatrix
リストまたは文字列から作成するfrom numpy import * print(matrix('1 2 3')) #1×3行列を文字列から作成 #[[1 2 3]] print(matrix([1,2,3])) #1×3行列をリストから作成 #[[1 2 3]] print(matrix('1; 2; 3')) #3×1行列を文字列から作成 ''' [[1] [2] [3]] ''' print(matrix([[1],[2],[3]])) #3×1行列をリストから作成 ''' [[1] [2] [3]] ''' print(matrix('1 2 3; 4 5 6; 7 8 9')) #3×3行列を文字列から作成 ''' [[1 2 3] [4 5 6] [7 8 9]] ''' print(matrix([[1,2,3],[4,5,6],[7,8,9]])) #3×3行列をリストから作成 ''' [[1 2 3] [4 5 6] [7 8 9]] '''
配列と行列を間違えないこと
似てるけど掛け算すると値は違うfrom numpy import * arr = array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]]) mat = matrix([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]]) print arr.shape #各要素数 #(3L, 3L) print mat.shape #各要素数 #(3L, 3L) print arr + arr #配列の足し算 ''' [[ 2 4 6] [ 8 10 12] [14 16 18]] ''' print mat + mat #行列の足し算 ''' [[ 2 4 6] [ 8 10 12] [14 16 18]] ''' print arr * 3 #配列を定数倍 ''' [[ 3 6 9] [12 15 18] [21 24 27]] ''' print mat * 3 #行列を定数倍 ''' [[ 3 6 9] [12 15 18] [21 24 27]] ''' print arr * arr #配列の掛け算 ''' [[ 1 4 9] [16 25 36] [49 64 81]] ''' print mat * mat #行列の掛け算 ''' [[ 30 36 42] [ 66 81 96] [102 126 150]] '''
配列でも行列の演算はできた
配列の場合で行列の掛け算を行うにはdot関数を使う。行列演算の他の関数も使用できる。from numpy import * arr = array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]]) mat = matrix([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]]) print arr.dot(arr) #配列でも行列の掛け算ができる arr * arr はダメ ''' [[ 30 36 42] [ 66 81 96] [102 126 150]] ''' print mat * mat #行列の掛け算 mat.dot(mat) でも良い ''' [[ 30 36 42] [ 66 81 96] [102 126 150]] ''
行列を配列に格納する場合
from numpy import * #arrayの中に入れるとうまくいかなかったのでリストにする。またはリストにappendで入れていく。 a = [ matrix('1 2 3; 4 5 6; 7 8 9'), matrix('10 20 30; 40 50 60; 70 80 90'), matrix('-1 -2 -3; -4 -5 -6; -7 -8 -9') ] for i,elem in enumerate(a): print i ,repr(elem) ''' 0 matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 1 matrix([[10, 20, 30], [40, 50, 60], [70, 80, 90]]) 2 matrix([[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]) '''
行列の演算
from numpy import * a = matrix([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9]]) b = matrix([[ 9, 8, 7], [ 6, 5, 4], [ 3, 2, 1]]) print a * b #行列積 a.dot(b) でもよい ''' [[ 30 24 18] [ 84 69 54] [138 114 90]] ''' print a.I #逆行列 linalg.inv(a) でもよい ''' [[ -4.50359963e+15 9.00719925e+15 -4.50359963e+15] [ 9.00719925e+15 -1.80143985e+16 9.00719925e+15] [ -4.50359963e+15 9.00719925e+15 -4.50359963e+15]] ''' print a.T #転置行列 transpose(a) でもよい ''' [[1 4 7] [2 5 8] [3 6 9]] ''' print a.diagonal() #対角要素をベクトル化 diagonal(a) #[[1 5 9]] vec = a.diagonal() #対角要素をベクトル化 c = matrix(zeros((3, 3), int)) #代入用のマトリクス作成 fill_diagonal(c,vec) #対角要素をマトリクスへ代入 print repr(c) ''' matrix([[1, 0, 0], [0, 5, 0], [0, 0, 9]]) ''' v = array([2,4,6]) print a.dot(v) #行列とベクトルの積 #[[ 28 64 100]]
0 件のコメント:
コメントを投稿