vopで双曲線関数を組んでみる


# vopで双曲線関数を組んでみる

vopで組もうと思ったのはvexに関数coshはあるのに~~vopのノードにはなかった~~のが大きな理由です。（記事を書いた後に教えてもらったのですがTrigonometric Functionsというノードがあり、coshや他の関数も使えるみたいです）
wikiとかで調べたところ式自体はシンプルだったのでとにかくやってみようと思ってやったら上手くいった、という結果オーライなセッティングだったりします。
途中悩んだのは指数関数というキーワード、ぶっちゃけ説明見ても何のことかよく分からなかったけどvopのmathノードのカテゴリの中に
Exponential VOP node
というのがあったので試しに使ったら上手くいったのでそのまま使うことにしました。

ちなみにVEXにはfunctionについてはここにあります
http://www.sidefx.com/docs/houdini/vex/functions/cosh
ぶっちゃけエクスプレッションを使えばvopでノード組まずにwrangleでシンプルに書けると思いますが、自分じゃコード書くの苦手なのでvop推しでいきます


基本的に数学的な解説やノードの細かい説明はしません。
また、houdiniの基本操作は分かってる前提で説明していきます。
ノードゴリゴリでスマートさには欠ける仕組みかもしれませんが、それなりにプロシージャルにはなっていると思います

この記事の下書き書いてるときにタイムリーに
数学とコンピュータ Advent Calendar 2017
懸垂線（カテナリー曲線）を考える
https://qiita.com/Ushio/items/3648bf64456fd7cea950
なんて記事が投稿されたので数学の話ならこちらの記事が参考になると思います


今回作成するのはcoshのカーブ
![step00.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/81b23a91-bff8-520c-0cb2-55af6bc21262.jpeg)

#実際にvopでcoshを作ってみる

1. ベースのカーブを作成
とりあえずy=0で中心が原点にくるラインを作成
resampleなどで任意の感覚で分割してください

2. Vopを接続し画像の様にノードを組みます
赤字が各ノードで何やってるかです。見ての通り仕組みそのものはかなりシンプルです

![step02.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/18a9073a-2319-4826-9e47-0f6e5db603df.jpeg)


Exponentialノードには入力があるのでparmを挿して任意のパラメーターをセットすると画像の様にカーブが変化します。これで懸垂具合がランダムになるように調整します
![step03.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/386c806d-de61-7be8-6dde-a3f8eaba295e.jpeg)





# 懸垂ケーブルを作ってみる

基本的には直線リニアのカーブもしくはラインポリゴンを作成し、for eachでセグメントごとにvopを適用し目的の様に作っていきます。
どちらかというとvopの処理よりも下準備の方に手間がかかっている感じです

さっきはx値を使用しましたが実際にはx値の代わりにカーブにcurveuアトリビュートを追加して使います
取りあえずこれが今回のノードネットワークの全体像
基本的に左側のカーブの作成について解説していきます。
フック自体はベースカーブのポイントに対して適当なモデルをコピーしてるだけです


![allnodes.png](https://qiita-image-store.s3.amazonaws.com/0/225202/46bc973b-1508-d331-d716-e1d553895857.png)


##1.ガイドカーブの作成

今回使うのはこんな感じのライン
リニアカーブを作ってこれに処理を加えます
![step06_baseline.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/2bbfcac1-dd2d-ceb1-ff70-f6644a5ea627.jpeg)

- ベースとなるガイドカーブの作成、複製
緑枠の中は複数ケーブルを作るための仕込みなので1本だけなら不要になります
XY平面の円形ポリゴン平面を作成し、1のscatterで作るカーブの数を決めます
2-1でPTをベースにidアトリビュートを作成しまた、各ポイントに中心から放射状にノーマルをセットします。2-2でそのアトリビュートをベースにaddでラインを作成します。
![A.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/a5083744-a9c1-651a-4ead-7e6d30330802.jpeg)

2-2でaddでポリラインを作成する前の状態はこんな感じです↓
![2-0.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/8c301c37-28f5-7261-2998-c5e011640a06.jpeg)

- 調整用アトリビュートのセット


2-2以下のノードでfor eachで懸垂化処理を加えるための下準備をしています。
主にケーブル単位、セグメント単位にランダム処理を加えるための個別アトリビュートを加えています。

3でconvertlineで生成された個別セグメントのrestlengthをプリミティブからDetailに入れています。
その時のメソッドをMaximun、Minmumにして最大、最小値をストックしておきます。
![2-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/b0440256-fceb-ec08-e9eb-3348a3b004e8.jpeg)


##2.カーブの懸垂化とポリゴン化

![B.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/08d877b0-1441-d670-12db-bdeeeb5d83e3.jpeg)

ここがメインの処理。
一つ目のfor each内でカーブのセグメントを懸垂化しています（vopの中の説明は後で）
赤で囲ったのは繋ぎ目部分を少し絞るためです。2-1で放射状にノーマルをセットしたのはこのため
アトリビュートをいったん消して、新たにcurveuを追加してランプで両端に値が来るようにする。ここではdisplacealongnormalで内側にポイントを移動しています。
2つ目のfor each内でfuseをかけているのは繋ぎ目を絞った時に頂点連結のしきい値内に複数ケーブルの頂点がきた時の回避用です。別のケーブルと結合してしまうとまずいので回避用にfor each内で個別処理しています。ここではついでに太さもランダムになるようアトリビュートもセットしてあります。あとはconvertでnurbsにして角を滑らかにしてconvertでポリゴンに戻してpolywireでポリゴン化しています。

- for each内の懸垂化処理

文章だけだと説明しづらいのでvopネットワークのスクショにコメントつけました。

少しややこしくなったけど処理そのものはシンプルです。
さっき作ったcoshの仕組みに手を加えていく感じです。
x値の代わりにresampleで加えたcurveuを使いますが、curveuの値は0～1なのでfitで-1～1になるよう再マッピングします。また、coshのカーブだと両端が持ち上がるのに対して、欲しいのはカーブの中心が下にさがる処理。
なのでvopネットワークの画像の様に処理を加えました。
![vop.png](https://qiita-image-store.s3.amazonaws.com/0/225202/052c64fd-6139-19e0-b568-a7eea646e116.png)

![vop2.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/e1133c62-d1ae-6068-0ab0-ff15d4f1b32f.jpeg)

自分自身、記事を書くために見直したらなんでこんな風に組んだんだろう？って思ってしまったので微妙に分かりずらいかもしれません（スミマセン）

##3.フックのコピー

基本は天井にあるフックのイメージなのでカーブの向きにそってノーマルをセットしてコピーしてるだけです。

![C.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/6d49219e-2a94-5cd0-697a-d83156162592.jpeg)

##4.最終結果

各カーブセグメントの懸垂具合をランダムに、間隔の短いとこは抑え目にしてケーブルの太さもランダムにしたので、背景の味付けとしてはまずまずな感じだと思います。
![final.jpg](https://qiita-image-store.s3.amazonaws.com/0/225202/674189bc-b2f0-3d7b-83bf-18bd962cfe38.jpeg)

ザックリとですが以上で説明は終了です。
自分が初めて作ったとき、双曲線の作成自体はすぐできたのですが、ガイドカーブを懸垂線の様にするときに悩みました。
試行錯誤してるうちにできたのが今回の仕組みです。（結果オーライ）
もしかしたら回りくどい処理や余計な処理が入ってるかもしれないし、wrangle使えばノードの数も減ると思いますが、とりあえず現状はこんな感じで組んでます。

自分でこの手のモノを作るときは基本背景の賑やかし用を想定しているので、手っ取り早くそれらしい雰囲気が出るのを目的としています。また、アニメ仕事で使う想定なので100％プロシージャルではなく6割プロシージャルぐらいの感覚で作っています。（まあ、完璧な仕組みを自分で作れないってのもありますが）


こういう形で記事を書くのは初めてなので説明が上手くできてるか自信ありませんが何か質問とかあればコメントとかでお願いします。