この記事はMaya Advent Calender 2019の7日目の記事です。
Mayaでモデリング向けのツールを作ると、選択されてるオブジェクトの頂点位置を取得する事があります。
ただ頂点数が多いモデルでMELやcmdsで全頂点位置を取得すると遅く、モデリング作業に支障が出るレベルです。
処理速度を上げる方法としてよくOpenMayaが紹介されていますが、自分にとっては敷居が高く、cmdsでもっと処理速度を上げる方法がないかと思っていました。
以前の書き方
私は以前はこういう書き方をしていました。
from maya import cmds
sel_obj = cmds.ls(sl=True)
verts = cmds.ls(sel_obj[0] + '.vtx[*]', fl=True)
vert_pos = [cmds.xform(vert, t=True, ws=True, q=True) for vert in verts]
しかしこの書き方で取得すると頂点数が多いオブジェクトだとかなり時間が掛かります。
処理速度を計ってみる
まずシーンにSubdivisions Axis、Subdivisions Height共に200のとても綺麗な球体を作成します。
頂点数は39802です。
この球体を選択して、上記スクリプトをPythonのtimeモジュールを使って計ってみます。
約2秒掛かりました。この速度だとモデリング作業に支障が出るレベルです。
新しい書き方
from maya import cmds
sel_obj = cmds.ls(sl=True)
verts = cmds.ls(sel_obj[0] + '.vtx[*]')
vert_pos = cmds.xform(verts, t=True, ws=True, q=True)
lsコマンドのflフラグを外し、取得した頂点のリストをまとめてxformの引数に与えています。
これで改めて処理速度を計ってみます。
約0.06秒!およそ33倍高速化しました。
XYZごとのリストに置き換える
ただ返ってくる値を見ると1次元配列になっているので、forで処理した時と同じ値を返すには下記コードを加えてXYZごとの2次元配列に置き換えてあげる必要があります。
vert_pos = [vert_pos[i:i + 3] for i in range(0, len(vert_pos), 3)]
まとめ
以上、頂点位置取得の処理速度を上げる方法を上げる方法でした。
物凄く小粒な記事ですが、自分にとっては発見だったのでメモがてら書かせていただきました。
Mayaはこういったリストを引数に取れる関数があり、forで処理するよりもかなり速くなったり、リストを与える時も重複を省く事で速くなる事があります。
自分が見る限り、公式ドキュメントでその引数がリスト可能かどうかを確認出来ないので、テストしてみるしかないのが面倒です…
もし記事内で間違いや不明点等あれば書き込んでいただけると幸いです。
最後までお読みいただき、ありがとうございました。