HoudiniのWrangleで平面を球、円錐に変形

## 概要
![untitled_1.gif](https://qiita-image-store.s3.amazonaws.com/0/46585/6620c763-2823-ba6c-1143-0c2398b79672.gif)


HoudiniのWrangleで平面を球や円錐に変形して、エフェクト用のメッシュを作成します。頂点の位置を計算で直接変更しているだけなので他の3Dソフトやコードでも使えると思います。もとの平面は0<x<1, 0<z<1のものを使います。Gridを使用し、Sizeを1*1にし、Transformでx,zを+0.5して、0<x<1, 0<z<1の平面を用意します。
![rapture_20170422220548.png](https://qiita-image-store.s3.amazonaws.com/0/46585/14aa5496-8bf0-647f-4a5a-9001a2e23d01.png)

※例ではわかりやすくするため間にUVQuickShadeを挟んでいます。
※書いていたときのミス防止のため、助長に変数を使っています(in, outなど）  
![Node.png](https://qiita-image-store.s3.amazonaws.com/0/46585/e8c03b3b-a934-3ec6-dd10-0f5890deb28f.png)


## 球
球面座標上に平面を投影します。[Wikipedia-極座標系](https://ja.wikipedia.org/wiki/%E6%A5%B5%E5%BA%A7%E6%A8%99%E7%B3%BB#.E7.90.83.E5.BA.A7.E6.A8.99)
![Sphere.png](https://qiita-image-store.s3.amazonaws.com/0/46585/d5bf829c-4186-7220-06e6-2b98e4b2c773.png)

```php
vector in = @P;
float r = 1.0;
vector out;

float angle1 = lerp(0.0, 2.0 * $PI, in.z);
float angle2 = lerp(0.0, $PI, in.x);

out.x = r * cos(angle1) * sin(angle2);
out.z = r * sin(angle1) * sin(angle2);
out.y = r * cos(angle2);

@P = out;
```

## 上端と下端を切り取った球
![SphereLack_ (2).png](https://qiita-image-store.s3.amazonaws.com/0/46585/47a382cc-2cec-93bc-ffe0-3eb40cea576e.png)

```php
vector in = @P;
float r = 1.0;
vector out;
 
float angle1 = lerp(-$PI, $PI, in.z) ;
float angle2 = lerp(0.3 * $PI, (1.0-0.3) * $PI, in.x);

out.x = r * cos(angle1) * sin(angle2);
out.z = r * sin(angle1) * sin(angle2);
out.y = r * cos(angle2);

@P = out;
```

## チューブ
円柱座標に平面を投影します。[Wikipedia-極座標系](https://ja.wikipedia.org/wiki/%E6%A5%B5%E5%BA%A7%E6%A8%99%E7%B3%BB#.E5.86.86.E6.9F.B1.E5.BA.A7.E6.A8.99)
![Tube_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/170e6e5c-8fe0-fe56-9ecd-66bc29ceafc5.png)

```php 
vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;
```
## ねじれたチューブ

![TubeTwist.png](https://qiita-image-store.s3.amazonaws.com/0/46585/15893341-175f-9360-448c-6f2923ee6fd3.png)


```php
vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;
float rotate_rate = -0.2;
angle += 2.0 * $PI * rotate_rate * in.z;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;
```

## 頂点が下寄りのチューブ
![TubeUnder.png](https://qiita-image-store.s3.amazonaws.com/0/46585/83e479ea-3fc4-066c-ae60-911ddcd0e126.png)

```php
vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * pow(in.z, 2.0);
out.z = r * sin(angle);
@P = out;
```

## コーン
heightで全体の高さ、rのlerp関数のminで下端、maxで上端の半径を指定
![Cone.png](https://qiita-image-store.s3.amazonaws.com/0/46585/cb35ade8-347d-12f9-cd80-a96b71ccf986.png)


```php
vector in = @P;

float angle = lerp(0.0, 2.0 * $PI, in.x);
float height = 0.3;
float r = lerp(0.75, 1.0, in.z);

vector result;
result.x = r * cos(angle);
result.y = height * in.z;
result.z = r * sin(angle);

@P = result;
```

## パラボラアンテナ
height式内のpowの係数、r式内のpowの係数により、形状の調整、頂点位置の調整ができます。
![ConeQua_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/2716fd47-0c36-71f2-4635-502b5f3b5728.png)

```php
vector in = @P;

float rad = 2.0 * $PI * in.x;
float height = 1.0 * pow(in.z, 2.0 );
float r = 1.0 * pow(in.z, 1);

vector out;
out.x = r * cos(rad);
out.y = height;
out.z = r * sin(rad);

@P = out;

```

## ブラックホール形状
![ConeQuadVerse.png](https://qiita-image-store.s3.amazonaws.com/0/46585/735d6b0c-76a6-aa88-5abd-27d0792c0c54.png)

```php
vector in = @P;
float r = 1.0;
vector out;
 
float angle1 = lerp(-$PI, $PI, in.z) ;
float angle2 = lerp(0.0 * $PI, 0.5 * $PI, in.x);

out.x = r * cos(angle1) * (1.0 - sin(angle2));
out.z = r * sin(angle1) * (1.0 - sin(angle2));
out.y = r * (1.0 - cos(angle2));

@P = out;
```

## リング
rのlerp内のminで内半径、maxで外半径を指定。
![Ring_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/8c439d22-5ef5-7de5-1d13-1827d251c267.png)


```php
vector in = @P;

float angle = lerp(2.0 * $PI, 0.0, in.x);

float r = lerp(0.5, 1.0, 1.0 * in.z);

vector out;
out.x = r * cos(angle);
out.z = r * sin(angle);
out.y = 0.0;
@P = out;
```
　
## 波打ったリング

![RingWave_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/f2f76627-1cff-77c5-e853-ff773f528379.png)


```php
vector in = @P;
vector out;

float rad = lerp(2.0 * $PI, 0.0, in.x);
int num = 6; // 波の数
float wave_height = 0.2; // 波の高さ

float r = lerp(0.8, 1.0, 1.0 * in.z) + lerp(0.0, 0.05, sin(rad));
out.x = r * cos(rad);
out.z = r * sin(rad);
out.y = wave_height * sin(rad * num);

@P = out;
```

## トーラス（ドーナツの形状）

一つのスクリプトだけでも作れますが、分けた見やすいので2つのWrangleに分けて書きました。この2つを連続でつなげてください。
一つ目のスクリプトのrがチューブの太さ、xに足した値d（今回は0.5)が全体の半径になります。

![Torus_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/6971247f-ff83-a293-680f-6ad7b285e22f.png)


```php
vector in = @P;
float r = 0.1;
float rad = 2.0 * $PI * in.x;
float d = 0.5;

vector out;
out.x = r * cos(rad) + d;
out.y = r * sin(rad);
out.z = in.z;
@P = out;
```

```php
vector in = @P;
float r = in.x;
float rad = in.z * $PI * 2.0;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;
```

## 内側が欠けたトーラス

![TorusLack_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/f7a25089-1a47-3a54-23e1-4bc8eb334b81.png)


```php
vector in = @P;
float r = 0.1;
float rad = lerp(-0.5 * $PI, 0.5 * $PI, in.x);

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = @P.z;
```

```php
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;
```

## トーラス上にリボン

![TorusTwist (2).png](https://qiita-image-store.s3.amazonaws.com/0/46585/7f254547-09db-92a2-201c-1b766949c6d6.png)

```php
vector in = @P;

float r = 0.2; //トーラスの太さ(0 <r < 0.5)
float rad = 0.5 * $PI * in.x ;

float rotate_num = 8.0;
rad += rotate_num * 2.0 * $PI * @P.z;

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = @P.z;
```

```php
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;
```

## ねじれたトーラス（ドーナツの形状）

twist_numでねじれ数を指定可能。

![TorusTwist_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/efaa6e52-b375-1183-b0f0-8bf729fdf56f.png)


```php
vector in = @P;
float r = 0.03;
float rad = 2.0 * $PI * in.x ;
float twist_num = 3.0; //ねじれ数
rad += twist_num * 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad) + 0.5;
out.y = r * sin(rad);
out.z = in.z;
@P = out;
```

```php
vector in = @P;
float r = in.x;
float rad = 2.0 * $PI * in.z;

vector out;
out.x = r * cos(rad);
out.y = in.y;
out.z = r * sin(rad);
@P = out;
```

## 帯
![Slash_.png](https://qiita-image-store.s3.amazonaws.com/0/46585/85ab1b0b-ba04-ce47-9f47-5d7bf55d6199.png)

```php
vector in = @P;
float r = 0.1;
float height_rate = cos(lerp(-0.5 * $PI, 0.5 * $PI, in.z));
float rad = 1.0 * $PI * (in.x-0.5) * height_rate;

@P.x = r * cos(rad) + 0.5;
@P.y = r * sin(rad);
@P.z = in.z;
```
```php
vector in = @P;
float r = in.x;
float rad = 1.0 * $PI * in.z;

@P.x = r * cos(rad);
@P.y = in.y;
@P.z = r * sin(rad);
```
## スライダーで値を調整
これ以降のスクリプトは、```chf```を用いて係数をスライダーで変更可能にしています。
```chf```を含んだスクリプトを書いた後、以下のボタンを押すとスクリプト下に値を変更可能なスライダーが現れます。
![rapture_20170819144614.png](https://qiita-image-store.s3.amazonaws.com/0/46585/5030c94f-40e3-0d03-edb7-5e019741bb38.png)

また、全ての係数の初期値が0なので、正しく設定しないと何も表示されないので注意してください。

## 係数によってチューブにもリングにもできる形状

![rapture_20170819145458.png](https://qiita-image-store.s3.amazonaws.com/0/46585/a4b0f6f5-87fa-bf08-f6c1-76c03341b7f4.png)

* 係数例  
![rapture_20170819145512.png](https://qiita-image-store.s3.amazonaws.com/0/46585/01467633-57bc-becf-b6a0-4e7e32998321.png)

```php
vector in = @P;
float rotate_num = chf("rotate_num");
float height = chf("height");
float radius_bottom = chf("radius_bottom");
float radius_top = chf("radius_top");
float radius = lerp(radius_bottom, radius_top, pow(in.z, chf("height_pow_rate")));
float angle = 2.0 * $PI * in.x
+ 2.0 * $PI * rotate_num * in.z;

vector out;
out.x = radius * cos(angle);
out.z = radius * sin(angle);
out.y = height * in.z;
@P = out;
```

## 螺旋リボン

![rapture_20170819145008.png](https://qiita-image-store.s3.amazonaws.com/0/46585/abca7927-0c0c-171e-1c1a-4600871cb1ad.png)

* 係数例  
![rapture_20170819145344.png](https://qiita-image-store.s3.amazonaws.com/0/46585/609ec6cb-a9bc-d310-4eff-c89b2ea07b65.png)


```php
vector in = @P;
in.x = lerp(chf("in_start"), chf("in_end"), in.x);
float radius = lerp(chf("radius_bottom"), chf("raidus_top"), in.x) 
+ chf("radius_z_rate") * in.z
+ chf("n_height") * sin($PI * in.z)
;
float angle = 2.0 * $PI * in.x * chf("rotate_num");

vector out;
out.x = radius * cos(angle);
out.z = radius * sin(angle);
out.y = in.z * chf("zrate") + in.x * chf("xrate");
@P = out;
```


## エフェクト用メッシュとして使うために

上記スクリプトでは書いていませんが、エフェクト用メッシュとして使う時は、各頂点のAlphaアトリビュートに適当な値を書き込んで出力してから使っています。（リングでは端に行くほど透明になる、チューブで上に行くほど透明になるなど）
FBXを出力する際にAlphaアトリビュートを書き込むには、間にColorを挟む必要があります。（不具合？）
![TubeAlpha.png](https://qiita-image-store.s3.amazonaws.com/0/46585/ef4e9fc2-ac11-332e-9d08-16881033a8d0.png)

```php
vector in = @P;

float r = 0.5;
float height = 1.0;
float angle = 2.0 * $PI * in.x;

vector out;
out.x = r * cos(angle);
out.y = height * in.z;
out.z = r * sin(angle);
@P = out;
@Alpha = 1.0 - pow(@P.y, 0.5);
```

![rapture_20170422221549.png](https://qiita-image-store.s3.amazonaws.com/0/46585/163dabd6-3ec2-82e3-8579-b3736c5a7369.png)

## 関連機能
SideFX LabsのCylinder Generator, Sphere Generator, Disc Generatorを使うことによって、UV付きのエフェクト用メッシュを作成することができます。
[チュートリアル動画](https://www.sidefx.com/forum/topic/55658/)
[SideFX Labs ツールリスト
](https://www.sidefx.com/ja/products/sidefx-labs/sidefx-labs-tools/)