すあまの備忘録

誰得内容の自分のための非営利目的備忘録ブログ(筆者がわかっても内緒にしてください)

モーショングラフィックスのような花を咲かせる

昔々に流行った気がする花とか模様がカーブに沿って生えてくるやつ。

分岐していても1本のカーブにFuseできるのであればあらゆることに応用できる。

Fuseが厳しければ一番下を見てね。

もともとは描いた稲妻の出現をアニメーションさせるための方法。

f:id:godofsuama:20201229234938g:plain

AEで散々マスクとかも駆使して作った思い出。

こんな素材集もありました…

Evolution - フラッシュバックジャパン

hip

hipはこちら

ネットワーク全体

f:id:godofsuama:20201230190655p:plain

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

メインカーブを作る

f:id:godofsuama:20201230190913p:plain

一番長いものはCurveノードで描き、それ以外はDraw Curveのフリーハンドで書いたものをきれいにしている。

どちらでもできることを表現したかっただけなのでどちらでもいい。

どちらもNURBSに変換したのちResampleを使用してポイント数をコントロールする。

その後両方をFuseでつなげる。この際くっついていないと最後に一括で出現のコントロールができないので注意。

出現用アトリビュートの作成

f:id:godofsuama:20201230191142p:plain

開始ポイント(ここではPoint番号0)をstGpにする。

終了ポイント(ここでは各Curveのcurveu==1)をedGpにする。

Find Shortest Pathノードを以下の設定にし、costを計算する。

f:id:godofsuama:20201230191404p:plain

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

f:id:godofsuama:20201230191535p:plain

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

f:id:godofsuama:20201230191637p:plain

幅をもたせる

f:id:godofsuama:20201230191749p:plain

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

f:id:godofsuama:20201230191844p:plain

これで茎は完成。色はお好みで。

Scatter Pointの用意

茎のrempCostを作成したAttribute Remapノードから分岐

f:id:godofsuama:20201230192116p:plain

subGpのみを取り出し、resampleでcurveuを再度作成。

PolyframeのBitangent NameをNにする。

Scatterの分布に使用するため、remap_curveでcurveuをRemapする。

f:id:godofsuama:20201230192307p:plain

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

f:id:godofsuama:20201230192626p:plain

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で配置する。

f:id:godofsuama:20201230193201p:plain

f:id:godofsuama:20201230193215p:plain

配置場所を決める

葉と同様にrempCostを作成したAttribute Remapノードから分岐

f:id:godofsuama:20201230193434p:plain

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

f:id:godofsuama:20201230193516p:plain

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;

f:id:godofsuama:20201230193725p:plain

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

f:id:godofsuama:20201230193805p:plain

f:id:godofsuama:20201230193829p:plain

出現のコントロール

f:id:godofsuama:20201230193926p:plain

すべてを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);
}

f:id:godofsuama:20201230193725p:plain

補足(カーブが繋げられない場合)

基本的にはFind Shortest Pathノードで指定した終点に到達するまでのcostを計算し、そのcostをもとにPointを削除して出現しているように見せている。

Find Shortest Pathはつながっている部分しかたどってくれないので、Fuseなどで結合できない場合には使えない。

下記画像のように繋げられないけど近づけられる場合は以下の方法で同じことができる。

f:id:godofsuama:20201231153755p:plain

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

f:id:godofsuama:20201231153834p:plain

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

f:id:godofsuama:20201231154008p:plain

f:id:godofsuama:20201231154137p:plain

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;

その後の処理は同じ。

f:id:godofsuama:20201231154426p:plain

f:id:godofsuama:20201231154709g:plain