VRChatでHoudiniのVATを使う(RigidBody編)

#VATとは?
VertexAnimationTextureの略でメッシュのアニメーションをテクスチャとして出力しUnityで再生する手法です。
事前にアニメーションを計算しておくことで流体のような複雑なシミュレーションや大量のオブジェクトの動作を比較的軽量に実現できます。
VRChat(Quest版含む)でも動作するので他では作れない演出ができます。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">VATパンチ！ <a href="https://t.co/TBb8GL1Szs">pic.twitter.com/TBb8GL1Szs</a></p>&mdash; なまのなまこ (@Iiron_Lung) <a href="https://twitter.com/Iiron_Lung/status/1368862590873526275?ref_src=twsrc%5Etfw">March 8, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

アニメーションのパターンによって種類があり、今回はRigidBodyシミュレーションについて扱います。
シミュレーション対象のメッシュ形状が変化しないシミュレーションであり、破壊表現などに利用できます。

他のパターンはこちら
[VRChatでHoudiniのVATを使う(SoftBody/Fluid編)](https://qiita.com/namanonamako/items/be02d3750c7800e33fc2)

#環境
VRCSDK2-2021.03.22.18.27
Houdini　18.5.499

VRC_SDKをインポートする前後でプロジェクトの設定が変わるので、必ず確認しましょう。
この記事の説明はVRC_SDKインポート済みを想定しています。
<font size =1 color="Silver">軸や色空間が変わるようです。このあたりシェーダー内の回避策がわかる人いたら教えて下さい</font>

Houdiniは無償ライセンス版も存在しますが、VAT用テクスチャにウォーターマークが入るためアニメーションが乱れます。

本記事のサンプルプロジェクトは[こちら](https://github.com/namanonamako/VATforVRChat)

#リソース
VRChat向けに手を加えたVAT用シェーダーをGithubで公開しています。
こちらのunity/shadersフォルダを自分のUnityプロジェクトに配置してください。
出力はPackedPrimitiveを想定しています。
調整中で不具合が残っているかもしれませんので、改善方法があれば連絡いただければ幸いです。

https://github.com/namanonamako/SideFXLabs

#Houdiniでアニメーションを作る
BoxをVoronoi分割して落下させる簡単なアニメーションを例にします。

まずはVoronoi分割。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/f6f98894-28ba-6534-c117-463b2b37d901.png" width=50%>
objレベルに戻って上部ツールから`RigidBodies>RBD Objects`を選択。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/94523e2a-21ea-ea0e-7126-d9ff38a0ea46.png" width=30%>
自動的に落下のシミュレーションが作成されます。
そのままでは無限に落下してしまうので自動生成された`AutoDopNetwork`ノードに入り、上のmergeに`GroundPlane`ノードを新規作成してつなぎます。
最初に作ったBoxの高さを2にして準備ができました。
再生ボタンを押すとBoxが落下して崩れてくれます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/4aed2655-cff6-0f87-667f-89332a7586aa.png" width=60%>

#HoudiniからVATを出力
作ったアニメーションをVATで出力します。
SOP(/obj)からROP(/out)へ移動し`vertex_animation_textures`ノードを作成します。

各項目の設定
`Start/End`：出力するアニメーションのフレーム指定
`Method`：VATの種類　今回はRigidを指定します
`Engine`：Unityをえらび必ず`Initialize Engine`を押す
`SOP Path`：出力するアニメーションノードのパス
`Pack Pscale into Position Alpha`：アニメーションする破片のスケール変化をテクスチャに焼くかどうか　今回はスケールを触っていないので外しておきます。
`Target Texture Size`：破片やフレームが多い場合は大きくしておくといいと思います。
`Paths`：必要な出力物にチェックをつけましょう。今回MaterialとRealtimeDataはいらないので外しておきます。

設定ができたら`Render`ボタンを押して出力
こんな感じになりました。
後でUnity側で値を使うのでHoudiniは閉じないでおきます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/1405c14e-332f-b7bb-5bae-b19146967dfd.png" width=60%>

#Unityに導入
指定したパスにテクスチャとメッシュが出力されているのでUnityのプロジェクトに導入します。
vertex_animation_textures1_mesh.fbx
vertex_animation_textures1_pos.exr
vertex_animation_textures1_rot.exr

導入したテクスチャのインポート設定を変更します。
VATは頂点位置を色として読み書きするので圧縮などされると動きが変わってしまうからです。
`AlphaSource`はHoudini書き出し時の設定に合わせます。
今回は出力時に`Pack Pscale into Position Alpha`を使っていないのでNoneでOK。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/d2beb239-a666-4255-1451-dea2da03ec2f.png" width=60%>

Meshをシーンに配置してマテリアルを割り当てます。
Materialのシェーダーは上記URLからダウンロードした`"sidefx/vertex_rigid_body_shader"`を選択。
PositionMapとRotationMapに出力されたテクスチャを指定します。

マテリアルの各項目はHoudiniの数値を持ってきます。

|Houdini  |Unity  |
|---|---|
|Pivot Min/Max  |Bounding Max Min  |
|Position Min/Max  |Bounding Max1 Min1  |
|Frame Range  |Number Of Frames  |
|Speed  |Speed  |

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/b44ed143-ae9d-c208-8381-68b8423f3c04.png" width=60%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/491b54b6-89a2-7c5f-1d65-d61688fc5a31.png" width=60%>

動きました！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/429626ac-cd1e-a54d-4d73-6c54d2d13f33.gif" width=60%>

VATはシェーダーで見た目だけを動かしているのでメッシュの実体は初期位置のままです。(オレンジ枠線部)
カメラを動かして破片が消えてしまうときはMeshRenderをSkinedMeshRenderに変えてBoundsを大きくしてみてください。
また、同じ理由からMeshColliderなども追従しません。

#おわりに
パラメーターが多く繊細なので変な動きをする場合は設定を見直してみてください。
他の種類のVATも順次追加予定です。

#動かないとき
- テクスチャの設定を見直す  
`Max Size`や`Alpha Source`など設定を変えてみるとうまくいくことがあります
- Houdiniの出力タイプを確認する  
RigidBodyのVATはPackedPrimitiveである必要があります
`vertex_animation_textures`ノードのSOPpathに設定したノードをマウスミドルクリックし、PackedFragmentsと表示されるか確認しましょう。  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/0e834715-d733-fb5b-d6ef-67a19b1e068f.png" width=50%>  
Polygonsになっていた場合は`assemble`ノードを使うことでPackできます。  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495102/4e79012d-344b-c1ab-51de-4fab09e8a2c0.png" width=65%>  
- `Engine`の設定  
Unityを選んだ後に`Initialize Engine`の押し忘れがあると動く向きがおかしくなります
- エクスポート時のエラー
HoudiniのプロジェクトによってはVATエクスポート時にエラーになるようです。(原因不明)同じノード設定を新規プロジェクトで試すと出力できるかもしれません。