[Maya API]MScriptUtilとMSpace.kWorld

あーーー、はまったはまった。
というかkWorld問題はまだ抜け出せてないんですが。

今Pythonでプラグインを書いてます。
内容がすごくすごく単純なので、まぁ体裁整えてやればすぐに使えるだろ、と思ってたのですが、予想以上にはまってます。

まず最初にはまったのが、ポインタ。
Pythonはご存知の通り、C/C++のように明示的にポインタを操作する言語ではありません。
ですが、MayaAPIはC++で書かれているので、MayaAPIで提供されている関数を使う際に、引数にポインタだとか参照だとかを要求されることがあります。
そういう場合、C++なら言語の機能を使ってそのまま渡せばいいんですが、Pythonだとその辺が面倒です。

例えばMFnNurbsCurveのgetPointAtParamなんかを考えてみます。
これはあるカーブ上の、自分で指定したu地点の位置が取得できます。(という説明であってますか?)
こんな感じで使います。ソースの一部を以下に。

point = OpenMaya.MPoint()
crvFn.getPointAtParam(0.5, point)
print(point.x, point.y, point.z)
#(0, 1.0, 0)

これ見ていただくと分かるように、結果が返り値ではなく、引数として与えたpointに返ってきています。
これはポインタなり参照なりによるものです。

で、↑のソースはPythonなんですが、何が難しいんだ、と思われるかもしれません。
そうそう、難しくないんです。オブジェクトを渡す場合には。

難しいというか、面倒なのは、基本的なデータ型の参照やらポインタを渡す場合です。
つまり、intやらfloatやらの、フツーーーーのデータ型です。

例えば1.0という値を代入したfloat型の変数があったとします。
僕は最初、てっきりそのまま渡せるんだと思っていました。
だってfloat型の変数とは言え、float型のインスタンスでしょ、っていうぐらいのイメージで。
(実はこの辺Pythonではどう扱われてるか詳しくは知りません。どこかで、Pythonでは全てがオブジェクトであるという記述を読んだことがあったような気がして、てっきりそうなんだと思っていました。でも非常に怪しい理解なので、詳しい方、良かったらレクチャーしていただけると助かります:D)

で、試してみたのが以下です。

point = OpenMaya.MPoint(0, 0.5, 0)
u = 0.0
crvFn.getParamAtPoint(point, u)
#Error

さっきとは逆で、座標からuを求めるという関数です。
今回はデータの戻り先がuというfloat型の変数になっているというところがミソ。
なんてエラーが出たか、消しちゃったのでアレですが、なんかとにかくエラーが出ました。
確か、型間違ってるよー、double&くれー、的なエラーだった気がします(ぇ

なんじゃ、無理なのか、と思ってMayaHelpを眺めていたら、Maya Python APIという項目が、、、、
あるんじゃん、、、、
で、ここで、初めて目の当たりにするわけです、MScriptUtilを。。。!!

このクラスは
Utility class for working with pointers and references
ということだそうです。Pythonでしか使わないクラスなんじゃないでしょうか。
つまりこいつを通してポインタとかリファレンスとか、上手い事やってね、ってことっぽいです。

なんとなく、使い方はこう。

point = OpenMaya.MPoint(0, 0.5, 0)
uPtr = OpenMaya.MScriptUtil().asDoublePtr()
crvFn.getParamAtPoint(point, uPtr)
u = OpenMaya.MScriptUtil(uPtr).asDouble()
# 0.5

つまり一旦ポインタもどきを作って、ポインタもどきがデータを受けたら、そいつをさらにdoubleに直す、ということをやっています。
いやー、クソめんどくせーーー。

某ブログの某さん(アーーーッ)もこんなことを仰ってますし、なんか、PythonAPI、意外とアレですね、、、
いろいろはまりまくってます。うぐぐぐぐ、、、

あともう1個、これはMayaAPI自体に関してなのですが、
↑で使ったparamAtPoint関数で、ワールド座標でのポジションがほしいなぁとおもって、OpenMaya.MSpace.kWorldを指定しました。
ら、取れないんですねー、これが。これがまた。

何かといえば、DAGノード渡さないと(?)ダメっぽいということ。
つまりはパスが判明しない限り、変換をリセットできませんよ、という話。
そこってどうにかしてくれるっていうものではないんですね、そうですよね。すみません。

で、それに関しては、ちょっと前のですがこちら(PDF)が参考になりそうです。
こちらに関してはこれから調査開始。

追記 ——
MSpace.kWorldが使いたければ、MDagPathオブジェクトを使用。
まずはMObjectにパスをGETしたいオブジェクトを取得しておく。で、

path = OpenMaya.MObject()
OpenMaya.MDagPath().getAPathTo(obj, path)
crvFn = OpenMaya.MFnNurbsCurve(path)

みたいな感じでOKっぽいです。
これであとはcrvFn内ではkWorld使いたい放題です。多分。

—– 追記ここまで

いろいろ覚えること多すぎる・・・
若輩者には厳しい道のりですが、作りたいノードがいくつかあるので、頑張ります・・・!!

※ざっくり&浅い知識で書いてるので、間違いあるかもしれません。
見つけてしまった方はお手数ですがご指摘下さいませ。

「[Maya API]MScriptUtilとMSpace.kWorld」への7件のフィードバック

  1. アーーーッ

    MScriptUtilは相当苦労しましたねー。これを頻繁に使う所ではPythonよりもC++で書いた方が数倍楽そうです。

  2. 暗黙の了解的なもの多いですよねー。

    DagPathを得るには
    MDagPath::getAPathTo()を使う方法
    MSelectionList::getDagPath()を使う方法
    MFnDagNode::getPath()を使う方法
    があります。
    またtransformへのDagPathを得てMDagPath::extendToPath()でshapeへのDagPathを得るのもよく用いられます。

    http://hohehohe2.hp.infoseek.co.jp/zu41.gif

  3. >某さん
    www

    > MScriptUtil
    いやー、こういう仕組みなのかと理解出来た半面、納得出来ない気持ちもあります笑
    確かにこれが頻発するようなら、間違いなくC++で書いた方が楽だと思いました。
    というかPythonでプラグイン書く利点て、クロスプラットフォーム&バージョンごとのコンパイルいらずなだけですね、ホントに。
    あ、でもincludeがOpenMayaとかぐらいで済むのは楽でしたw

    >hohehohe2さん
    wwwwwwwwwwwwwwww

    > DagPath
    おーー、なるほど、思った以上にたくさん。
    今はMDagPath::getAPathTo()でやってるんですが、何かエラー出てました、、んー、、、
    MayaAPIとお友達になるにはまだしばらくかかりそうです:(

    > GIF
    おおおおこれはわかりやすい!
    参考にさせていただきます。ありがとうございますっっっ!!

  4. >hohehohe2さん
    姉妹品wwwwwwwwwwwww
    これは助かります!ありがとうございます!

  5. 亀レスですが…
    DagPathやらのAPI用のオブジェクトを取得する方法としてPymel使うって方法もありますよ。
    それだけのためにPymel入れるのはあれかもしれませんが参考程度に。
    今まで面倒だったAPIとPython間のデータの取り回しがかなり楽になりましたよ。
    APIの機能の幾分かは直接呼び出すこともできます。

  6. >YAさん
    Pymel!
    使ってみたいと思いつつ使ったことのないモジュールの代表格ですwww
    Pymelの守備範囲ってAPIにも及んでたんですね・・・!!
    Pythonはやはり手軽に使えるのがうれしいです:)
    導入検討してみます。ありがとうございます!

コメントを残す

メールアドレスが公開されることはありません。