チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第112回: 知っておくと便利な関数

  • Maya
  • ゲーム
  • コラム
  • スクリプト・API
  • チュートリアル
  • 初心者・学生
Maya Functions

このところのコラムはスキニングに関わる話で、あとはバインド後にジョイントを追加したり、移動したりするときの方法をまとめようと思ったのですが、正確な動作を裏取りするのが大変なので箸休め。

今回はすぐに使える便利な関数について、取りとめなくご紹介します!

Mayaの中にはスクリプトもコマンドも含めて、大量の関数が存在します。コマンドリファレンスに記載があればまだ使われるチャンスもありますが、ドキュメント化されていないものもたくさんあります。

そこで、そんな日陰に暮らす関数にスポットライトを当ててみます!

選択しているコンポーネントのリストを簡単に得る

コンポーネントを選択してMELコマンドで ls -sl を実行すると、コンポーネントのリストを得られます。
ただし、連続したコンポーネントはvtx[0:30]のようにまとまって返されます。

一つのコンポーネントごとに、一つの文字列となるようにバラバラにしたいときは、おなじみの filterExpand コマンドを使用します。例えば頂点をバラバラにしたリストが欲しいときは次のようにします。

filterExpand -sm 31;
コンポーネントのリスト

で、誰もが直面する問題があります。

「-sm (-selectionMask)の番号がわからん…」

コマンドリファレンスでfilterExpandを開くと「頂点がほしければ31番」とテーブルに書かれているのですが、覚えていないと毎度調べる羽目になります。かろうじて31番だけは覚えていますが。

実は簡単にコンポーネントを得られる関数があります。
C:/Program Files/Autodesk/Maya2026/scripts/othersフォルダ内に「get〇〇.mel」というのがたくさんあります。

次のように実行すると、指定したコンポーネントとしてバラしたリストを取得できます。オブジェクトを選択していてもコンポーネントを選択していても、どちらでもOKです。

getEdges();
getFaces();
getVerts();
getUVs();

$edges = getEdges(); // 結果をすぐに変数に入れる

単にpolyListComponentConversionで選択を指定したコンポーネントに変換して、filterExpandをしているだけではありますが、毎回その数行を書くよりは簡単です。
実行すると現在の選択が指定したコンポーネントの種類に変換されます。これは良し悪しありますが。
とりあえずgetと名前のついたMELは要チェック!

ポイントの位置を取得する

xformコマンドでしょ?と思うかもしれませんが、他にも便利なものがあります。
xformでTranslateのワールド座標を得るにはこんなふうに、若干フラグが多くなりがちです。Pythonだと特に書くのが面倒です。(ほんとうに面倒だ、=Trueは!)

MEL
xform -q -ws -t;

Python
cmds.xform(q=True, ws=True, t=True)

代わりにpointPositionというコマンドが使えます。
ポイント、つまり頂点やUVを選択して実行すると、ワールドもしくはローカル座標の位置を返してくれます。Transformノードの位置は返せませんが、ロケーターであればポイントとして扱ってくれるので位置を返します。
引数が少ないので記述しやすく、読みやすいです。コマンド名自体が少々長いですが。

pointPosition; // world
pointPosition -local;
pointPosition " pCube1.vtx[2]"; // 直接コンポーネントを指定できます。
pointPosition

pointPositionコマンドは一度に一つのポイントの座標しか取れないため、大量の座標を一度で取るにはxformを使うことになります。大量の頂点を扱う場合は、pointPositionの方がやや処理が重いので、お好みに応じて使い分けをしてください。マシンによりますが、処理負荷の傾向としては50,000頂点でxformは0.1秒、pointPositionは1.0秒程度。

ロケーターがポイントなのかというと、別にポイントではないのですが、pointPositionコマンドでは一応ロケーターか確認して、ロケーターの内部クラスから座標を取り出しています。ノードのクラス自体が位置に関して関数を持っているのはロケーターならでは。

ロケーターノードのメンバ関数は内部使用用なのでユーザが直接アクセスする方法はありませんが、spaceLocatorコマンドで間接的に結果を得られます。

次のコマンドで、ワールド座標を得られます。(-a, -rフラグは照会モードで使えないので、ワールド座標のみ取得可能)

spaceLocator -q -position locatorShape1;

ノード名を抜き出す、アトリビュート名を抜き出す

これも自前で実装するには地味に面倒です。例えば pCube1.translateX という文字列からノード名やアトリビュート名を取り出すときです。

tokenizeコマンドでドットのところで文字列を分けて…などはもうイヤだ!引数の順番も忘れがち!
代わりにplugNodeとplugAttr関数を使うと簡単に文字列を取り出せて、精神的にもゆとりが生まれます。

plugNode "pCube1.translateX";
// Result: pCube1

plugAttr "pCube1.translateX";
// Result: translate
plugAttr "node.compound.elemX";
// Result: compound.elemX

plugNode.melの中ではtokenizeを実行しているわけですが…。自前で実装するよりも賢くて、例えばアトリビュートの中のアトリビュートのように、ドットがどんどんつながっている場合ははじめのドットで区切ってくれます。

他にも似たような関数があります。
plugAttrNoIndexではインデックスの部分を取り除く事もできます。
plugMultiAttrsでは、マルチアトリビュートの部分だけ見つけることができます。(実在するノードとアトリビュートを指定する必要あり)

plugAttrNoIndex "mesh.vert[1]";
// Result: vert

plugMultiAttrs "pCubeShape1.pnts.xValue";
// Result: pnts

C:/Program Files/Autodesk/Maya2026/scripts/others/plugNode.mel という感じで、関数ごとにそれぞれMELスクリプトがあります。

スクリプトを書いている方にとってはプラグ(plug)という用語が耳慣れないと思いますが、これはNode Editorで見かけるノードのアトリビュートにある接続部分のように想像していただくとよいです。
アトリビュート名だけではどのノードのアトリビュートかわからないので「ノード.アトリビュート」として関わりを明確にします。そしてこれをプラグと呼ぶ感じです。

スクリプトでは単に文字列で名前を指定しますが、C++などのAPIではMPlugというオブジェクトでこの情報を扱います。
もっとも、plugAttr関数などは単にその雰囲気を関数名にしているだけです。文字列処理をしているだけで真のプラグ(MPlug)ではありません…。

とりあえず関数名とかにplugと書かれていれば、スクリプトでは「ノード名.アトリビュート」の文字列でやり取りするのね!と捉えるといい感じです。

アトリビュート: “translate”
ノード: “pCube1”
プラグ: “pCube1.translate”

plugMultiAttrsは本当にオブジェクトのアトリビュートをチェックするので、シーンに実在するノードやアトリビュートを指定する必要があります。それ以外は単に文字列をいじっているので、ドットで区切られた文字列なら何を渡しても動作します。

指定した位置に一番近いUVを取得する

最近のMayaの機能は、少々ややこしいことをしているとPythonを実行していることがあります。
特にデフォーマ系は裏でややこしいセットアップや取り回しをしているので、Pythonの関数をいくつも用意しています。それを拝借すると複雑なことが簡単に行えます。

ここではUV Pinコンストレインが使っている、近接したシェイプのUV値を取る関数を使ってみましょう。

はじめにメッシュを選択して、次にTransformノードを選択します。
下記のPythonスクリプトを実行すると、Transformの位置に最も近いUVの座標を得られます。

指定した位置に一番近いUVを取得する


import maya.cmds as cmds
import maya.internal.common.utils.geometry as geo_utils

# ジオメトリを選択してから、その他位置情報となるTransformを選択。
selectedObjects = cmds.ls(sl=True)
uvSetName = '' # 指定したければ
geomuvs, resStat = geo_utils.getUvsFromClosestPointToTransforms(selectedObjects[0], selectedObjects[1:], normalizedIsoParms=True, uvSet=uvSetName)
print(geomuvs, resStat)

('pSphereShape1', 'map1', [[0.4500000476837158, 0.6500000953674316], [0.4500000476837158, 0.9086366295814514]], ['locator1', 'locator2']) 0

getUvsFromClosestPointToTransforms関数にオブジェクトを渡します。
結果は2つ返されますが、主に使うのははじめの方です。配列の中には、対象のシェイプ名、使ったUVセット名、その後にUV座標と、それに対応するTransform名が来ます。
このようにして3D空間の座標からUV値を割り出せるので、リグのセットアップなどに便利です。

例えばUV PinではなくPoint On Polyコンストレイント(pointOnPolyConstraintコマンド)を使いたいときに便利です。
Point On Polyは選択した頂点のところにコンストレインしますが、実際には頂点のUV値を使っています。上のコードで事前にUV値を割り出せれば、Point On PolyのpointOnPolyConstraintノードにUVを設定することで、頂点以外の狙った場所にコンストレインできます。

pointOnPolyConstraintノードのUV値は、アトリビュートエディタのExtra Attributesのところで設定できます。
アトリビュート名は「pointOnPolyConstraint1.(コンストレインのメッシュ名)U0(V0)」となります。(こんなことをしないでも、はじめから近接したUVのところにコンストレインしてくれればいいのですが…。)

あああ

getUvsFromClosestPointToTransforms関数はC:\Program Files\Autodesk\Maya2026\Python\Lib\site-packages\maya\internal\common\utils\geometry.pyにあります。(geometry.pyには他にも便利な関数があります。)
関数の中を見るとfnMesh.getUVAtPointという行があります。ここでMFnMesh::getUVAtPoint(位置, …)というOpenMayaのAPIを呼び出しています。
MFnMesh::getUVAtPointは総当りでフェースをテストしていきます。Mayaでは大抵は特殊な最適化はしないので、TBBで並列処理でテストするだけです。毎フレームリアルタイムで実行させるような関数ではありませんので。

まとめ

まだまだいろいろな関数があるのですが、とりあえず今回はここまで。
ご興味があれば次の場所を発掘してみてください。

MELスクリプトはC:\Program Files\Autodesk\Maya2026\scripts\othersの中を、
PythonスクリプトはC:\Program Files\Autodesk\Maya2026\Python\Lib\site-packages\mayaの中を見ていただくと、便利な関数が見つかります。

ドキュメントに記載されていない関数は、今後も永続的に存在するのかどうかという不安があるかもしれませんが、20年以上前の関数も現役ですし、まあ大丈夫でしょう。無くなくなれば無くなったで、すぐにエラーが出るので対処はしやすいです。
ちなみに、古い関数を廃止して削除するほうがリスクが高く、とても大変ですので、大抵はそのまま残しています。

ぜひ面白い関数を見つけて活用してください!

製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。