graphics.hatenablog.com

技術系テクニカルアーティストのあれこれ

Maya .NET API をそこそこ真面目に叩いてみた(シーングラフ編)。

最近ちょっとした心境の変化などもありつつ .NET API が気になってきたので、少し時間をとってちょっと真面目に叩いてみた。結果、環境によっては決して悪くない選択肢だという感触を得たので、ぼちぼちメモっておくことにする。

なお検証用のテストコードについては、普段から大変お世話になっている DF TALK さんの pymel 入門記事のコードを参照した。
デジタル・フロンティアさん、いつもありがとうございます m(_ _)m

github.com
github.com
github.com

検証環境
現時点での結論
  • 制作環境とTA/TDのスキルセットによっては、十分実用的
    • 制作環境が Windows かどうか?
      • Mono 非対応
      • .NET Core の Linux/Mac 移植に期待するには時期尚早
    • Microsoft .NET Framework の扱いに慣れているかどうか?
      • 他の内製 Windows アプリと十分に連携できなければメリットを活かしきれない
      • API だからといって C++ と同じ感覚で導入すると、主に動作速度の面で痛い目をみる
      • 動作速度を求めないのであれば Python API (1.0/2.0) で十分
雑感
  • C++ とは比較にならないほど使いやすい
    • Visual Studio のコードアシストが C++ より充実してる
    • Roslyn Scripting APIpython に近い感覚の運用が可能
  • 「失敗したら例外を投げる」という仕様が予想以上に厄介
    • C++ でいうところの「返り値の MStatus が false になる」状況では常に例外が発生するのが、正直いってめんどくさい
      • 例外を放置するとアプリが落ちてしまう上にロクなデバッグ情報も手に入らないので、ほぼすべてのAPI呼び出しについて、try-catch の実装を検討する必要がある
  • 根っこの部分が C++ API とあまり変わらない
    • C++ であればスタックに積めるところを C# ではヒープ上に new しなければならないので、その負荷がバカにならない
      • 特に MFn 系を毎回 new するのはちょっとどうかと思う
    • イテレータ系のインターフェイスが不十分
      • getConnections や getChild が必要になるケースが多々ある

C# 特有の問題として動作速度への懸念は避けられないので、どちらかというと、C++ よりは Python API を扱うのに近い感覚で運用せざるを得ない。なので、「C++APIの代用としての.NET API」という方向性は思い切って捨ててしまい、「Pythonでできることを.NET上で実現する」という方向性に絞って考えてみた。それがうまくいけば、WPF/WinFormのようなGUIフレームワークとの連携や、VisualStudioの強力さがデメリットを補って余りあるのではないかという皮算用。WPFやWinFormに慣れてしまえばPySide(QT)世代のGUIフレームワークにはもう戻れないし、PythonにもPTVSがあるとはいえ、ネイティブC#に対するMicrosoftの本気度には到底敵わない。何より、Mayaが感知しない範囲に関しては.NETの既存資産を完全に流用できる。

さて、まずはC#の運用について。
基本的にはC++と同じくプラグイン開発としての運用になるんだけど、「アンロードできない問題」が強烈すぎて正直言って全然お話にならない。めんどくさすぎる。なので、Roslyn から導入された Scripting API を使って(やや強引に)これを解決することにした。発想としてはごくシンプルで、「C#をスクリプト実行するコマンドプラグイン」を作って、そこからC#のコードを実行する、というもの。とはいえ実際のところ、C#で書いたコードは最終的にプラグインとしてリリースすることになると思われるので、これはあくまでサンドボックス的な扱いだったり、開発用途と割りきって「プラグインの内部実装を直接呼び出すC#コード」を用意してそれを呼びだすくらいにとどめておく。こういうのがあるとMayaプラグインデバッグ実行する回数=Mayaを再起動する回数を圧倒的に減らすことができる。

次にAPIの運用について。
↑で「Pythonに近い感覚で」とは書いたものの、そうするとmaya.cmdsやpymelに相当するレイヤが存在しないのが地味に効いてくる。ちょっとつらい。実務レベルではかなり厳しいのでは。なので今回は、(ひとまずの検証基盤として)自前でそのレイヤをあつらえてみた。いわゆるホリデープログラミングだから時間管理は適当だけど、1日8時間換算でざっくり3日くらいはここに費やした計算。自分は普段あまりAPIを使わない人なので、慣れてる人ならもうちょっと手早くできると思う。

というわけで、とりあえず DF TALK さんのコードを移植してみた。実際の移植コードはリポジトリにあげてある。

VisualStudioを使う前提で考えれば、まぁまぁ悪くないのでは。

個人的にノードプラグイン以外でAPIを使いたくなるシーンといえば、「大量のシーングラフノードの走査」と「大量の属性値(座標・UV・ウェイトなど)の一括操作」になるのかなと思う。ノードの走査に関しては、イテレータLinqがものすごく相性がいい。属性値の操作に関してはまだなんともいえないけど、scipyやnumpyでどうにかなる範囲に関しては、Math.NETや、その内部実装のMKLを使えばなんとかなるんじゃないかと思ってたりはする。
問題はノードプラグインになるわけだけど、うーん、、特に描画周りがどれだけ使い物になるかはちょっとよくわからない。ちょっとしたロケータ系くらいならなんとかなるかもしれないけど、その中で各種演算がはいってくるとどうかなぁ?

まぁなんていうか、悪くないですよ。