LoginSignup
4
3

More than 1 year has passed since last update.

CarveSOPをAttributeで制御したい。

Last updated at Posted at 2022-12-21

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 … 彫る、切る、刻む

CarveSOPドキュメント JP EN

Carveノードは、フェースやサーフェスタイプ、ポリゴン、Bezier、NURBSで動作します。 Carveノードを使えば、プリミティブをスライスしたり、複数断面にカットしたり、ポイントや断面を抽出することができます。

CurveSOPは曲線や面を生成するのに対して、CarveSOPは作られたものに対して処理を施すノードですね。

左はMeshに対して、右はpolylineに対してCarveSOPを適用した例です。

今回はPolyLineに対する挙動について取り扱っていきます。

やってみる

必要な項目を考えてみます。

  1. PolyLineをスライスする位置を定義するアトリビュートの用意
  2. アトリビュートに基づいてPolyLineに処理を施す

大きくはこの2つです。

アトリビュートの準備

ということで、まずはスライス位置を決めるアトリビュートを用意します。
アトリビュートの用意は特別なことはしておらず、
ばらつきを持たせることを目的とした任意のアトリビュートを用意するだけです。
CarveSOPにならって、First U(頭から)とSecond U(お尻から)の両方からスライスできように作ります。

範囲が0~1のプリミティブアトリビュートを用意し、プリミティブのパラメトリックUV座標を用いてスライス位置を決めていきます。
First UとSecond U用の2つ用意します。

PolyLineスライス処理

メインの処理はここになります。

RunOver : Primitive
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にまとめると
このような処理が起こっていることになります。

Videotogif.gif

できた

Videotogif (4).gif
growth.gif
わーい

おわりに

あとはインプット時のアトリビュートを補完してあげれば
その後の処理にも対応できるアセットとして完成するはずです。

処理速度を求めるとなると、もっと最適な解はあるかもしれませんが
とりあえずのところ、勘弁してください…。

少々雑ですが、HDAとして簡単にまとめたものもダウンロードできるよう用意したので
見てみてください。

hipこちら

ここまで読んでいただきありがとうございます!!
良いHoudiniライフを~

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3