targetvを活用する

Houdini Advent Calender 2017、12/20の記事です。
POPを使ってパーティクルシミュレーションをする際に、自分が思った通りにパーティクルを動かすために**targetv**の解説をします。

#すごく便利なのに影が薄い存在
そもそもtargetvって何？という方の方が多いのではないかというぐらいに影が薄い存在のtargetv。
これはその名の通りvのtargetです。
誤解を恐れずにすごく簡単に言えば、targetvを設定しておくとvは最終的にこの値になります。
ただし、その際セットで必ず必要なのが**airresist**です。
これはvがtargetvになろうとする強さやスピードみたいなもので、airresistが大きければ大きいほどvは早くtargetvに近づいていきます。

# 影は薄いが実はよくお世話になっている
targetvとairresistは、明示的に自分で使ったことはないかもしれませんが、POPを使って何かを作ったことがある人であればおよそ大多数の人がこれら両方のアトリビュートのお世話になっていると考えられます。
これら2つのアトリビュートは、POP Dragを使用すると自動で作成、設定されます。

![popdrag.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/027f3ff2-7043-69e9-4162-0a4a0262062f.jpeg)

ここで設定したWind Velocityがtargetv、Air Resistanceがairresistの値となります。

なぜWind Velocityという名前になっているのか、という点に関してですが、風っぽい動きを作る時に使える様に、ということだと思います。そのままですがｗ

では逆に、これを使わずに風を作ろうと思ったらどうしましょう？
POP ForceでX方向にForceをかけるとか？それだと実はパーティクルが毎フレーム加速していくため風っぽく振る舞いません。
風っぽく動かしたいのであればある一定のところで収束する様にしないといけません。
それを実現してくれるのがWind Velocityであり、targetvというわけです。


# どういう計算が行われているのか
POPの計算は全てPOP Solverの中で行われています。
targetvも例外なくPOP Solverの中で計算され、パーティクルのPやvが更新されます。

targetvが計算されている場所は、POP Solverの中のintegrate_forcesになります。

![integrate_forces.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/a6031fae-c76d-caa2-4bde-54708184ba00.jpeg)

integrate_forcesはGeometry VOPで、中身はこうなっています。
![integrate_forces_vop.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/3eff766c-affe-627f-1048-77e05b51362c.jpeg)

Yes, guilty. こりゃ解析に骨が折れそう。。
メモにもなにやら計算の詳細がまとめたるっぽいので、詳細まで解説したい、と思ったのですが諸事情により後日別記事でということにさせて下さい。


# どういうときに使う？
先程、POP DragではWind Velocityという名前で値を設定することが出来ると書きましたが、風のシミュレート以外にも当然使えます。

個人的には最近これを使ってCurve Follow的なことをやっています。
Houdiniには既にPOP Curve Forceというノードがあるのでわざわざ自前で組む必要もないのですが、中身を熟知していないものは使いづらいし、せっかく覚えたテクは使ってみたいということで、実験的に使っています。

# 例
まずは適当にNurbsカーブを引いて、そのカーブをresampleで十分に分割しておきます。とは言えあまりやりすぎない程度で。
それに対してPoly Frameを使ってtangentuを出します。
この際、tangentuの向きが思った方向と違う（多くの場合は逆を向いている）ことがあります。これはカーブを引く方向に依存するためであり、その場合はwrangleなどを使用して逆にしてやります。

で、それをDOP内でpcopenして読むことで、このカーブの情報をDOPに持ち込むことが出来ます。

これにパーティクルの基本的な設定をして、ちょろっとWrangleを書いて、再生えいやっ！！

![pop_follow_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/1f432d7c-6db2-4e8e-2eeb-634aaff3ee5f.jpeg)

・・・は？

全体的にはなんかぼんやりフォローしてますけど、なんか思てたんとちゃう、です。

実はCurve Follow的なことをやりたいとき、そのカーブに沿わせるためにはそのカーブのtangentをforceとして使用するだけではまだ半分しか出来ていません。

これに対してもう1個処理を加えて上げるとこうなります。

![pop_follow_02.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/5841fe00-6a73-8ccb-985a-c78d58ffd244.jpeg)

もう1個の処理というのは、カーブの形状を維持するための力です。
具体的には、カーブ上の最寄りのポイントに向いたvectorをtargetvに足しています。
これによってカーブに沿って進む力とカーブに引き寄せられる力のバランスが取れて、カーブに沿うことが出来るようになりました。

当然この2つの力のバランスでフォローする際の結果は大きく異なります。
とりあえずカーブに沿わせたいのであれば、大体同じぐらいの大きさの力を与えて上げるとまぁなんとなく沿う気がします。

とかなんとか言ったところで、データを見ていじった方が絶対にわかりやすいのでデータを以下にUPしておきます。

#### POP版データ
http://taikomatsu.com/public/hou-adv-cal-2017/curve_follow_pop_01.hip
http://taikomatsu.com/public/hou-adv-cal-2017/curve_follow_pop_02.hip

#### FLIP版データ
http://taikomatsu.com/public/hou-adv-cal-2017/curve_follow_01.hip
http://taikomatsu.com/public/hou-adv-cal-2017/curve_follow_02.hip


余談ですが、これらをベースにもうちょっとモゴモゴやって作ったのがこちらです。
![spiral_force_sample.jpg](https://qiita-image-store.s3.amazonaws.com/0/75701/5f4709e6-df90-77fc-a40e-9700e56225db.jpeg)
https://youtu.be/9incHe2hHVE

これはカーブに沿いすぎて気持ち悪くならないように各種Forceを足したりなどしつつ、ある程度のところで形が崩れて自然になるように調整してあります。

# まとめ
扱いが難しいと思われがちなFLIPでも、Houdiniの良いところを使いながら思い通りにコントロールが出来る方法ということで、これを知った時には狂喜乱舞しました。
とはいえ実際に使ってみると、意外にコントロールが難しい面もあります。しかし何も知らない時との表現力は雲泥の差。
思い通りにコントロールする系の機能は非常にHoudiniっぽくて便利で、なんというか最高です。

是非皆様もお試しください！！