Houdiniで鳥の群れを飛ばそう

#はじめに
この記事は　HoudiniApprenticeAdventCalendar2019　16日目の記事です。
Houdini Indie 17.5.327 を使用しています。
hipファイルは[こちら](https://www.dropbox.com/s/ot4msgwj867r1iw/birds.zip?dl=0)

#この記事で作るもの
こんな感じの鳥の群れを作成していきたいと思います。
![instance_result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/6f1eea0d-abef-e29c-bd19-fab3650976bc.gif)
#鳥のモデルを作成
![modeling_all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/f75161b5-57fb-38fb-3ebf-c75a27e9502c.png)


大量に配置することを考慮して、簡単なジオメトリを組み合わせて作ります。
「頭」、「胴体」、「尾」、「翼」をそれぞれ作成して、Merge SOP でまとめます。
「翼」は片側だけをつくって Mirror SOP で反転コピーします。
![modeling_network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/2ea10f59-2299-f176-0f71-f4a2be497988.png)

#はばたきのアニメを作成
はばたきは遅めで作っておき、配置時にスピードを変えられるようにします。
キーフレームを手付けしてもいいのですが、今回はSin関数を使用してアニメをつけていきます。


翼の mirror SOP の上に Transform SOP を追加します。
（回転軸を原点にしたくない場合は pivot translate を設定します。）
Rotate の z に
`sin($F/36*360)*45`
と入力してみます。
![animation_transform1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/004b6709-024a-d21e-d7d7-328237cb6767.png)


すると、-45 ~ 45の間を36フレームで１ループする動きが設定できました。
360を乗算しているのは、sin関数では()の中が360になった時に1ループするためです。
merge1 に Display Frag を立てて確認してみます。
![animation_result1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/ceb7e9e5-9cd6-4684-166a-8efaef688c33.gif)

つづいて、翼の動きが硬いので関節を曲げる動きをつけていきます。
新たに Transform SOP を１つ上に追加します。
Group Parameter で翼の先のほうだけを選択します。
（Group parameter 横の矢印をクリック → SceneViewで面を選択 → Enter）
![animation_selectWing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/6459895c-8cb4-4b2f-c292-782fe976427d.png)

pivot Translate で pivot を回転軸にしたい位置にもっていきます。
(SeeneView で Insert キーを押すと pivot 移動モードになり、SceneViewでも設定できます)
![animation_pivotTranslate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/bc4ca0f6-a52e-5ae1-589b-7129232ea86e.png)

Rotate の z に
`sin(($F-5)/36*360)*45`
と入力してみます。
これで関節の動きがつけられました。
![animation_transform2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/442bc4e9-fdce-0552-bf09-b1c16b75a67b.png)

merge1 に display Frag を立てて確認してみます。
($F-5) とすることで翼の動きから5F遅れて(オフセットされて)
柔らかい動きになっていることがわかると思います。
![animation_result2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/4a2db604-7edb-306c-09e2-9aca1a22a575.gif)

sin関数の使い方をまとめると
`sin(($F-オフセット)/１ループのフレーム数*360)*角度`
といった感じになると思います。

「翼」の Rotate x と y 、「頭」、「尾」、「全体」も同じようにsin関数でアニメを設定していきます。
SOPで親子関係を持ったアニメをつける時は、翼の時と同様に、
<b>上流で子のアニメ、下流で親のアニメ</b>をつけると上手くいきます。
![animation_network_edit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/28a139c4-9fbc-f51f-192a-6b27158cbf9e.png)

さらに全体のコントロールをしやすいように Null に変数をまとめて一箇所で調整できるようにします。
（このやり方の説明は割愛します。詳しくは hip ファイルを見ていただくか、[こちら](https://www.sidefx.com/ja/docs/houdini/ref/windows/edit_parameter_interface.html)をご覧ください。）

動きを調整して、こんな感じのはばたきアニメができました。
![animation_result3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/a39c9bee-a389-5543-383d-f69bf10bddcf.gif)

Transform SOP で全体の大きさを調整して、
File Cache SOP で bgeo連番を1ループ分書き出します。

#パーティクルを作成
シンプルなパーティクルを作ります。
size 3*3 の grid に scatter をつなぎ、こんな感じの source を作ったら popnet につなぎます。
![particle_emitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/7f2b30d3-1832-64e4-fdb3-f76759796272.png)
![particle_source.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/9fae7244-b3c9-ad09-42e4-ae6f8b02551a.gif)

DOP 内は POP Source の Emission Type を「All Points」に変更。
popforce だけ追加してパラメータを調整します。
![particle_popforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/3b3f621e-cace-107c-d6f7-b12a41b4895d.png)

こんな感じのパーティクルができました。
![particle_result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/0674a931-15bb-ddbc-0fc0-da481e66d19d.gif)


#インスタンスを配置
コピーする方法は多数ありますが、今回は Houdini Advent Calendar 2018 19日目の @AokTky_doriさんの記事「[addprimでインスタンス](https://qiita.com/AokTky_dori/items/53057591a2c52b7cf15d)」で紹介されている方法を参考にしています。
この方法はキャッシュファイル連番を高速に並べるのに優れています。
Point Wrangle を追加し、下記のように入力します。
![instance_instancefile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/4bf45e51-a293-a7cd-d4a2-74678faa6bd3.png)
※instancefile のパスは書き出した bgeo のディレクトリを入力してください。
※今回のhipファイルは1001Fスタートにしています。
ここでは書き出された bgeo ファイルを point ごとに Packed Disk で読み込んでいます。
その際のパスのフレーム番号部分にランダムなスピードとオフセットを与えています。
（詳しくは参考記事「[addprimでインスタンス](https://qiita.com/AokTky_dori/items/53057591a2c52b7cf15d)」をご覧ください）

Attribute Randomize SOP で pscale を設定
（まだ反映はされません。）
![instance_pscale.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/f1f6b44f-e75c-24f1-c6a5-f1bfb126b537.png)

Point Wrangle で orient を設定
（まだ反映はされません。）
ここでは v 方向から y 成分を弱めたものを回転方向とします。
![instance_orient.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/b8a920dc-ad13-a3de-86f0-38572fcf40d7.png)


Primitive Wrangle で
point に設定した pscale と orient を primintrinsic の transform に反映します。
（詳しくは参考記事「[addprimでインスタンス](https://qiita.com/AokTky_dori/items/53057591a2c52b7cf15d)」をご覧ください）
![instance_transform.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/a1f9884e-58f0-e573-8ae8-97014a00c78b.png)


最後に不要なアトリビュートとグループを削除してマテリアルを設定します。
僕の環境ではビューポートで鳥がチカチカ消えたりしたのですが、最後にFile Cache を取ると直りました。
![instance_result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/6f1eea0d-abef-e29c-bd19-fab3650976bc.gif)

#使用例
巨大感演出にはとても効果的かと思います！
![exsample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/215daa78-b3b6-12f0-2da1-0f028500eb94.gif)

#終わりに
最後まで読んでいただきありがとうございます。
Houdini を勉強し始めて１年が経ち、少しずつ仕事でも取り入れるようになってきました。
学習にあたって、Houdiniマスターたちの日本語ヘルプ、書籍、チュートリアル、セミナー、ワークショップに助けられました。
この記事が少しでもHoudini日本語コミュニティへの恩返しになればいいなと思います。

SlackのHoudiniコミュニティのほうでもいくつか hip ファイルを共有しているので、
もしご興味ある方は参加してみてください。
https://trello.com/b/7ftxZclJ/houdini%E3%82%86%E3%82%8B%E3%82%86%E3%82%8B%E4%BC%9A
![slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535300/5313edb4-e84c-9c7b-44fd-04747c840708.png)
↑ Slack に上げてる hip ファイル例