kick the base

Houdiniと、CG技術と、日々のこと。

Houdini: アトリビュートの初期値について

Houdini楽しんでますか?ぼくはありがたいことに忙しい日々を過ごしています。 今回はとても小さなTipsのご紹介ですが、広範囲で使える知識なのでご存じなかった方はぜひ今後使ってみてください。

f:id:kickbase:20210207141115p:plain

今回のテーマは上記画像に尽きるのですが、一行目のVEXが「何をしているか」がわかりますでしょうか。わかってればこの記事から得られることはありません(笑)

しかし、もし「アトリビュートの前に型が書いてある…?」みたいな感じでしたらぜひ引き続き読んでみてください。アトリビュートをひとつ深く使いこなせるようになるかと思います。

目次

シーンファイル配布

シーンファイルはこちらからダウンロード可能です。

シーンの作成環境は下記のとおりです。

  • Windows10
  • Houdini 18.5.408

基礎

まずはアトリビュート自体のお話。簡単にふたつのノードでポイントアトリビュートを与えるシーンを作ってみました。

f:id:kickbase:20210207141359p:plain

if(@P.x > 0) @test = 5;

VEXコードは一行。これは説明不要かと思いますが、念の為簡単に解説します。

最初のif文で「ポイントのX座標がゼロより大きいかどうか」を判定しています。つまりポイントの位置がビューポートでX座標ゼロより右側にあれば条件式はTrueになり続く@test = 5が実行されます。

つまり、X座標がゼロより右側にあるポイント全てにtestというアトリビュート5が付与される1ということです。

ここで質問です。ifの条件を満たさないポイント、つまりゼロより左側にあるものはアトリビュートが作られないのでしょうか?

答えはtestアトリビュート0が付与されます。ビューポート上でもジオメトリスプレッドシートでも確認できますね。

この勝手に作られる0という値をコントロールしようというのが今回のテーマです。

デフォルト値の指定をしないとどんな問題が起こるか

回避方法はいくつかあるのですが、ここではデフォルト値を明示的に指定しなかったため予期せぬ問題が起こってしまったケースを見ていきましょう

グリッドを作る

f:id:kickbase:20210207144044p:plain

Subdivideする

f:id:kickbase:20210207144059p:plain

Sortでプリミティブナンバーをランダムにする

f:id:kickbase:20210207144116p:plain

プリミティブナンバーをアトリビュートとして保持する

f:id:kickbase:20210207144132p:plain

i@primid = @primnum;

プリミティブを削除する

自分で作ったパラメータ、target_idとprimidアトリビュートが等しいとき、プリミティブ(面)を削除します。

f:id:kickbase:20210207144156p:plain

if(i@primid == chi("target_id")) removeprim(0, @primnum, 1);

target_idを0から15まで変更してプリミティブを削除する方法は本来良い手法ではないのですが、解説の都合上使用しています

f:id:kickbase:20210207190357g:plain

問題なさそうですね。しかし、Mergeで他のジオメトリをまとめたあとにプリミティを削除する処理を入れるとどうなるでしょう?

アトリビュート作成前にストリームを分岐させた場合

アトリビュートを付与しているノード(attribwrangle_primid)の前にストリームを分岐させた場合、primidが付与されていないジオメトリ(分割前の大きいグリッド)ができるので自動的にprimid = 0が付与されます。

f:id:kickbase:20210207145825p:plain

デフォルト値を意識しないと意図しない結果に

primidを元に削除すると、primid==0のプリミティブが重複するので同時に消えてしまいます。これが意図した動作であればOKですが、右の大きいグリッドは常に消したくない場合はどうすればよいでしょう。

f:id:kickbase:20210207150726p:plain

デフォルト値を明示的に指定しよう

f:id:kickbase:20210207152104p:plain

下記コードの1行目はデフォルト値の明示的な指定だったわけですね。

int @primid = -1; //here
i@primid = @primnum;

このようにデフォルト値を指定すると大きいグリッドが事故で削除されることを防ぐことができます。

f:id:kickbase:20210207152500p:plain

当然ながらAttribute Createでもデフォルト値は設定できます

今回のVEXコードと同様の設定は下記パラメータで実現2できます。

f:id:kickbase:20210207152821p:plain

線形補間のコントロールにも便利

HoudiniではResampleやClipを用いてアトリビュートの線形補間する(中間をリニアな値で埋める)ことが多々ありますが、そのレンジもアトリビュートのデフォルト値を利用することで柔軟にコントロールすることができます。

まずは基本のやり方から確認していきましょう。

ポイント数2のLineを作成する

f:id:kickbase:20210207155838p:plain

ビューポート上水色の数値がポイントナンバーを示しています

任意のポイントにアトリビュートを設定する

Attribute WrangleのGroupにポイントナンバーを指定してWrangleの適用範囲を限定します。ここではポイントナンバー1に対して@pid = 1;を実行しました。

繰り返しますが、デフォルト値を指定していないので他部分(つまりここではポイントナンバー0)には自動でpidアトリビュートゼロが付与されます。

f:id:kickbase:20210207160006p:plain

ビューポート黄色の数値がpidアトリビュートを示しています

Resampleを接続

ご覧の通り、0-1の範囲でアトリビュートが補完されているのがわかりますね。これは非常によく使うテクニックですので慣れていない方はこれを期にぜひ覚えておくと良いでしょう。

f:id:kickbase:20210207160025p:plain

デフォルト値を設定する

LineSOPに続けてAttribute Wrangleをつなぎ、下記コードを実装しましょう。

f:id:kickbase:20210207160045p:plain

float @pid = -1;
@pid = 1;

ポイントナンバー1に対して@pid = 1;を実行するところは同じですが、1行目に初期値-1を設定していますね。これによりポイントナンバー0のpidは-1になります。

Resampleを接続

今度はアトリビュートが-1~1の間でマッピングされました。0から1-1から1-1から0などのレンジはケースバイケースで使用したい場面が異なりますのでうまく活用していきましょう。

f:id:kickbase:20210207160107p:plain

まとめ

非常に基本的な内容でしたが、アトリビュートのデフォルト値は大切だよ。気をつけていないと事故るよ。というお話でした。

Houdiniを使うということはアトリビュートを変更するということとほとんど同義なので、どんなときもスマートにアトリビュートをコントロールしたいものですね。


  1. @test = 5f@test = 5の省略形の書き方で、アトリビュートはfloat型だよという情報が隠れています。

  2. もちろんこれでも問題ないのですが、Attribute Createは作成するアトリビュートのデータ型(ディメンション)問わずインプット欄がいっぱいあるのであまりスマートな見た目になりません。個人的にはアトリビュート作成はWrangleを使うことをおすすめします。