Houdiniで螺旋(らせん)を作る

※この記事ではHoudini 17.0.416 Apprenticeバージョンを使用しています。
※Houdiniの基本的な操作やウィンドウの役割等は他のチュートリアルで既に分かっている前提です。


# この記事の目的

Houdiniの練習として「ネジ」を作ろうと思ったのですが、螺旋を作る方法をググっても自分が求めていた超初心者向けなシンプルな記事を見つけられませんでした。
そこでとにかくシンプルで汎用的な螺旋を作る方法として超初心者の自分に対するメモ用も兼ねて記事としてまとめます。

この投稿を読んで下さった方がHoudiniで単純な螺旋が作れるようになる事を目指しています。

![hou_spiral_06_final_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/a904069b-9890-a669-9f40-c875d6baaa8f.png)
↑こんなのが作れます。


# 参考にしたサイト

「Houdini ネジ」で[検索](https://www.google.com/search?q=houdini+%E3%83%8D%E3%82%B8&oq=houdini+%E3%83%8D%E3%82%B8&aqs=chrome..69i57.3620j0j4&sourceid=chrome&ie=UTF-8)した結果出てきた[こちらのブログ](http://graberry.blog70.fc2.com/blog-entry-130.html)の記事を参考にさせてもらいました。


# 「螺旋」はどうやって作るか

[Wikipedia](https://ja.wikipedia.org/wiki/%E8%9E%BA%E6%97%8B)によると、

> 3次元曲線の一種で、回転しながら回転面に垂直成分のある方向へ上昇する曲線である。

と書いてあるので、要するに**点**を**クルクル回しながら上昇**させれば螺旋になるようです。


# ノード構成

![ノード構成](https://qiita-image-store.s3.amazonaws.com/0/336581/f21a0fd4-f4e0-d806-94de-2da11b21c551.png)
各ノードの役割は以下の通りです。

|ノード名           |ノードタイプ        |役割                                                 |
|:-----------------|:------------------|:----------------------------------------------------|
|add1              |Add                |原点から半径分離れたpointを一つだけ作る(点を作る)        |
|copy1             |Copy and Transform |↑のpointを螺旋状(回転しながら上昇)に並べながらコピーする |
|add2              |Add                |全てのpointをつなぐ                                   |


# 作成手順

### 1.元になるpointを作る
まず元になるpointを作ります。そのために**"Add"**ノードを使います。
**"Add"**ノードって何かを追加するために使うノードのような印象を受けるのですが、これを使えばとりあえずpointをひとつ作る事も出来ます。

ネットワークエディタで**TAB**を押してノードを作成します。(ノード名は**add1**とします)

まず、pointを一つ作りたいだけなので**Number of Points**は**1**にします。
次に、すぐ下のチェックボックスをONにして**Point 0**を使えるようにします。
**Point 0**の**X**要素に螺旋の半径(ここでは1)を入れます。

![hou_spiral_03_add1_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/7cab1640-3054-3dac-bb25-de197317788e.png)![hou_spiral_03_add1_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/ff5a102d-4cca-6594-00a2-7efbaa040f35.png)


### 2.pointを螺旋状にコピーする
**"Copy and Transform"**って名前からしてコピーしながらトランスフォーム出来る名前のまんまのノードです。
ネットワークエディタで**TAB**を押してノードを作成します。(ノード名は**copy1**とします)
**add1**の出力をこのノードの入力に繋ぎます。

まず**Total Number**に**121**と入力します。
これでadd1ノードで作ったpointを121個のコピーを作ることになります。
つまり、螺旋を121個の点で作成することになります。

次に**Translate**の**Y**要素に**0.05**、**Rotate**の**Y**要素に**15**と入力します。
これによりコピーする度に15度回転して0.05ずつY方向にずれてコピーしてくれます。

そうすると画像のように螺旋状にpointがコピーされます。
![hou_spiral_04_copy1_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/3bfb0d91-b945-edc6-b92e-15d86d4f2a5e.png)![hou_spiral_04_copy1_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/96b0a1a6-407c-5861-0750-4f5ddd9092f8.png)


### 3.全てのpointをlineでつなげる
**"Add"**ノードって何かを追加するために使うノードのような印象を受けるのですが、これを使えば並んでるpointをつなげて線を作る事が出来ます。

ネットワークビューで**TAB**を押してノードを作成します。(ノード名は**add2**とします)
**copy1**の出力をこのノードの入力に繋ぎます。

**Polygons**タブをクリックして、その中の**ByGroup**を選択します。
そして**Group**の中は空に、**Add**は**All points**を選択します。

これにより、各pointが番号順にlineで繋がれます。
![hou_spiral_05_add2_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/0a224b34-5bef-0062-9cec-cd7a1b9542ef.png)![hou_spiral_05_add2_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/12e54990-8560-93fd-2e91-6f727c7eae53.png)

### 4.とりあえず完成！
"Display points"と"Display points number"の表示をOFFにして確認した結果がこちらです。
![ノード構成](https://qiita-image-store.s3.amazonaws.com/0/336581/f21a0fd4-f4e0-d806-94de-2da11b21c551.png)![hou_spiral_06_final_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/a904069b-9890-a669-9f40-c875d6baaa8f.png)

出来ました！やったね！
**add1**ノードと**copy1**ノードで使ったパラメータの値を調整すると、螺旋の形状が変更出来ます。
とりあえず螺旋が作りたかった人はここで終了です。

# サブネット化＆パラメータ追加で調整しやすくする
**add1**と**copy1**のパラメーターを調整すると螺旋の形が変えられるのですが、現在の状態だと形状が調節が面倒です。
そこでサブネット化して調整用のパラメーターを追加して使いやすくしていきます。

### 1.サブネット化
ネットワークエディタで**Ctrl+A**を押して、**add1**、**copy1**、**add2**とすべてのノードを選択して。**Shift+C**を押して今作ったノードをサブネット化します。
![spiral_07_subnet_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/65e404d3-a8da-5a2d-456a-1d99224d5dbd.png)


### 2.調整用パラメーターの構成を決める
作った**subnet1**にパラメーターを追加していきます。
自分の場合は、次のような想定でパラメータの構成を決めました。

- ポリゴン具合をカッチリ決めたい
- **Tube**ノードと組み合わせて**Boolean**ノードで形を切り出すために、形を揃えやすいように共通のパラメーター(radius, height, cols)を持ちたい

よって、以下のようなパラメーターを追加する事にしました。

|Name          |Label      |Type    |役割                                                 |
|:-------------|:----------|:-------|:----------------------------------------------------|
|radius        |Radius     |Float   |螺旋の半径                                            |
|height        |Height     |Float   |螺旋の高さ                                            |
|cols          |Columns    |Integer |ひとつのループの分割数(SphereやTubeのColumnsと同じ意味) |
|loopNum       |LoopNum    |Integer |ループの数                                            |

目的によっては違うパラメーターの持ち方をした方が使いやすいかもしれません。
その場合は色々考えて試してみてください。


### 3.調整用パラメーターの追加
**subnet1**ノードを選択した状態でパラメーターの右上にあるギアアイコンを押して**Edit Parameter Interface...**を押してパラメーターの編集ウィンドウが開いたら、以下のように上記の表のパラメーターを追加します。
![spiral_07_subnet_3.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/9407a461-da03-7b1c-f6d7-98fd5d5b5b3b.png)

追加したら、パラメータを以下のように設定しておきます。

![spiral_07_subnet_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/6afb088d-8626-6428-2e8c-f6fe4b0c5fc3.png)

- Radius = 1
- Height = 6
- Columns = 24
- LoopNum = 6

### 4.半径のエクスプレッションを設定

調整用のパラメータを元に、subnet内のノードのパラメーターを設定するようにエクスプレッションを組んでいきます。
**subnet1**をダブルクリックしてサブネット内のネットワークを表示します。

**add1**の**Point 0**のXに、以下のエクスプレッションを設定します。
pointがradius分離れているのをクルクル回しながらコピーするので、つまり螺旋の半径になります。

```text:add1/pt0x
ch("../radius")
```

確認のため、ネットワークの階層を一つ戻ります。
**subnet1**の**Radius**パラメーターを変更すると、半径が変わるようになっていると思います。

### 5.螺旋の形を決めるエクスプレッションの設定

再びネットワークビューで**subnet1**内に戻ります。
**copy1**には複数のエクスプレッションを設定します。

まずは**Total Number**です。
ここには螺旋を構成する頂点の数を指定します。
**cols**はループ一個のpoint数です。Y軸に一回転すると**cols**個の点が使われます。
それをループ数(**loopNum**)分コピーします。
また、ループの終わりに必要な分を**+1**します。
つまり以下のような記述になります。

```text:copy1/ncy
ch("../loopNum")*ch("../cols")+1
```

続いてTranslate**のYです。
ここには、一つコピーする度に移動する量を入れます。
最終的なサイズを**height**に合わせたいので、heightを螺旋の頂点数(loopNum*cols)で割って一つのpointがコピーする度に移動する量とします。
つまり以下のような記述になります。

```text:copy1/ty
ch("../height")/(ch("../loopNum")*ch("../cols"))
```

最後に**Rotate**のYです。
ここには、一つコピーする度に回転する量を入れます。
一回転(360度)で、cols個の点になるようにしたいので、360を**cols**で割ります。
つまり以下のような記述になります。

```text:copy1/ry
360.0/ch("../cols")
```

以上で完成です！
ネットワークの階層を一つ戻って**subnet1**のパラメータを変更してみてください。
形が調整出来るようになっています。


# 応用例

とりあえず、自分の目的は以下のモデルを作ることだったので、螺旋からネジを作ってそれを複製して使いました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Houdiniでポケモンのコイル作ってみた。 <a href="https://t.co/XxkE2gD9ES">pic.twitter.com/XxkE2gD9ES</a></p>&mdash; マメマメ (@mamemame360) <a href="https://twitter.com/mamemame360/status/1075410931218182145?ref_src=twsrc%5Etfw">2018年12月19日</a></blockquote>


# その他の方法

**Sweep**ノードのtwistを使ってやる方法もあります。
こっちの方が冗長ですが応用はしやすいかもしれません。
BornDigitalさんの[チュートリアル記事](https://support.borndigital.co.jp/hc/ja/articles/115008583387-%E3%82%B3%E3%82%A4%E3%83%AB%E7%8A%B6%E3%81%AE%E3%82%AB%E3%83%BC%E3%83%96%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)を参考に少し変更を加えています。
![hou_spiral_09_next_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/758098f8-7121-c664-e519-63bb139b10e5.png)
![hou_spiral_09_next_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/336581/ccb24ebd-c3bc-895f-615a-2d4644742945.png)


# あとがき

自分の本職はプログラマで、Wrangleノードを使えば簡単に出来るのは重々承知なのですが、
それだとなんでもWrangleノードでやってしまえば良いことになります。
ですが、アート畑で同じようにHoudiniに興味があって勉強している人にそう言うと100%ウンザリした顔をされます。
そもそもHoudiniの練習にもならないと思いWrangleノードを使わずに作る方法を探していました。

ちなみに公式にVEXで螺旋を作るサンプルもあります。
http://www.sidefx.com/ja/docs/houdini/ref/expression_cookbook.html

自分もHoudiniを初めて半年弱しか経っていませんので、こういう定石っぽいものをたくさん集めていきたいと思っています。