2020年12月11日金曜日

使ってはいけないStamp!

この記事はHoudiniアドベントカレンダー2020 11日目の記事です。

皆さん、大量なオブジェクトのアニメーションのタイミングをアトリビュートを利用してズラしたい!なんて事はありますでしょうか?
はい。自分は良くあります。
実は、様々なチュートリアルでStampとTime shift Sop使った悪手が散見されるので記事にしました。

Houdini独特の機能のStampですが、移動・回転・スケール・Alphaなどなどアトリビュートで操作できる値はアトリビュートを直接いじりましょう!というのはHoudiniをある程度触った事がある人ならば共通認識だと思いますが、見落とされがちなのがアニメーションをキーフレームで行いたい場合です。
そんな時はwrangleでch関数のとあるオプションを使いましょう。

まずは簡単な例から。ランダムにアニメーションをズラしています。

よく見るダメな例。ランダムな値が入ったshiftアトリビュートをstampで参照しtimeshiftノード内で使用。

スケールのアニメーションは以下の様にキーフレームでアニメーションつけています。(上図ではscale_Animationノード)


良い例。Wrangleノードの自作したscaleというパラメーターに、上と同じキーフレームアニメーションが付いています。

Wrangleでパラメーターを作る時に、chf , chvなど良く使うかと思いますがch関数には時間指定して値を取ってくるオプションがあります。

上の例だと chf('scale' , @Time - ここにズラしたい値を入れる) 

つまりchf('scale',@Time) だと元のアニメーションと全く同じタイミングでchf('scale')と同様の挙動です。  

この方法のほうが、パフォーマンスは段違いに速いのでstampはどうしようもない時のみ使う様にしましょう。



----------------------------------------------------------------------------
応用例です。(トップのムービー)

といっても、本題のch関数のオプションの話は済んでいるので
この様な各面の基点、サイズ、スケールアニメーションの向き、面の向きがバラバラなタイプの表現をする時に使えるテクニックの紹介です。

大まかに流れを説明すると、各ポリゴンをから基点(pivot)、upとNの向き、サイズ(scale)を
割り出し、1ポリゴンのgridを割り出した各面のpivotにcopy to points でコピーし面を再構成しなおすという感じです。
元の形状はSidefx Lab toolsのLot subidivisionというSopで作りました。
このSopお手軽ですが、以前R&D行っていたTreemapアルコリズムとは違う様で用途は限定的です。
facet sopでプリミティブをバラバラにします。Primitive wrangle(上図get_pivot_dir)で各プリミティブのエッジ上の中点を基点としたいので、
prim points関数を使って下図の様に全ての面に対してpt0とpt1を選びます。
int primPts[] = primpoints(0,@primnum);
int numPt = len(primPts);
int start = floor(fit01(rand(@primnum*1.23),0,numPt));

int pt0 = primPts[start];
int pt1 = primPts[start+1];
if (start == numPt-1) pt1 = primPts[0];
この2点が選べれば、それらのポジションの平均が中点になり、
vector P0 = point(0,'P',pt0);
vector P1 = point(0,'P',pt1);
v@pivot = avg(P0,P1); 
v@dir = P0 - P1 ;
-----------------------------------------------------------------
upとの外積を取る事でN、dirのlengthでx size、中心点からpivotまでの距離から
z size も取得できます。下図参照。

(set_pivot_N)
vector pivot = prim(1,'pivot',@ptnum);
@zsize = length(@P-pivot)*2;
@P = pivot;
vector dir = prim(1,'dir',@ptnum);
@N = cross(v@up,dir);
@xsize = length(dir);

(この図は黄土色のプリミティブのみ図解していますが、各プリミティブに同様の処理が行われます。)
scale_timeshiftノード
float timeShift = @Time - fit01(rand(@ptnum),0,2) ;
v@scale = set(@xsize, 1, chf('scale', timeShift) * @zsize ); 
先ほど同様、chvのオプションを使ってタイミングをズラします。各面が1方向にスッと動きを付けたかったのでz sizeのみアニメーションさせています。

以上です。

早いものでHoudiniアドベントカレンダーが始まってもう5年目ですね。

毎年沢山の方が記事を書いてくれています。過去のテクニックも古くなるものは殆どないので、是非みてみて下さい。


アペレンティス https://qiita.com/advent-calendar/2018/happrentice