GameDev Destruction Cleanup について


こんにちは篠島です。今回はGame Development Toolの一つ、Destruction Cleanup について説明したいと思います。

 

Destruction Cleanup とは何か?

一言で説明すると、リジッドボディのシミュレーションを効率よく出力する為のツールです。リジッドボディシミュレーションをゲームエンジンに持っていくにはVertex Animation Texture を使うわけですが、前回のVATの記事で説明したとおり、テクスチャのサイズは頂点とフレーム数に依存するわけです。Houdini はPacked Primitive という機能のおかげで全頂点を出力する必要はなく、破片毎に出力する事でテクスチャサイズを小さくできます。ここまでが通常のHoudiniでのワークフローで、Destruction Cleanup を使うことでクラスターや動かないジオメトリ等も一つの塊として一つのトランスフォームを使うことで、更にテキスチャに書き込む情報を減らすことが出来ます

例えば下のようなリジッドボディシミュレーションがあるとします。Pack Primitive で破壊シミュレーションをしているので、破片毎にトランスフォームが存在します。下の図を見て分かる通り、ポイントが495個存在します。ポイント一つ一つにトランスフォーム情報があり、それを元に破片を動かしているわけですね。
下のGIFアニメを見るとわかりますが壁のオブジェクトは複数の破片から構成されており、半分以上は全く動いていません。全く動いていないトランスフォーム情報を書き出すのは無駄なので1つにまとめられれば書き出すデータのサイズが減るのがわかると思います。

 

Destruction Cleanup を使って最適化してみると、ポイント数が175に減少しました。Visualizeによって壁の色が一色になっていますが、これは一つの破片として処理されてることを意味します。他にも位置情報を元に近隣にあるオブジェクトを一つのオブジェクトとしてまとめることでポイントを少なくします。

 

下の図を見てもらえば分かる通り、通常のPacked Primitie をVATで書き出した場合495×89 になり、Destruction Cleanup SOP で最適化した後のVAT のサイズは 174×89 とかなり効率化されました。

 

Destruction Cleanup SOP の使い方

Destruction Cleanup SOP にはインプットが4つあり、それぞれ下のようなインプットを取ります。インプット1と2は絶対必要で、3と4はオプションです。

  1. 静止した状態のジオメトリ(最初のフレーム)
  2. DOPから吐き出されたシミュレーション(キャッシュされたジオメトリ可能)
  3. バウンディングボックス
  4. コンストレイントネットワーク

 

Constraint Network とは

このツールを説明するにあたってコンストレイントネットワークの説明は避けて通れません。コンストレイントネットワークとはシミュレーションされるオブジェクトのコンストレイントを設定したネットワークで、各プリミティブにコンストレイントのタイプ、強さ、などなど色んな値を設定することでシミュレーションを細かくコントロールできます。破壊系エフェクトでは必ず使うことになる物です。例えばシミュレーションしていくとコンストレイントのジオメトリもリアルタイムに変更が加えられ、例えばオブジェクトが一定の値のインパクトを受けるとコンストレイントが外れ broken というグループに含まれます。
Destruction Cleanup SOP はこのコンストレイントネットワークの情報を見ながら細かく最適化をしていきます。

 

 

パラメーターの説明

Input Mode

Input2につなぐものがDOPを直に繋いでいるのか、それともキャッシュしたジオメトリを繋いでいるかの設定です。

 

Output Mode

このノードの出力が最適化されたアニメーションか、インプット1に繋いだ静止した状態のジオメトリか、トランスフォームポイントだけ出力するかを選ぶことが出来ます。

 

Simulation Range

ここで指定したフレームの最初と最後のオブジェクトを比較し、どのオブジェクトがどのくらいバラバラになったかを判断します。

 

Proximity Based と Constraint Based

Proximity Based は破片の距離に基いて処理します。このモードにしてもコンストレイントネットワークをインプット4に繋げて処理することができます。
Constraint Based はコンストレイントネットワークを元に処理します。なのでインプット4が繋がれていることが必須になります。破片でコンストレイントネットワークの部分で破片がバラバラになっていなければ1つの破片として処理されます。
ちなみにこのモードは内部のPythonコード内でC++を使っていて、自分の環境ではエラーが出て使えませんでした。

 

Exclude Disconnected Chunks

インプット4を繋いだ時にONかOFFかを設定できるようになります。コンストレイントネットワークを元に、バラバラになった部分は最適化(一つのオブジェクトにまとめる)しないという意味です。
下のGIFアニメを見るとわかりますが、OFFだと Cluster Search Radius によって近隣の破片が一つのオブジェクトとして扱われてしまいますが、ONにすることでコンストレイントネットワークで破壊されている物は別オブジェクトとして扱われます。

Cluster Search Radius

シミュレーションをした結果、破片同士が似たようなアニメーションをしていた場合、それをまとめて一つの破片にするための距離のスレッショルドです。

Visualize Chunks

Destruction Cleanup SOP によって処理されたオブジェクトを破片毎に色分けします。

Freeze Threshold

指定したフレームの最初と最後を比較し、指定したスレッショルド以下しか動いていない破片は1つの破片としてまとめられます。

Fuse

Destruction Cleanup SOP によってまとめられた破片のポイントをマージします。

Clamped Bounds

インプット3に繋いだバウンディングボックスから外にでたオブジェクトを指定した場所に移動します。こうする事でオブジェクトがかなり遠くまで行ってしまった場合のゲームエンジン内での不動点少数エラーを防ぎます。
下のGIFを見て分かる通り、バウンディングボックスからはみ出た破片は指定した場所(ここでは壁の下の方)に集められているのが確認できます。

 

 

試しにUnityに読み込んでみた結果・・・

さて、VATのテクスチャサイズも小さくなって便利に使えるぞ!と思い試しにUnityでテストしてみた矢先・・・、停止した壁の部分がなぜかFBX内で小さくなっていました(最後のフレームで印を付けてあります)。それになぜかSphereの法線もおかしい・・・。ちなみに手前がDestruction Cleanup SOP で最適化した物、奥側が通常のジオメトリです。
自分の作り方が悪いのかそれともバグなのか・・・。サンプルファイルをUPしようと思ったのですが、ちょっと怪しいので原因が判明し次第改めてブログの方にアップします(HipとUnityファイル含めて)。