Maya で突き抜けチェックプラグインをつくったはなし

皆様ごきげんよう。毎年恒例 Maya Advent Calender 2023の季節がやってきた。これは12日目の記事。今年は作ったプラグインの紹介をおこなうことにする。



## はじめに
みなさんは「突き抜けチェック」をおこなったことがあるだろうか？たとえばアニメーションを付けているときの衣服と身体の干渉であったり、モデリングにおいては装備品同士の組み合わせによるめり込みの検出とその修正だったりのことだ。場合によってフレーム単位でのブラッシュアップが必要になったりする地道な作業である [^thought] 。この記事ではそのような「突き抜け」のチェックを支援するようなプラグインの紹介と、その製作過程及び動作について解説を行う。

![スカートと脚の接触判定表示図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17220/c0dfbfa9-bc20-7a01-206a-58410e27633d.gif "動作イメージ。スカートの出来がなんかもうあれなのは勘弁な")


## プラグイン 
https://github.com/yamahigashi/MayaIntersectionMarker/tree/main#%E6%A6%82%E8%A6%81

上掲GIFをみていただければ一目瞭然だが、突き抜けカ所に赤いマーカーを表示するだけの単機能プラグインだ。Githubにてビルド済バイナリを配布している。インストールおよび使用方法は

##### インストール
1. **ダウンロード**: Githubのリリースページより最新版 [Zipファイル](https://github.com/yamahigashi/MayaIntersectionMarker/releases/download/1.0.0/MayaIntersectionMarker.zip) を取得
1. **展開**: Zipファイルを解凍する
1. **配置**: mayaモジュールフォルダへ `MayaIntersectionMarker.mod`, `MayaIntersectionMarker` フォルダを配置する

「mayaモジュール」について不慣れであれば マイドキュメントの中の mayaフォルダ内、`modules`フォルダ（なければ作る）に配置すると良い。慣れている方であれば説明不要だろう。お好みの場所に配置してほしい。
![Install3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17220/ef4740ce-15c0-f63a-9b62-1ef24f98cce6.png)



##### 有効化
マーカーをシーンに追加するには、 **メッシュを2つ選び**、メニュー **「Windows > Intersection Marker**」[^menu]を実行

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17220/8ec4245d-eb69-9aab-fe09-13b661ca1bf5.gif)
すると アウトライナに`intersectionMarkerXform`というノードが作成され、そいつが赤色マーカの表示を担う。このノードの移動回転拡縮をおこなうことでマーカのオフセットや表示非表示の切り替えが可能だ。

##### 無効化
有効化の際に作成された `intersectionMarkerXform` を削除すればよい


## 実践例

接触・突き抜けを強調表示できることはわかったが、ではこれはどのように活用できるのか？いくつか列挙してみよう

#### アニメーションチェック（目視）：
一番単純だが、アニメーション作業中に使用する。メッシュの形状や複雑さにもよるが、限定的であればリアルタイムにチェッカーを動かすことが可能だ。とはいえ軽い処理ではないので、普段はオフのほうが作業しやすいだろう。また、ポリゴン数が少ないほど軽くなるため、交差判定を行いたい個所のみに事前にメッシュを分割しておくと良い。

#### アニメーションチェック（バッチA）：
強調表示している赤色だが、突き抜け時は `outputIntersected` (bool)アトリビュートが true になるため、これを機械的に判定することもできる

#### アニメーションチェック（バッチB）：

強調表示している赤色を *プログラム* から判定する。アニメーションをレンダし、その全フレームを赤色検出プログラムにかけてやる。こうすることで、実際見た目に影響するもののみを事前にチェックすることができる。カメラが事前に決まっている場合特に有効だ。（決まっていない場合、各方向何画面か撮影を行うことになる）この際の検出は何で行ってもよいが、サンプルとして、配布ファイル内、`shared\win64\colorscope.exe` をつけている。こいつは画像ファイル中に占める指定色の割合を求めるコマンドラインプログラムだ。こいつに単色デフォルトマテリアルを割り当てたうえで intersectionMarkerを有効にしレンダリングした画像を食わせれば、その瞬間にどの程度めり込んでいるかを判定することができる。
```colorspace.bat
colorspace.exe --file-path 画像ファイルのパス --color 255,0,0 --tolerance 許容プラスマイナス値
```
で画像ファイルに占める指定色（幅）の割合を出力する。Pythonであれば PIL/pillowを用いれば似たような処理を記述できる。ソースコードは Githubレポジトリ内、[supplimentalフォルダ](https://github.com/yamahigashi/MayaIntersectionMarker/tree/main/supplimental/colorscope)にアップしているので適宜参照してほしい。


 #### モデルチェック（バッチ）：
 ゲーム制作では、任意の装備の組み合わせが可能で、結果膨大な組み合わせが発生することがままある。そのような場合、ある程度のレギュレーションをもって製作にあたるのだが、すべての組み合わせで破綻なくモデリングを行うことが現実的でない。そこでバッチ処理で事前に撮影をおこなうことで、まずい不整合がないかを検出し、事前にふるいにかけ、必要なもののみに対し修正を施すことが可能になる。

 このようなチェックの場合、内部で突き抜けていても見た目に影響がなければ放置してよいが、外から見て破綻が起きているものはなるべく検出したい。複数の角度からレンダリングしてやり赤色を検出してやると良い。

---

## プラグイン製作記
ではここからは、このプラグインをどのように作ったのかについて解説していこう

### 技術背景
こういったものを実装しようとした方であれば、愚直な方法での「めり込みチェック」がどのようなものであるかは想像つくであろう。対象メッシュどうし全 face で総当たりをし、交差判定を取ればよい。ただし、この方法ではfaceの数が増えれば増えるほど、計算量が爆発し、かえってこなくなる。

そこで何らかの方法での高速化が必要なのだが、これには ***空間分割*** と呼ばれる手法を用いることができる。空間分割とは、3次元空間を小さな領域やセルに分割する方法のことだ。この分割した空間同士では高速な判定が可能だ。そこれメッシュが属する空間を事前に分割し、そこに各ポリゴンをわりあて分類することで、ポリゴン同士の交差判定の高速化が可能になる。3DCGにおいてはレイトレースや、コリジョン判定などの文脈で出てくることが多い。

今回の場合、メッシュとメッシュ、面と面でのチェックを行う必要がある。既存手法は「面と点」や「面と線」を前提とするところがあったり、一箇所trueとなっただけで探索を中断してよいわけでもない、その違いが今回の課題となる。

今回このプラグインをつくったのも、この空間分割を自分で実装してみるという裏の目的があった。概念として知ってはいたが、自分で手を動かしたことがなかったので改めて学習してみようとおもったしだいだ。いくつか参考にしたものがあるのだが、

https://www.youtube.com/watch?v=MzUxOe5x24w

や @ushio さんの https://github.com/Ushio/NoMemoryBVH （や他のレンダラ、スライドや資料）が大変参考になった。ありがとうございます。空間分割にもいくつか手法があるのだが、今回のプラグインでは、BVH(embree）、Octree, KDTree を実装してみた。結果embreeがすごく早いということが分かった。昔からある話題ではあるのだが、最近でも改良手法が提案されているので、折を見てさらに調査してみたい。

### mayaでのビルド
今回のプラグインは C++ で作っているため、ビルドのための環境構築が必要だ。しかしあたりを見回しても、どのようにmaya用C++の環境構築を行うのかについての情報があまりないため、ここでは筆者のビルド環境について少しばかりその紹介を行う。なお都合上 windows環境を対象とし、CMakeを使うことにする。

##### 事前準備

今回必要なものは以下3点セット
- C++ のコンパイラ
- maya の devekit
- CMake

 それぞれ説明する
 - **C++コンパイラ**: https://visualstudio.microsoft.com/visual-cpp-build-tools/ より `Download Build Tools` を押下し、インストーラを取得、実行し、インストールを行う。`Visual Studio Build Tools 20XX` となっているものを選んでインストールすればOK. mayaバージョンごとに build toolのバージョンも変わるため、一式インストールしておくと良い。コンパイラのみ必要であり、それは **Build Toolsのインストールで済む** ため、 ***Visual Studio本体は不要*** だ。
 - **Maya Devkit**: 配布場所がコロコロかわるのでググってほしい。記事執筆時点で https://aps.autodesk.com/developer/overview/maya の `Download SDKs 2019-2024 for ...` からたどることができるようだ。
 - **CMake**: https://cmake.org/download/ から入手可能だ。CMakeとはビルドプロセスを簡素化するツールで、`CMakeList.txt`と呼ばれる定義ファイルを記述しておけば、自分の環境に応じたビルド設定を自動で行い、それに基づきコンパイラをたたいてくれたりする便利ツールである。C++プロジェクトではビルドを通すのがまず大変なのだが、CMakeがあればだいぶ軽減できる（きがする）。特定環境に縛られないので、mayaプラグインなど複数プラットフォームが対象となるようなプロジェクトには好適だろう。

##### ビルド
レポジトリ内 `build.bat` および `buildAll.bat` 参照。build.batではプラグインの単体でのビルド、buildAll.bat では mayaの各バージョンのビルドおよび、デプロイ用zipファイルの作成までを行っている。このような全バージョン一括ビルドバッチを用意しておくと、mayaのバージョンアップがある場合などの対応が楽になる。

https://github.com/yamahigashi/MayaIntersectionMarker のレポジトリをビルドするにはさらに、依存ライブラリである embree および、glm の手配が必要になる。ご興味おありの方はDLしてビルド試してみていただきたい。embree はBVHの構築、glmは算術演算の支援に使用している。

##### みどころ
DrawOverride をもったロケータノードを登録するにはコツがあり、はまることがある。というか筆者はおおはまりしたはずなのだが、記憶にないのでおもだし次第追記することにする。

### colorspace.exe
余談。わざわざ外部プログラムで用意したのには理由がある。ビルド、インストール、配布の手間を考えると pythonで書いてしまったほうがよいのだが、画像認識を pythonで書こうとすると、pillow/PIL などを用いることになる。のだが、pillow（含むコンパイルが必要な拡張モジュール）には pythonのマイナーバージョン間でのバイナリ互換がないものがある。maya2022以降 Python3 に移行したわけだが、じつは 2022: python3.7.7 2023: python3.9.7, 2024: 3.10.8 とことごとくマイナバージョンが異なるため、単一ファイルで済ませることができない。そのため各バージョンごとに用意する必要があるのだが、なかなかの手間となる。であれば最初からほかのプログラムバイナリ1個用意するほうがいいやとなったので Rustプログラムとしてビルドした。Rustを選んだ理由はC++より、もはや慣れているからね。

## おわりに
このプラグインは、効率的に「突き抜け」問題を解決するために開発した。技術的な側面だけでなく、実践を考慮して製作したつもりだ。この記事を通じて、Mayaの（CPP)プラグインの開発に興味を持つ人が増えることを望む。このようなちょっとしたものをプラグインとして作成することができるようになれば、解決できる問題の範囲を広げることになる。手段が増えると、制作過程で直面する様々な課題に対して、まあ毎日のように事件が起きるのであるが、より多角的で柔軟なアプローチが可能になる。ちりも積もればなんとやら、幅広く影響を及ぼす。みなさまのもとにより快適で生産的な制作環境が築かれることを期待している。

この記事を通じみなさまの創造的な作業が、さらに充実したものになることを願いつつ、この記事を締めくくる。Maya Advent Calendar 2023の次回記事もぜひ楽しみにしている。


[^thought]: ごく個人的な意見だがそんなとこに時間使うんだったらもっと根本的なところに時間使おうぜとおもったりするし、自分のような向いてない人にはとことん向いていない。正直つらい（アニメーションの場合全体的な質感が何となく上がった気がするのも確かなわけなのだが)のでこのようなものを用意したというわけだ
[^menu]: なんでそんなとこに登録しているんだ、mesh以下のほうが妥当だろと筆者も思うわけだが、まぁ訳ありなのでいつかいい方法みつけたら改善するかもしれない。