cg memo

備忘録をまとめるブログ

Houdini Group Work

Houdini でのグループ操作の備忘録をまとめました。ショートカットキーなどはWindows版となっています。


グループの確認

Viewport上で[9]キーで、グループ選択ディスプレイ(?)のON/OFFができます。
point や primitive などのコンポーネントの変更は、歯車マークから。
ハイライト色が見づらければ、右側の色の付いた四角をクリックすると変更できます。

f:id:satyk:20180110132848j:plain


ノード名をグループ名にする

Group (Group Create) SOP の Group Name 欄に、以下のように入力すると、ノード名がグループ名となります。

`opname(".")`

この方法は「gametutor」で知りました。
http://www.gametutor.com/live/home-live/

`$OS

上記でも同様の効果があります。
こちらは杉村さんのワークショップで知りました。ありがとうございます。:)

基本のGroup

各手法の Enable にチェックを入れると設定項目が表示されます。

f:id:satyk:20180111134259j:plain

- Base Group

point番号 や prim番号 などを入力してグループ化ができます。
Viewportでコンポーネントを手動選択してから Group SOP を作成すると、その 番号 が入力された Group SOP になります。
ただ、上流でトポロジが変化すると番号が変わってしまいますので、番号を直接指定することはあまりしません。
 $F などのローカル変数や、 @P.y>0 などのアトリビュートを使った構文で指定することが多いです。

インディゾーンさんのブログや、Houdiniのリファレンスにもあるように、VEXとは違って@構文にスペースを入れるとエラーになるので注意が必要です。

【参考1】
Group geometry node - "@ syntax does not allow spaces."
http://www.sidefx.com/docs/houdini/nodes/sop/groupcreate.html

【参考2】
グループの所でアトリビュートを直で指定 | インディゾーンHoudini情報日本語ブログ

Group Expression SOP を使えば、構文にスペースが入っていても大丈夫なようです。

- Keep in Bounding Regions

グループにしたい箇所の位置が分かっていて、計算式を考えるのが面倒なときは、いつもバウンディングで指定しています。
パラメータを使ってバウンディングを作っても良いですが、input の 2つめに Object を入力し、プルダウンを「Bounding Object (points only)」(もしくはVolume) にします。
また、(points only)と書いてあるように、point のグループしか作れないようなので、Group Type を「Points」にします。
グループ位置をアニメーションさせたい時などは、この手法が一番良いのかも?

f:id:satyk:20180111233219p:plain

- Keep by Normals

法線方向でグループ化できます。
下記は、Direction が「0,1,0」で Spread Angle が「60」の場合です。

f:id:satyk:20180111234305p:plain

使った事なかったのですが、「Backface from」は特定のオブジェクトから見て背後になるメッシュをグループ化するようです。
基準となるノードをパスで指定するのですが、この場合に指定するノードはSOPノードではなく、GeometryなどのObjectノードのようです。
従って、指定したgeoノード内の Transform は反映されず、純粋にObjectノードのポジションを見るようです。
おそらく Camera からの Backface culling などのために使われるものと思われます。

f:id:satyk:20180112000537p:plain

「Non-Planar Polys」は、tolerance を加味しつつ非平面のポリゴン primitive をグループ化します。

f:id:satyk:20180111235716p:plain

- Include by Edges

ボーダーエッジのみをグループにする時によく使います。
「Unshared Edges」 にチェックを入れるだけです。
Group Type を 「Edge」 にすればボーダーエッジとしてグループ化できます。point や primitive にも対応しています。
エッジの長さ指定などもできるので、色々工夫できそうです。

f:id:satyk:20180110133732j:plain


Wrangle でのグループ処理

グループは Attribute の亜種として扱われているようで、スプレッドシートから確認することができます。
そのグループに属していれば「1」、属していなければ「0」となります。

//戻り値int setpointgroup(インプット番号, グループ名, ポイント番号, 属しているかどうか)
int newpointNum = 0;
setpointgroup(0, "groupname", newpointNum, 1);

当然  setedgegroup  setprimgroup  もあります。ただ、エッジグループについては、スプレッドシートから確認する方法が無いような気がします。
グループの中身を配列で取得する時は  expandpointgroup  を使います。

グループは、他のアトリビュートと同様に、宣言しなくても唐突に作ることができます。
また、 i@group_グループ名 を使って、「1」「0」だけで追加や除外ができます。

if (@P.x>0){
    i@group_test = 1;
}

この場合、グループ「test」が作成されて、x座標がプラスのポイントがそのグループに属します。

Wrangle でグループを作った時は、Bindings タブの Output Selection Group にグループ名を入れる事でハイライトできます。


Subdivide した時の分割線をグループにする

1枚の板ポリを Subdivide SOP で四分木(Quadtree)に割った後の、縦もしくは横のpoint群のグループ化です。
Subdivide SOP で直接グループを作成してくれれば楽なのですが、そういった機能は見つけられませんでした。(Edge divide も)

f:id:satyk:20180112011441p:plain

サーフェスノードのバウンディング重心を返す  centroid  エクスプレッション関数を使いました。

@P.y==`centroid("../split1",D_Y)`

 @P.y>0 などとは違って、エクスプレッション関数部分を「`」でかこまないといけませんでした。
詳細はよく分からなかったのですが、そういうものなのでしょうか?
このケースでは、 Subdivide 処理した板ポリはメッシュ群のうちの1枚なので、splitでそれを抽出し、split SOP からバウンディングを取っています。
何かもっとスマートな方法もありそうな…。


ループを使った複数グループのリネーム

For-Loop を使用して、大量にあるグループのリネームを行います。
サフィックスがナンバリングで、そのリネームおよびソートを行うケースです。

「aaa_0」「aaa_2」「bbb_0」「bbb_1」とある場合に「aaa_*」だけを「ccc_0」「ccc_1」にしたい。

f:id:satyk:20180112124550p:plain

1.
For-Loop with Feedback SOPを作成します

2.
repeat_end ノード の Iteration に以下のエクスプレッションを記入します。

argc(pointgrouplist("../null1"))

3.
repeat_begin ノード の「Create Meta Import Node」ボタンを押下して repeat_begin_metadata ノード を生成します。これが"iteration"アトリビュートを持っています。

4.
ループ内に Group Rename SOP を入れ、以下のエクスプレッションを記入します。
Group:

`arg(pointgroupmask("../null1","aaa*"),detail("../repeat_begin1_metadata1", "iteration", 0))`

New Name:

ccc_`detail("../repeat_begin1_metadata1", "iteration", 0)`

5.
「ccc_0」「ccc_1」「bbb_0」「bbb_1」となりました。

エクスプレッションmemo(1)

argc(pointgrouplist("../null1"))
  • argc(line) …文字列lineをスペースで区切った時の単語数を返します。
  • pointgrouplist(surface_node) …指定したノードのpointグループ名をスペース区切りにした文字列を返します。

null1ノードのpointグループには「aaa_0」「aaa_2」「bbb_0」「bbb_1」が存在するので、
pointgrouplistによって文字列「aaa_0 aaa_2 bbb_0 bbb_1」が返されます。

argc(aaa_0 aaa_2 bbb_0 bbb_1)

4

Iteration 回数は「4」になります(ぴったりグループ数ぶんだけ反復する)

エクスプレッションmemo(2)

ccc_`detail("../repeat_begin1_metadata1", "iteration", 0)`

repeat_begin1_metadata1 ノードには、ループ時のみ使用される特殊なアトリビュートがあり、
そのうちの"iteration"(現在の反復回数)を取得しています。

リネーム後の名前は「ccc_」+「現在の反復回数」

「ccc_0」「ccc_1」にリネームされる

エクスプレッションmemo(3)

`arg(pointgroupmask("../null1","aaa*"),detail("../repeat_begin1_metadata1", "iteration", 0))`
  • arg(line, argNum) …文字列lineをスペースで区切った時のNum番目の単語を返します。
  • pointgroupmask(surface_node, pattern) …指定したノードのうちパターンにマッチするpointグループ名を、スペース区切りにした文字列で返します。

pointgroupmaskで"aaa*"にマッチするグループ名を文字列で取得(「aaa_0 aaa_2」)

「aaa_0 aaa_2」のうち「現在の反復回数」番目の単語を取得(反復1回目なら「aaa_0」)

グループ名に「aaa_0」や「aaa_2」が入る

Game Development Toolset にもグループ関連のSOPがあったので、ついでにそちらも確認してみました。

Group Expand

グループの拡張と縮小ができます。

  1. 任意のグループを作成します。
  2. Group Expand SOP を作成し、グループ名を選択します。
  3. 「Iterations」をプラスに増やすとグループが拡張し、マイナスにすると縮小します。

https://i.gyazo.com/904e5412407ea14e7fb35723bc0f9621.gif

Group Edge Loop

エッジループとエッジリングのグループを作成します。

  1. 任意のエッジを2本選択し、グループ化します。
  2. Group Edge Loop SOP を作成し、グループ名を選択します。
  3. 2本のエッジが水平にあれば、エッジループになります。2本のエッジがパラレルであれば、エッジリングになります。
  4. 「Step」を増やすと、1つ飛ばしや、2つ飛ばしの選択になります。

f:id:satyk:20180113103717p:plain
f:id:satyk:20180113103724p:plain

公式のチュートリアルムービーでは、1つのエッジだけを選択しているようですが、現在の仕様(ver.1.8)では、2つのエッジを選択していないとエラーになるようです。
また、エッジを3本以上選択して階段状のエッジグループなども作れましたが、場合によっては Fatal Error で落ちました…。鋭意開発中という感じですね。

以上となります。

その他の Group 関連の記事は、インディゾーンさんで詳しく書かれています。
houdini.indyzone.jp