Houdini Advent Calendar 2022 22日目の記事です。
久しぶりにHoudini Advent Calenderに参加させて頂きます!
特に面白いことしてませんが、どうかお手柔らかに…
環境
Houdini 19.5.303
はじめに
みなさんはラインを使った表現をアニメーションさせる際、どういったアプローチを取りますか?
POPやsolverSOPでシミュレーションしたり、トランスフォームで地道に…等
手法は様々かと思います。
私はラインのアニメーションをする際CarveSOPを使うことがあります。
しかしながら!既存のCarveSOPは複数のラインを扱う際に、1本1本へのアクセスができないのです。(おそらく)
そのせいか、アニメーションにばらつきをもたせたり複数のラインを1つのノードで扱うとき少々不便におもうことがあります。
今回はCarveSOPでPolyLineを扱う際の挙動をWrangleを使用して再現しつつ、
Attributeを使って操作できるようにしていきたいと思います!
したがって正確には、、、
CarveSOPをAttributeで制御というよりは、CarveSOPの挙動をwrangleを用いて再現しつつ
Attributeで制御できるように組み立てよう!です!
CarveSOPとは…
周知の事実ではありますが…
CurveではありませんCarveです。
Carve … 彫る、切る、刻む
Carveノードは、フェースやサーフェスタイプ、ポリゴン、Bezier、NURBSで動作します。 Carveノードを使えば、プリミティブをスライスしたり、複数断面にカットしたり、ポイントや断面を抽出することができます。
CurveSOPは曲線や面を生成するのに対して、CarveSOPは作られたものに対して処理を施すノードですね。
左はMeshに対して、右はpolylineに対してCarveSOPを適用した例です。
今回はPolyLineに対する挙動について取り扱っていきます。
やってみる
必要な項目を考えてみます。
- PolyLineをスライスする位置を定義するアトリビュートの用意
- アトリビュートに基づいてPolyLineに処理を施す
大きくはこの2つです。
アトリビュートの準備
ということで、まずはスライス位置を決めるアトリビュートを用意します。
アトリビュートの用意は特別なことはしておらず、
ばらつきを持たせることを目的とした任意のアトリビュートを用意するだけです。
CarveSOPにならって、First U(頭から)とSecond U(お尻から)の両方からスライスできように作ります。
範囲が0~1のプリミティブアトリビュートを用意し、プリミティブのパラメトリックUV座標を用いてスライス位置を決めていきます。
First UとSecond U用の2つ用意します。
PolyLineスライス処理
メインの処理はここになります。
removeprim(0, @primnum, 0); //インプットジオメトリのプリミティブのみ削除
float u = f@__u; //First U用任意のアトリビュート
float su = f@__su; //Second U用任意のアトリビュート
int count = i@__count; //予め算出しておいたプリミティブのもつポイントの数アトリビュート
//--------ポイント交差処理--------
float t;
float t1;
if(u <= su)
{
t = u;
t1 = su;
}else{
t = su;
t1 = u;
}
//--------新たにプリミティブを定義--------
int newprim = addprim(0, "polyline");
//--------First Uを作成--------
vector uPos = primuv(0, "P", @primnum, t);
float attr_utop = primuv(0, "__rstu", @primnum, t);
int attr_id = primuv(0, "__id", @primnum, t);
int upt = addpoint(0, uPos);
setpointattrib(0, "__top", upt, 1, "set"); //First U 抽出用
addvertex(0, newprim, upt); // プリミティブに追加
//--------FirstUとSecondUの間に存在するポイント--------
int primpts[] = primpoints(0, @primnum);
for(int i = 0; i<count; i++)
{
float u_value = point(0, "__rstu", primpts[i]);
addvertex(0, newprim, primpts[i]); // プリミティブに追加
if((u_value < u && u_value > su || u_value < su && u_value > u)!=1)
{
removepoint(0, primpts[i]); //範囲外のポイントを削除
}
}
//--------Second Uを作成--------
vector suPos = primuv(0, "P", @primnum, t1);
int supt = addpoint(0, suPos);
float attr_ubottom = primuv(0, "__rstu", @primnum, t1);
int attr_id1 = primuv(0, "__id", @primnum, t1);
setpointattrib(0, "__bottom", supt, 1, "set"); //Second U 抽出用
addvertex(0, newprim, supt); //プリミティブに追加
ドンと載せてしまいましたが、
処理の内容を簡単なgifにまとめると
このような処理が起こっていることになります。
できた
おわりに
あとはインプット時のアトリビュートを補完してあげれば
その後の処理にも対応できるアセットとして完成するはずです。
処理速度を求めるとなると、もっと最適な解はあるかもしれませんが
とりあえずのところ、勘弁してください…。
少々雑ですが、HDAとして簡単にまとめたものもダウンロードできるよう用意したので
見てみてください。
ここまで読んでいただきありがとうございます!!
良いHoudiniライフを~