見出し画像

Maya ツールのテスト環境を整備してユニットテストを書いた話 Now In REALITY Tech #124

アバターシステムチーム、エンジニアのいぐちです。

アバターシステムチームでは今期から、アセットまわりの運用改善とアートチームの製作効率化をメインミッションとした「テクニカルアート・運用効率化チーム」を立ち上げました。その一環で 3D アートチームが使用している 3D 製作ソフト Maya のツールを受け継いで保守するとともに新規開発も担当することになりました。ツールの開発を担当するにあたりまずは Maya のテスト環境を整えユニットテストを書いたので、紹介しようと思います。

REALITY における Maya の実行環境について

3D 製作ソフトである Maya は Windows だけではなく Mac や Linux でも動作するソフトです。ただ REALITY で 3D アーティストがメインで使用しているのは Windows なので、使用している Maya ツールも Windows での動作が前提となっています。

アバターシステムチームでは従来 Unity に関連する開発をメインに担当することが多く Mac を日常的に使っているエンジニアがほとんどなのですが、出社するたびに Mac と Windows のノートパソコンを 2 台持ち運ぶのは手間なので、ツールを完全に動作させるのは難しくてもユニットテストは可能な限り Mac でも実行できるようにする方針にしました。

なぜ Maya ツールが必要なのか

Maya にはツールを開発するための API があり、それらを使うことで Maya に新しい機能を追加する事ができます。REALITY では衣装などのモデル製作に Maya を使用する場合が多いのですが、海外を含め製作メンバーや環境が多様化するなかで、製作プロセスを最適化したりモデルの品質を均一化させるために、モデルが仕様に沿っているかどうかを検査したり不具合がないかどうかを確認するバリデーションツールや、Unity にモデルをデプロイするためのエクスポータなどを Maya ツールとして開発して運用しています。

Maya からバリデーションツールを起動しているところ

Maya ツールの開発について

ここではあまり詳しくは触れませんが Maya でのツール開発では MEL (Maya Embedded Language)、Python、C++ など複数の言語を使うことができます。REALITY では以下のような使い分けをしており、ほとんどのツールは Python で記述されています。

  • 基本的には Python で書く

  • メッシュの頂点などを高速に処理したい場合には C++ を使う

  • 起動用の Python スクリプトを用意するだけではなく、簡単に呼び出せるように MEL コマンドも用意する

ツールを起動する Python コードは例えば以下のようになります。ここでは UI に関連するコードは qt という名前空間に入れることにしており、UI を使うコードのエントリーポイントは qt.main() という関数に統一しています。

import reality.foo_module.qt
reality.foo_module.qt.main()

さらに以下のような MEL も用意することで、Maya から MEL を叩けば目的のツールが起動するようにしています。

global proc Foo(){
    python('import reality.foo_module.qt')
    python('reality.foo_module.qt.main()')
}

Maya のテスト環境について

Maya で Python のユニットテストを書くのは簡単で、通常の Python の unittest フレームワークがそのまま使用できます。テストは Python で書き、以下のように unittest.TestCase を使ってテスト用のクラスを定義します。

class MaterialTest(unittest.TestCase):
    def test_material_node_type(self):
        """
        マテリアルタイプが適正か
        """
        nodes = reality.commons.get_target_materials(pm.ls())
        results = reality.material.Material.check_material_node_type(nodes=nodes)
        self.assertEqual(len(results), 0)

ユニットテストは Maya を立ち上げた後に Script Editor の Python タブから直接起動することもできますが、mayapy を利用すれば Maya の UI を立ち上げることなくユニットテストを実行することが可能です。mayapy から Maya の API を利用してユニットテストを実行するには以下のように maya.standalone モジュールを利用します。

import maya.standalone

# Maya のライブラリを import するには、先に Maya を初期化しておく必要がある
maya.standalone.initialize(name='python')

import maya.cmds as cmds

def suite():
    """
    テストケースをロードする
    """
    loader = unittest.TestLoader()
    suite = unittest.TestSuite([
        # テストを追加する場合はここにクラスを追加していく
        loader.loadTestsFromTestCase(tests.validator.character.CharacterTest),
        loader.loadTestsFromTestCase(tests.validator.mesh.MeshTest),
        loader.loadTestsFromTestCase(tests.validator.material.MaterialTest),
    ])
    return suite

def test():
    """
    テストケースを実行する
    """
    runner = unittest.TextTestRunner()
    runner.run(suite())

    # Mac では何故か uninitialize がクラッシュするので pass
    if sys.platform == 'darwin':
        pass
    else:
        maya.standalone.uninitialize()

if __name__ == '__main__':
    try:
        # evalDeferred を使って、Maya の準備ができてからテストを実行する
        cmds.evalDeferred(test)
    except:
        logging.error(traceback.print_exc())

今回このようにロジックに対するユニットテストをコマンドラインから実行できるようにしましたが、上記コードを実行してみると Mac では何故か maya.standalone.uninitialize() がクラッシュするという現象に遭遇しました。そのため、上記コードでは Mac の場合シンプルに uninitialize をスキップするという手段でクラッシュを回避しています。この方法で今のところ問題ないようにみえるのですが、根本的な解決策などあればぜひコメント欄などで教えて頂けると幸いです。

プラグインを Mac 向けにビルドする

Mac での Maya ツール開発は、基本的には Python を使っていれば Windows と共通で実行できるのですが、REALITY では高速化のために一部を C++ で開発しており、Mac 用バイナリをビルドしていなかったためすべてを Mac で実行するのは難しいという問題がありました。今回 Maya ツールの開発環境を整備するにあたり、このプラグインも Mac で実行できるようにしました。

Maya のプラグインの開発には Maya devkit という SDK を使います。devkit では C++ で記述されたプロジェクトを CMake でビルドできるようになっていて マクロなど CMake から便利に使えるライブラリが含まれているので、これを使えば CMakeList.txt を簡単に記述できます。

cmake_minimum_required(VERSION 3.22.1)

include($ENV{DEVKIT_LOCATION}/cmake/pluginEntry.cmake)

set(PROJECT_NAME example)

set(SOURCE_FILES
    example.cpp
)

set(LIBRARIES
    OpenMaya
    Foundation
)

ターゲットアーキテクチャに注意する

プラグインのビルド時にはターゲットとなるアーキテクチャに注意が必要です。たとえば Apple Silicon のサポートは Maya 2024 から となるので、それ以前のバージョンの Maya を使っている場合は x86_64 をターゲットにビルドする必要があります。

cmake -H. -Bbuild -G Xcode -DCMAKE_OSX_ARCHITECTURES="x86_64" -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

pip でインストールする依存モジュールなどがある場合、こちらもネイティブバイナリのターゲットアーキテクチャに注意する必要があります。たとえば以下のように pip を実行する際はアーキテクチャを指定するようにします。

arch -x86_64 pip install numpy

外部モジュールのなかにはそもそも Mac に対応していない、という場合もあるので注意が必要です。今回はあくまで開発者用の環境を整えることが目標なので、無理だった場合はあまり深追いしない方針にしています。また、開発が Mac でできるようになったとはいえ最終的は Windows で動作させることになるので、Windows での動作確認は引き続き必要です。

まとめ

今回は Maya ツールのテスト環境を整備してユニットテストを書いた話を紹介しました。

テスト環境を整備しユニットテストを簡単に実行できる環境を整えることで開発効率を上げソフトウェア品質を向上させることが出来るのはもちろんですが、今回さらに C++ のプラグインも Mac に対応させたことで、今まで Windows でしか動かなかったツールが Mac でもほぼ動くようになりました。

とはいっても REALITY の 3D 製作では Windows を使っていることが多いので動作確認を Windows で行うことは引き続き必要ですが、たとえば職場に Mac のノートしかなかった場合でも Maya のツール開発ができる環境が構築できたので、開発効率の向上につながったのではないでしょうか。