やりたいこと
任意のメッシュを任意のカーブに沿って変形させたい。
まっすぐなヘビのモデルをカーブで手軽に変形させたり、つたなどの細長いオブジェクトのジェネレータへの応用が期待されます。
前提知識
- Geometry Nodesの基本的な概念
- 各ノードの意味
- 高校数学(特にベクトル)
以上
アイデア
変形したいメッシュはもともとx軸に沿っているという前提で考えます。
メッシュをyz平面で輪切りにするようなイメージで細分化し、それぞれの平面をカーブの対応する点に再配置します。
流れ
- 変形させるメッシュの準備
- カーブをサンプリング
- メッシュをサンプリング
- 頂点の再配置
- メッシュの複製
- 位置を変更
- タンジェントとノーマルを適用
変形させるメッシュの準備
変形させたいメッシュを準備します。
カーブに沿って変形させるため、十分に細分化されていないと変形後にガタガタします。
今回は先細らせた三角柱を蛇の胴体に見立てて使用します。
カーブをサンプリング
入力として渡ってきたカーブの情報をサンプリングします。
カーブはfactorという値を保持しており、それぞれのストロークについて始点が0、終点が1です。
下図カーブ上の点にfactorに応じたスケールのインスタンスを配置することで、その値を可視化しています。
よくあるカーブ上にものを配置する系のチュートリアルはここまでの内容で作れます。
factorではなくlengthを使い、一定の間隔でサンプリングを行いインスタンスを配置します。
次にカーブ上の任意のfactor値の点をsample curveノードを使い、直接サンプリングしてカーブのタンジェントを取得し、カーブに沿って回転させます。ここまでで、ソースのカーブから情報を取得することができるようになりました。
blender3.4より前のバージョンではsample curveノードのcurve indexピンがありません。
複数のカーブがある状態でサンプリングをすると、すべてのカーブが対象になるので、めちゃくちゃな値が返ってきます。
メッシュをサンプリング
x軸に沿ったオリジナルのメッシュの各頂点について、それらがカーブのどの位置に対応するか、つまりfactor値を求めます。
これはとても簡単で、下の式で求まります。
factor(x) = \frac{x - x_{min} }{ (x_{max} - x_{min})}
可視化したとき、きちんと0から1へグラデーションがかかっているのがわかります。
頂点の再配置
メッシュの複製
カーブが複数ある場合、その数だけメッシュを用意する必要があるので、カーブの始点にインスタンスを作成します。
このとき、各インスタンスに紐づくカーブのインデックスをattributeに保存します。
後々の処理を考えて、生成位置を原点にするために一度各カーブの始点をサンプリングしています。
(ここをinstanceのpositionで求めようとすると接続時にエラーになりました。わかる方コメントをいただけますと幸いです。)
この段階で最終的な頂点が生成されたので、各頂点のfactorを求めカーブのサンプリングを行い、attributeに保存しておきます。
位置を変更
まずは各頂点の位置を変更します。
上で求めた各頂点のfactorで対応するカーブをサンプリングし、頂点が存在するyz平面の原点をその位置に持ってくるという処理です。
タンジェントとノーマルを適用
タンジェントはカーブの微分値です。
つまり任意の点でカーブがどの方向に延びているかということです。
ノーマルはカーブのねじれの方向です。
デフォルトがどの方向かはわかりませんが、タンジェントとは直行しています。(おそらくデフォルトは-y軸方向ではないかと思います。)
これらを使い、頂点のyz平面を一意に回転させます。
最初に説明した通りオリジナルのメッシュはx軸に沿って配置されているという前提です。
よってカーブのタンジェントはyz平面のノーマル方向、カーブのノーマルはyz平面のタンジェント方向です。
ややこしいですが、図を見てみるとわかります。
そしてyz平面のノーマル方向は当然直行するx軸方向、タンジェント方向は平行なyz平面上のベクトルとなります。ここでは-y軸方向をyz平面のタンジェントとしてみます。
回転にはAlign Euler to Vectorノードを使用します。まずx軸をタンジェントに一致させます。
その後-y軸をノーマル方向に一致させます。
タンジェントとノーマル、x軸と-y軸はそれぞれ直行していますので、完全に一致させることができます。
ただし-y軸の回転の際にはローカル座標系で行う必要があるので、ノードを2連結させて一意に回転を定めます。
さらにこれらはyz平面を回転させていたので、x=0である必要があります。
よってyz平面の回転はyz平面の移動の前に行います。
あとがき
備忘録のようなものでしたので粗末な文章ですが、お役に立てましたら幸いです。
Geometry Nodeを学び始めて1週間程度ですが、とても面白くmodifier等よりも細かな調整が可能だなという印象を受けました。
今後プロシージャルなアプローチはさらに需要が高くなるでしょうから、勉強しておくのが吉だと思います。
間違った箇所等ございましたらコメントにてご教授ください。
ここまでご覧いただきありがとうございました。
参考になるサイト、動画