Houdini Advent Calendar 2020 6日目 の記事です
はじめに
背景TAになって1年目、TAらしい良い記事を書こうとひねり出したテーマは"ポリラインの抽出"です
Houdini歴0-2年ぐらいの方に向けて書いたつもりです
ポリラインはポリゴンに比べて単純な構造で、プロシージャルに制御するのにハードルが低いと思います
ジオメトリから欲しいポリラインを適切に抽出できれば、様々なシーンで活躍します
この記事を読んで生成されたポリライン達が、皆さんのHoudiniライフの一助となれば幸いです
また、抽出したポリラインの変換については、↓↓こちらのページにわかりやすくまとまっています
https://issekinichou.wordpress.com/2020/03/01/houdini-curve-editing/
※英題について
英語でも同じテーマで最新の情報がまとまった記事は存在しないと感じ、少しでも多くのHoudinistにリーチしてほしいと思ったからです
カッコつけではありませんw
動作環境
Houdini Apprentice 18.5.351
Labs 18.5.417
Primitive毎にエッジからポリラインを抽出
Ends,Primitive,Carve、これら3つのSOPは大体同じことができますが微妙に違います
Ends
エッジを一周する一つのポリラインを、プリミティブ毎に生成します
PrimitiveSOPでも同じことができますが、新しそうなこちらが推奨です
CloseU>Unroll with New Pointsを選べば端点が繋がっていないポリライン
CloseU>Unroll with Shared Pointsを選べば端点が繋がっていないポリライン
を得ることができます
Primitive
端点について
なお、EndsSOPもPrimitiveSOPもポリラインの端点は必ず元のプリミティブの頂点番号0が参照するポイントになります
任意で指定することはできないので、端点を変更したい場合はReverseSOPのVertex>Shiftで対処してください
※PrimitiveSOP内にも同じパラメータがありますがうまく行かないので注意!
Carve
端点をパラメトリック座標から始点終点を指定してポリラインを生成できます
前述の2つのSOPと違い、必ず端点は繋がってない状態でポリラインが出力されます
ポリゴンエッジをポリラインにする目的でCarveSOPを使う場合、FirstU,SecondUのみを使用します
FirstUのみ設定すると、EndsSOPのUnroll with New Pointsと同じ挙動をしますが…
FirstUを設定することで、端点を任意に指定できます(ポイント及びVtxは増えるので注意)
FirstU,SecondUを設定すると、始点終点をそれぞれ指定できます
※パラメトリック座標についてよく理解していない場合は、以下を参照
プリミティブのパラメトリック空間(暗黙的なUV): https://www.sidefx.com/ja/docs/houdini/model/primitive_spaces.html
何度読んでも難しい…
Facet
上記3つのSOPに共通する事項として
入力ポリゴンのエッジを構成するポイントがPrimitive間で共有されていれば、出力されるポリラインもポイントが共有されます
つまりポリラインがダブっている箇所があるのに、ジオメトリとしては切り離せないということになります
基本回避したい状況だと思いますので、FacetSOPを繋いでUniquePointsをチェックしてプリミティブ同士を切り離してから接続するようにしましょう
見かけでは分かりづらいので注意!
※ポイントと頂点についてよく理解していない場合は、以下を参照
ポイントと頂点: https://www.sidefx.com/ja/docs/houdini/model/points.html
各エッジでダブらないポリラインを抽出
ConvertLine,PolyPathは、上記3つと違ってダブらないポリラインを生成します
ConvertLine
各エッジに一つのポリラインを生成します
入力ジオメトリでポイントが共有されている場合は、ジオメトリとして繋がって出力されます
バラバラのポリラインにしたい場合は、FacetSOPを使用しましょう
FacetSOPの位置で挙動が変わります
右の結果はEndsSOPなどの出力結果と似ていますが、すべてのエッジが独立したポリラインになっている点で異なります
ちなみにダブルクリックで中を覗けます
結構シンプルな作りでわかりやすいです(こちらのVEX関数については後で説明します)
ポイント番号で駆動しているので、ポリラインの向きの制御が難しいです
向きのそろったポリラインが欲しい時は仕方なくVEXを書きます(VEX関数を参照)
PolyPath
できるだけ繋がったポリラインを生成します
左がConvertLineSOP,右がPolyPathSOPで、プリミティブごとに色分けしています
Sweepしたいときに良いです
こちらもダブルクリックで中を覗けます
trace_edgesというAttributeWrangleがキモです…が難しくてよくわかりません
いつか追記するかもしれません
VEX関数
addprim: https://www.sidefx.com/ja/docs/houdini/vex/functions/addprim.html
addvertex: https://www.sidefx.com/ja/docs/houdini/vex/functions/addvertex.html
の2つでとりあえずポリラインが作れます
↓↓に簡単なサンプルを用意しました
Wrangleの中身はこんな感じ
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);
//プリミティブの重心にポイントを作成
int newpt = addpoint(0,@P);
//構成ポイント毎に重心までのポリラインを作成
foreach(int ptnum;primpts){
int polyline = addprim(0,"polyline",newpt);
addvertex(0,polyline,ptnum);
}
//元のポリゴンを消去
removeprim(0,@primnum,1);
もっとこの辺りのVEXを詳しく知りたい方はこちらやこちらなどを参照してください
おまけで、Vtxの並び方が綺麗にパラメトリック座標に反映されたポリライン
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);
//構成ポイント毎にエッジを生成する
foreach(int ptnum;primpts){
int hedge = pointhedge(0, ptnum);
int ptnum_next = hedge_dstpoint(0,hedge);
addprim(0,"polyline",ptnum,ptnum_next);
}
//元のポリゴンを消去
removeprim(0,@primnum,1);
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);
//終点用に配列に始点を追加
push(primpts,primpts[0]);
//空のポリラインを作成
int polyline = addprim(0,"polyline");
//ポリラインに頂点を追加
foreach(int ptnum;primpts){
addvertex(0,polyline,ptnum);
}
//元のポリゴンを消去
removeprim(0,@primnum,1);