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 件のコメント:
コメントを投稿