Blender3.1でうに爆発エフェクト
見出し画像のようなエフェクトを作ります。GeometryNodesで作ります。適当に頂点を選んで伸ばすだけだろ? そんな風に考えていた時期が私にもありました。
ランダムに頂点を選ぶと、こうなる😇
隣接頂点を同時に伸ばすと、画像の右上の方にあるように、針状にならずにきしめん状になってしまいます。
つまり、隣接しない頂点を計算でしっかり選んで、伸ばす距離だけランダムにする、というのが正解です。
平面型
まずは簡単な平面から見ていきます。
アルゴリズムの考察
もっと効率のいい方法があるような気もするなぁ……。
はおいておいて、まずはどういった頂点を選べばきしめんが生まれないか考えます。座標に目印としての座標を割り振ります。中央を(0, 0)とし、右に+x、上に+yとして設定します。
隣接しない頂点を選べばいいので、選択して持ち上げるとこの4パターンになります。
斜めは直接連結していないので選びたくなるかもしれませんが、実際はポリゴンは三角形なので隣接頂点となります。
さてここで問題。BlenderのGeometryNodesで奇数・偶数ってどう調べたら?
プログラムをやってる人なら簡単ですね。剰余演算(%, Moduro)を使えばいいだけです。割り算のあまりを求めることができるので、2で割ったあまりが0か1かで判別できます。
偶数:数値%2 == 0
奇数:数値%2 == 1
GeometryNodesでは次のように計算できます。
頂点座標を整形する
頂点座標を整数に整形します。等間隔に並んでさえいれば簡単で、頂点間の距離で割るだけです。頂点座標はローカル座標で入っているので、オブジェクトモードでの移動・回転・拡大の影響を受けません。
というわけで平面を分割して始めている場合、大抵は固定値でも問題ないでしょう。
ただし頂点座標をちょっとでも触ると、頂点間距離が0.5や0.25など2のn乗で表せなくなり計算誤差が発生します。
計算誤差がでてうまく選択できない場合、簡単に直すなら距離をちょっとだけ減らせばいいです。
ちゃんと計算するなら、奇数偶数を出す計算式ごと変更を加えます。最終的には奇数偶数がわかればよく+ーを考慮しないので、まずAbsで絶対値にします。次に0.9999とか1.0001とか微妙な値になっている数値に0.5を足して1.5前後の値にし、Truncateで小数部分を切り捨てて、きれいな整数を得ます。
中心からの方向に伸ばす
伸ばす方向は中心からの方向にします。中心が原点であれば、座標の値そのものがxy方向になります。zの大きさを適当に決めたら、扱いやすいよう正規化をしておきましょう。
中心以外の場合は、Positionから中心としたい座標を引いてやります。
座標をずらす
SetPositionノードで座標をずらしてみます。とりあえず、偶数・偶数パターンでいってみましょう。
x,yが共に偶数である、というのは、xの偶数チェックとyが偶数チェックの結果を掛け算します。
これをSetPositionのSelectionにつなぎます。zの値を適当に入れたら偶数・偶数パターンで頂点が選択され、移動します。
奇数・奇数パターンも問題ないか見ておきます。ノードが少なくなるので、基本はこれを使うことになると思います。
SetPositionのoffsetに方向を入れます。
VectorMathのMultiplyで長さを調整できます。
MultiplyにつないだValueで長さを、Addのzで広がりを調整できます。
長さのランダム化
長さをvalueの固定値ではなくRandomValueを使えばランダムな大きさにできます。
後は調整
平面を細かく割って、頂点間の距離が入っているValueを調節するとトゲが細かくなります。
見出し画像の残り部分
逆側は複製して180度回転させただけです。
爆発部分は凸凹にした球にそれっぽいマテリアル(グラデ+ノイズ)を当てただけです。
というわけで、後の見栄えはほとんどマテリアルで決まります。
UV球型
今回の制作では使っていないのですが、いつか使うかもということでUV球からうにフラを作る手順も作っておきました。
考え方は平面型とほぼ同じで隣接しない頂点を選択する方法さえ見つければほぼ終了です。
アルゴリズムの考察
UV球を作るときに、計算しやすいようにSegmentsを36、Ringsを18に設定しました。これですべての頂点が10度ずつずれていることになります。
均一にずれた数字さえ取れれば後は平面型と同じでいけるので、この角度を整数で0,1,2…となるようにしていけば良さそうです。
頂点座標を整形する(XY平面)
UV球はXY平面上にSegmentsの分割数で分割されます。というわけで、まずはXY平面上の頂点の座標を取得し(zに0を設定するだけ)、Normalizeして単位ベクトル化しておきます。
基準となるベクトルを数学っぽく(1, 0, 0)として、平面上の頂点へのベクトルと内積を取るとコサイン値が出るので、アークコサインで角度がでます。アークコサインは値をラジアン(すべてプラスの値)で返すので、計算し易いよう度に変換しておきます。
今回各頂点は10度ごとのはずなので10で割ります。これで整数の0, 1, 2, …といいたいところですが、コサイン周りの計算は結構値に誤差がでます。0, 1.0001, 1.9999, …みたいにちょっとだけずれてしまいますので、そのまま2で割ったあまりを出すと、0, 1, 0, …とはならず、0, 1.0001, 1.9999, …と期待しない数字になります。
こういった場合は0.5を足して0.5, 1.5001, 2.4999, …のようにし、Truncateで整数部分だけ抜き出すと、0, 1, 2, …というきれいな整数を得ることができます。
座標をずらす(XY平面)
ここまでで選択できる頂点をSetPositionでNormal方向にずらしてみます。
頂点座標を整形する(Z軸)
UV球のZ側は単純にZ軸の長さから角度を得ることができます。
球の半径が1のときはZ軸の大きさがそのままコサイン値となります。球の半径が1以外のときは、球の半径で割っておいてください。
コサイン値さえ作れれば、アークコサインから先の計算式は同じです。
座標をずらす(Z軸)
ここまでで選択できる頂点をSetPositionでNormal方向にずらしてみます。
座標をずらす(合成)
XY平面とZ軸の選択結果は掛け算でAND合成できるので、2つ合わせた状態で選択してNormal方向に動かしてみます。
長さのランダム化
SetPositionにつないでいたNormalにランダム値を掛け算して長さをランダムにします。
この記事が気に入ったらサポートをしてみませんか?