CopyのStampを使わずに花が咲広がるアニメーション

#はじめに
こんにちは。フジヤマタカシです。調子にのってHoudini Apprentice Advent Calendar 2018、4つ目の投稿をさせていただきます。
今回のは花畑で花が咲広がるアニメーションをCopyのStamp機能を使わずに行います。
[fujitaさんの記事](http://blog.livedoor.jp/fujitarium/archives/52412058.html)の中でCopy Stampはなるべく使わず、アニメーションに関してはなるべくCopyよりも下流で行うとの話があったので、勉強のためそれに挑戦してみようと思います。

#単体の花びらアニメーション
ベースのシェイプはGridとランプで適当に用意します。
![Screenshot from 2018-12-24 00-00-02.png](https://qiita-image-store.s3.amazonaws.com/0/321297/17bcb9d2-b27f-80a7-ba45-57409dd4efcc.png)


花びらのアニメーションに関しては[前の記事で紹介したBendのテクニック](https://qiita.com/takashiFujiyama/items/79e1b3f191b737777aa4)を使うので、まずはBnedの関数を用意します。

```
////function fn_rot////
matrix3 fn_rot(float r_val; vector axis){
    matrix3 rotM = ident();
    rotate(rotM, r_val ,normalize(set(axis)));
    return rotM;
}
////function fn_trans////
matrix fn_trans(vector position){
    matrix transM = ident();
    translate(transM, position);
    return transM;
}

/////function fn_bend//////
matrix fn_bend(vector P, pivot, dir, axis; float dist, angle){
    matrix bendM  = ident();
    bendM *= invert( fn_trans( pivot ));
    float dot = dot(normalize(dir),P*bendM);
    matrix horizonDir = bendM * invert( fn_trans( normalize(dir) * dot));
    float bendArea = fit(dot,0,dist,0,1);
    if(bendArea < 1){
        bendM = horizonDir;
    }else{
        bendM *= invert( fn_trans(normalize(dir) * dist));
    }
    float angAmount = angle * min(dot,dist)/dist;
    float axisOffset = dist/angle;
    vector axisPos = normalize(cross(axis,dir)) * axisOffset;
    matrix3 rot = fn_rot(angAmount,normalize(axis) );
    if(bendArea > 0 && angle != 0){
        bendM = bendM * invert(fn_trans(axisPos)) * matrix(rot) * fn_trans(axisPos) * fn_trans(pivot);
    }else{
        bendM = ident();
    }
    return bendM;
}
```

bendの式は`matrix fn_bend(vector P, pivot, dir, axis; float dist, angle)`と設定してあるので、アングルをアニメーションさせます。

```
`chs("../fn_bend/snippet")`

float bloomStart = length(v@flowerCenter)* 20;
float bloomAnim = fit(@Frame - bloomStart,0,25,0,1);

float bloom = fit01(bloomAnim,-0.32,2);

matrix bendB = fn_bend(@P, set(0,0,0), set(0,1,0), set(1,0,0), 0.4, bloom);

@P *= bendB;
```

`float bloomAnim = fit(@Frame - bloomStart,0,25,0,1);`の部分で２４フレームアニメーションさせています。
![gaxgm-erino.gif](https://qiita-image-store.s3.amazonaws.com/0/321297/4157c6ce-6adb-6652-5152-dfa518fb130d.gif)

#花のひらくアニメーション
circleを作りそのポイントにベースシェイプをコピーします。その時にポイントにアトリビュートを用意しておきます。

```
@N = -normalize(@P);
@up = set(0,1,0);

v@petalCenter = @P;
```

![Screenshot from 2018-12-24 00-29-58.png](https://qiita-image-store.s3.amazonaws.com/0/321297/e4192162-3fef-8af3-a59b-e36bd984f560.png)
N up は花びらの向きに必要で、それにpetalCenterを加えたそれぞれのアトリビュートはBendの為に必要なパラメータなのでコピーの際に移しておきます。
![Screenshot from 2018-12-24 00-35-34.png](https://qiita-image-store.s3.amazonaws.com/0/321297/24d78cb7-2ba1-83cf-7911-5323c26a3f82.png)

それぞれのアトリビュートをBendの関数の中に埋め込みます。

```
`chs("../fn_bend/snippet")`

float bloomStart = 1;
float bloomAnim = fit(@Frame - bloomStart,0,24,0,1);

float bloom = fit01(bloomAnim,-0.32,2);
matrix bend = fn_bend(@P, v@petalCenter, @up, cross(@N,@up), 0.4, bloom);
@P *= bend;
```

![jbi4n-k16jv.gif](https://qiita-image-store.s3.amazonaws.com/0/321297/93a66226-6803-f396-950f-a3d490bff411.gif)

#花畑のアニメーション

先ずは適当にScatterで花のポイントを作ります。
![Screenshot from 2018-12-24 00-50-38.png](https://qiita-image-store.s3.amazonaws.com/0/321297/d94d9629-5bb3-d6e0-1a38-7f1444aaaf54.png)
そして用意したアトリビュート

```
i@flowerid = @ptnum;
v@flowerCenter = @P;

@up = @N;
@N = cross(@up,set(1,0,0));
v@floweraim = @N;
```

花の向きの為up Nを用意します。floweraimは得に無くてもいいですが最終的に花の角度を調整したい場合に必要です。
そしてCircleで作ったポイントをScatterのポイント上にコピーします。
![Screenshot from 2018-12-24 00-58-40.png](https://qiita-image-store.s3.amazonaws.com/0/321297/e992c504-feda-9149-0b4a-cf5f75a232c7.png)
ScatterのNとupはコピー先に読み込みさせませんが、Circle上で作ったNとupが、ScatterのNとupを元に調整されているのが分かります。（赤はfloweraim。これは移行させる。）

それからコピー後に`v@petalCenter = @P;`で花びらの中心アトリビュートを用意します。

これに花びらシェイプをコピーしたら準備は整いました。
![Screenshot from 2018-12-24 01-08-16.png](https://qiita-image-store.s3.amazonaws.com/0/321297/4e2d0acc-749b-5f7d-d7cc-9cd19afffde2.png)

これに対してアニメーションコードを書きます。

```
`chs("../fn_bend/snippet")`

float bloomStart = length(v@flowerCenter)* 20;
float bloomAnim = fit(@Frame - bloomStart,0,24,0,1);

float bloom = fit01(bloomAnim,-0.32,2);
matrix bend = fn_bend(@P, v@petalCenter, @up, cross(@N,@up), 0.4, bloom);
@P *= bend;
```

花単体との違いは`float bloomStart = length(v@flowerCenter)* 20;`で中心から離れた花ほど咲くタイミングを送らせてるだけです。

![i1eq1-oezlz.gif](https://qiita-image-store.s3.amazonaws.com/0/321297/fd0f1c1a-70f1-3c0c-3692-e5889391c0e0.gif)

これだけではAnimation Packを使った方が早いので、せっかく用意したアトリビュートを元にもう少し複雑にしてみましょう。

```
`chs("../fn_bend/snippet")`
int uniqueid = i@flowerid * 100 + i@petalId;
@Cd = lerp( set(fit01( rand(i@flowerid + 11),0.5,1),fit01( rand(i@flowerid + 22),0,0.2),fit01( rand(i@flowerid + 22),0,0.2)), vector(rand( uniqueid) ), 0.3);

float bloomStart = length(v@flowerCenter)* 18;
float bloomAnim = fit(@Frame - bloomStart,0,20 + rand( i@flowerid + 33)*10 ,0,1);

float bloom = fit01(bloomAnim,-0.32,1.8 + rand( uniqueid + 33));
matrix bend = fn_bend(@P, v@petalCenter, @up, cross(@N,@up), 0.4, bloom);
@P *= bend;

float scale = fit01(bloomAnim,0.75,1 + rand( i@flowerid + 33)*0.5);
@P = (@P - v@flowerCenter) * scale + v@flowerCenter;

float rot = rand(i@flowerid + 555) * 3.1415;
matrix3 randomrot = fn_rot(rot, @up);
v@floweraim *= randomrot;

float shakeVel = sin(bloomAnim * 3.141592 * 4) * 0.15;
matrix3 shake = fn_rot(shakeVel, v@floweraim);
@P = (@P - v@flowerCenter) * shake + v@flowerCenter;

@P += @up * fit01(pow(bloomAnim,0.5),-0.5,0);
```
花別のIDであるfloweridと花びらのIDであるpetalIdを使って、色々ランダム値を仕込んで見ました。（ちょっと分かりずらいのでもう少し大げさにすれば良かったかな・・・。）
![p8xkb-z1j8g.gif](https://qiita-image-store.s3.amazonaws.com/0/321297/07b0bddb-f391-f28c-af6a-796207466dce.gif)
ネットワークを見てもらえればCopyノード以前はアニメーションされてないのが分かると思います。
![Screenshot from 2018-12-24 01-52-18.png](https://qiita-image-store.s3.amazonaws.com/0/321297/9d17981f-5748-a6e8-ff7d-b417fc66fb6e.png)


作成したファイルはこちらになります。
https://drive.google.com/file/d/1Zx2MM6g2AYVh9ikeCbnsZxEAwuwq2VEo/view?usp=sharing

では今回は以上になります。ここまで読んでいただきありがとうございます！