MAYAのPythonスクリプトにMELを組み込んでベクトル計算をする方法

maya_python_melscript_vector_topimage

MAYAはPythonでスクリプトを書けますが、MAYAのデフォルトのスクリプトはMELです。

MAYAでPythonでスクリプトを書けるようになってから大分たつので今はなくなりましたが、Python対応し始めた頃はまだMELと同等のコマンドが使えなかったり、同じコマンドでMELだと問題ないのにPythonだと動かない等のバグがありました。


MAYAのPythonにはMELスクリプトを実行可能にする方法が備わっているのでその様にPythonスクリプトでは実行できない場合はPythonのコードの中にMELを組み込んで対応していました。


しかし現在のMAYAのMELとPythonはバグ対応ではなくMELとPythonそれぞれの固有機能を互いに補完する有効な使い方ができると思います。
この記事では、Pythonスクリプトの中にMELスクリプトを組み込む書き方を紹介したいと思います。


Pythonでベクトル型を扱う場合は numpyモジュールを使うのが一般的ですがMAYAのPythonに標準では入っていません。モジュールをMAYAで使えるようにする事は可能ですが、素のMAYAのPythonでもベクトル計算ができる方法として紹介します。※あくまでも3DCGツールとしてのMAYAの中でのみ成立する方法です。

PythonでMELスクリプトを使えるようにmaya.melモジュールをインポートする

MAYAのロケーションパスをプリントで出力表示するスクリプトです。Pythonの中でMELコマンドを実行してMAYAのロケーションパスを取得しています。

import maya.mel as mm

maya_location = mm.eval("getenv MAYA_LOCATION")
print(maya_location)

説明:

import maya.mel as mm

MAYAのPythonスクリプトで使用できるMELのモジュールをインポートします。

maya_location = mm.eval("getenv MAYA_LOCATION")

MELで書かれたMAYAのロケーションパスを取得する(env)エンブコードをPythonのMELモジュールで実行

print(maya_location)

受け取ったパスをプリントで出力表示します。

結果:

C:/Program Files/Autodesk/Maya2020

MAYAのロケーションパスが出力表示されました。

型の設定は必要ない

セレクトしたオブジェクトの名前をリスト化して3番目の名前をプリントするスクリプトコードをMEL Python Python+MEL それぞれの方法で書きました。

MEL:

string $select_Obj_list[] = `ls -sl`;
print($select_Obj_list[2]);

説明:
MELは型の設定が必要です。このコードではstring型を設定しています。

Python:

import maya.cmds as cmds

select_Obj_list = cmds.ls(sl=True)
print(select_Obj_list[2])

説明:
Pythonなので型の設定は必要ありません。

Python + MEL:

import maya.mel as mm

select_Obj_list = mm.eval("ls -sl;")
print(select_Obj_list[2])

説明:
MELスクリプトを実行して値を返されますが、受け取り側はPythonなので型の設定は必要ありません。


実行:
ポリゴンのプリミティブを生成して選択して、それぞれ実行しました。

selectd objs


結果:

pCylinder1

3つのコードすべて同じ結果になりました。

外部ファイルのMELスクリプトをPythonで実行する

ボタンが並んだウィンドウが生成されるMELスクリプトを

test_mel_code.mel

の名前で保存しました。

MEL:

global proc test_mel_code()
{
window -width 150;
columnLayout -adjustableColumn true;
    button -label "Button test1";
    button -label "Button test2";
    button -label "Button test3";
showWindow;
}


このMELスクリプトをPythonスクリプトで実行します。

Python:

import maya.mel as mm

maya_location = mm.eval("test_mel_code;")


実行:
ボタンが並んだウィンドウが生成されました。

button window

PythonにMELスクリプトを組み込んでベクトル計算をする

MEL にはベクトル計算ができるvector型があります。

MAYAのベクトルは 3 つのfloat値を関連付けてグループ化したものでMAYAのみで成立する独自の概念ですが、他のプログラミング言語では数学の知識を必要とするベクトル計算を簡単に扱えます。※一般的にベクトルは方向と力を表す用法で使いますが、MAYAのvectorはfloat値を3つ並べた集まりを指します。

MELでベクトルは

<<float,float,float>>

で表します。

vector型の変数に代入するには

vector $vec = <<2.3,6.8,1.6>>;

加算減算などの計算も一度に行えます。

例:
2つのベクトルを乗算します

vector $vec_multi = <<3.6,8.3,4.1>> * <<52.8,1.2001,7.30000>>;
print($vec_multi);


結果:

229.97083 229.97083 229.97083

3.6*52.8 8.3*1.2001 4.1*7.30000
3つの計算が一回で終わりました。

上記を踏まえて今度はPythonスクリプトにMELのベクトルを組み込んだのが以下のコードです。

MEL と Python+MEL の両方で書きました。

MEL:

vector $vec ;
$vec=<<1.2, 2.3, 3.4>> + <<2.6, 3.4, 5.4>>;
float $vecX_float = $vec.x;
float $vecY_float = $vec.y;
float $vecZ_float = $vec.z;

print($vecX_float);
print($vecY_float);
print($vecZ_float);


説明:

vector $vec ;
$vec=<<1.2, 2.3, 3.4>> + <<2.6, 3.4, 5.4>>;

2つのベクトルを加算してvector型の変数「$vec」に代入しました

float $vecX_float = $vec.x;
float $vecY_float = $vec.y;
float $vecZ_float = $vec.z;

加算したベクトル「$vec」のXYZそれぞれの要素をfloat型の変数に代入

print($vecX_float);
print($vecY_float);
print($vecZ_float);

取得した値をprintで出力

これと同じ事をPythonにMELを組み込んで書いたのが以下のコードです。

Python+MEL:

import maya.mel as mm

mm.eval("vector $py_vec ;")
mm.eval("$py_vec=<<1.2, 2.3, 3.4>> + <<2.6, 3.4, 5.4>>;")
mm.eval("float $py_vecX_float = $py_vec.x;")
mm.eval("float $py_vecY_float = $py_vec.y;")
mm.eval("float $py_vecZ_float = $py_vec.z;")
vector_x = mm.eval("min $py_vecX_float $py_vecX_float;")
vector_y = mm.eval("min $py_vecY_float $py_vecY_float;")
vector_z = mm.eval("min $py_vecZ_float $py_vecZ_float;")

print(vector_x)
print(vector_y)
print(vector_z)


説明:

mm.eval("vector $py_vec ;")
mm.eval("$py_vec=<<1.2, 2.3, 3.4>> + <<2.6, 3.4, 5.4>>;")

2つのベクトルを加算してvector型の変数「$py_vec」に代入しました

mm.eval("float $py_vecX_float = $py_vec.x;")
mm.eval("float $py_vecY_float = $py_vec.y;")
mm.eval("float $py_vecZ_float = $py_vec.z;")

加算したベクトル「$py_vec」のXYZそれぞれの要素をfloat型の変数に代入

vector_x = mm.eval("min $py_vecX_float $py_vecX_float;")
vector_y = mm.eval("min $py_vecY_float $py_vecY_float;")
vector_z = mm.eval("min $py_vecZ_float $py_vecZ_float;")

Pythonの変数で値を取得するため、何らかのMELコマンドで実行結果を戻り値として受ける様にします。※この辺りがPython+MELで書く場合のマイナス点ですね。

このコードではMELコマンドの min を使いました。

min float値 float値 

で小さい方の値を戻り値として返します。両方同じ値でもエラーにはならずに戻り値を返します。

print(vector_x)
print(vector_y)
print(vector_z)

取得した値をPythonスクリプトのprintで出力


結果:

3.8
5.7
8.8

1.2+2.6 , 2.3+3.4 , 3.4+5.4 の結果が表示されました。


MAYAの為に作られたMELのvectorなので3次元を扱う事にも長けてます

次は2本の頂点法線のベクトル値をPythonスクリプトで取得してMELスクリプトで2本のベクトルの間の角度を取得します。

import maya.cmds as cmds
import maya.mel as mm

vertex_normal = cmds.polyNormalPerVertex( query=True, xyz=True )

mm.eval("vector $vertex_normal_1 = << %s , %s , %s >>; " % (vertex_normal[0],vertex_normal[1],vertex_normal[2]))
mm.eval("vector $vertex_normal_2 = << %s , %s , %s >>; " % (vertex_normal[3],vertex_normal[4],vertex_normal[5]))
mm.eval("float $rad = `angle $vertex_normal_1 $vertex_normal_2`;")  
deg = mm.eval("rad_to_deg($rad);")  
print(deg)


説明:

vertex_normal = cmds.polyNormalPerVertex( query=True, xyz=True )

Pythonスクリプトで選択したバーテックスフェースの法線のXYZ値を取得

mm.eval("vector $vertex_normal_1 = << %s , %s , %s >>; " % (vertex_normal[0],vertex_normal[1],vertex_normal[2]))
mm.eval("vector $vertex_normal_2 = << %s , %s , %s >>; " % (vertex_normal[3],vertex_normal[4],vertex_normal[5]))

Python+MELスクリプトで2本の法線の値をそれぞれvector変数に代入

mm.eval("float $rad = `angle $vertex_normal_1 $vertex_normal_2`;")

Python+MELスクリプトで2本のベクトルの間の角度をラジアンで取得。その値をfloat変数に代入

deg = mm.eval("rad_to_deg($rad);")  

Python+MELスクリプトでラジアンから角度に変換

print(deg)

Pythonで角度の値をprint出力表示


実行:

バーテックスフェースを2つ選択して実行

selected vt


結果:

54.0802493103

2本の法線の間の角度が表示されました。

まとめ

Pythonスクリプトの中にMELスクリプトを組み込む書き方
及び
PythonにMELスクリプトを組み込んでベクトル計算をする方法

を紹介しました。

PythonでMELコマンドを使うにはMELモジュールをインポートする
import maya.mel as mm

MELで得た戻り値を受け取る時の変数は通常のPython同様に型は必要ない
select_Obj_list = mm.eval(“ls -sl;”)

MELのvector型を使った計算をPythonスクリプトでも使える
maya_location = mm.eval(“angle <<0,0,-1>> <<0,1,0>>;”)


MAYAのスクリプトにPythonを使っているとMELの事を気にする事はありませんがたまにMELのリファレンスを覗いてみるとMELにしかない便利なコマンドが見つかるかも。


以上です


Twitter Facebook Pocket LINE はてブ

おすすめの関連記事:

 

コチラの記事も読まれています
あわせてよく読まれている記事

タグ: ,