昔々に流行った気がする花とか模様がカーブに沿って生えてくるやつ。
分岐していても1本のカーブにFuseできるのであればあらゆることに応用できる。
Fuseが厳しければ一番下を見てね。
もともとは描いた稲妻の出現をアニメーションさせるための方法。

AEで散々マスクとかも駆使して作った思い出。
こんな素材集もありました…
hip
ネットワーク全体

Y軸が正面になるように作成しているので、向きを変える場合は一部アトリビュートを変更する必要がある。
茎
メインカーブを作る

一番長いものはCurveノードで描き、それ以外はDraw Curveのフリーハンドで書いたものをきれいにしている。
どちらでもできることを表現したかっただけなのでどちらでもいい。
どちらもNURBSに変換したのちResampleを使用してポイント数をコントロールする。
その後両方をFuseでつなげる。この際くっついていないと最後に一括で出現のコントロールができないので注意。
出現用アトリビュートの作成

開始ポイント(ここではPoint番号0)をstGpにする。
終了ポイント(ここでは各Curveのcurveu==1)をedGpにする。
Find Shortest Pathノードを以下の設定にし、costを計算する。

出現用アトリビュートの整理

あとで何度も使用するため、costの最小最大をDetailにPromoteし、Attribute Remapで0-1にremapし、その結果をremapCostとする。

幅をもたせる

pscaleやcurveuを作成し、Sweepで幅をもたせる。

これで茎は完成。色はお好みで。
葉
Scatter Pointの用意
茎のrempCostを作成したAttribute Remapノードから分岐

subGpのみを取り出し、resampleでcurveuを再度作成。
PolyframeのBitangent NameをNにする。
Scatterの分布に使用するため、remap_curveでcurveuをRemapする。

Scatter用アトリビュートの用意

Scatterでポイントをいい感じにばらまく。
del_curveu_0のPoint Wrangleには以下を記述し、curveu==0のポイントを削除する。
if(@curveu == 0) {
removepoint(0,@ptnum);
}
random_NのPoint Wrangleには以下を記述し、Nにばらつきを与える。
すべてのNが一定の向きを向いているはずなので、Thresholdで反対側を向く比率を調整する。
AngleでNのばらつく角度を設定。
vector nor = sample_sphere_cone(set(0,1,0), radians(ch("angle")), rand(@ptnum));
nor *= fit01(abs(@N*1000), {0,0,0}, {1,1,1});
v@N += nor;
v@N = normalize(@N);
float threshold = chf("threshold");
if(rand(@ptnum) >= threshold) {
v@N *= -1;
}
rand_pscaleで適当にランダムなpscaleを作成、rand_delayも同様。
delayを使用して出現時のスケールにばらつきを作成する。
delete_ptのPoint Wrangleには以下を記述し、出現のコントロールをする。
Delは一番最後の同じ赤色のdelete_ptと同じ値になるようにする。
float del = chf("del");
float remap = fit(del, @remapCost, @remapCost + @delay, 0, 1);
f@pscale *= remap;
その後、葉をいい感じに作成し、Copy to Pointsで配置する。


花
配置場所を決める
葉と同様にrempCostを作成したAttribute Remapノードから分岐

PrimitiveのSphereを使用し、Transformを使い手動で配置する。

get_costの第一に、配置したい花の位置を。第二に茎から分岐したremapCostを繋ぐ。
get_costのPoint Wrangleには以下を記述し、近接するメインのカーブからremapCostを取得する。
int nearpt = nearpoint(1, @P, 1); f@remapCost = point(1,"remapCost",nearpt);
rand_delayでランダムなDelayを作成。
delete_ptのPoint Wrangleには以下を記述し、出現のコントロールをする。
Delは一番最後の同じ赤色のdelete_ptと同じ値になるようにする。
ほか2つと違い、出現時のスケールをランプで調整している。
float del = chf("del");
float remap = fit(del, @remapCost, @remapCost + @delay, 0, 1);
float ramp = chramp("scale",remap);
f@pscale = ramp;

作成した花をCopy to Pointsで配置し、葉や茎と重なってしまうため、少し+YへTransformする。


出現のコントロール

すべてをMergeする。
最後にdelete_ptのPoint Wrangleには以下を記述し、出現のコントロールをする。
ここのThresholdにキーをうち、
ほか2つの赤いdelete_ptノードDelにつなぎ一律で出現のコントロールをする。
この際、0-1のアニメーションではあるが、実際にはDelayのアトリビュートでの追加分だけ値をアニメーションさせる必要がある。
例:Delayが+0.2なら0-1.2のアニメーションキーを打つ。
float threshold = chf("threshold");
if(@remapCost >= threshold) {
removepoint(0,@ptnum);
}

補足(カーブが繋げられない場合)
基本的にはFind Shortest Pathノードで指定した終点に到達するまでのcostを計算し、そのcostをもとにPointを削除して出現しているように見せている。
Find Shortest Pathはつながっている部分しかたどってくれないので、Fuseなどで結合できない場合には使えない。
下記画像のように繋げられないけど近づけられる場合は以下の方法で同じことができる。

終点のグループを作成するまでは同様で、その後Assembleでnameを作成し、PointにnameをPromoteする。

Edge Transportを以下の設定で作成し、各ポイント間のDistanceを計算する。


get_nearAttribのPoint Wrangleに以下を記述。Search DistとSearch Countは10と4くらい?
float search = chf("search_dist");
int searchCnt = chf("search_count");
int ptnums[];
if(@curveu == 0) {
int nearpts[] = nearpoints(0, @P, search, searchCnt);
foreach(int pt; nearpts) {
string name2 = point(0, "name", pt);
if(@name != name2) {
push(ptnums, pt);
}
if(len(ptnums) >= 1) {
int minValue = min(ptnums);
float nearDist = point(0,"distance", minValue);
f@calcDist = nearDist - @distance;
}
}
}
calcDistをPointからPrimitiveにMinimumでPromoteし、再度PrimitiveからPointへPiece AttributeをオンでPromote
distance_plus_calcDistのPoint Wrangleに以下を記述。
f@cost = @distance + @calcDist;
その後の処理は同じ。

