すあまの備忘録

誰得内容の自分のための非営利目的備忘録ブログ(筆者がわかっても内緒にしてください)

Solaris - Instancer LOPあれこれメモ

Instancerをフローに乗せるためにいろいろ調べてみた結果のメモ

メモっておかないとすぐ忘れるので。

Houdini 19.5.534でテスト。

Instancerメモ

  • Location PrimitiveやPrototype Sourceの指定は積極的にマッチングパターンを使用しないとミスが起きる
  • SOP上(USD内の)のN,up,orient,pscale,scaleを認識する。
  • 各種アトリビュートをInstancerがUSD用のorientarions,scales,positionsに変換する。
  • 基本的にレンダリング時に変換結果がRender Scene USDに配列情報で書き込まれ、肥大化する傾向にある。どうもこれは回避できない。(Configure Layer等でSave Layer Pathをしない場合)
  • USDのPointを使用した場合、生成されるアトリビュートにタイムサンプルがないため、Render Scene USDで書き出した際に動かない。
  • Indexは自然順でソートされていないため、SOP上のIndexとずれることがある。
  • USD Pointの場合は、Nameアトリビュートを別のアトリビュート名にしないとPrimitive Pathになってしまう。
  • USD Pointの場合は、USD Export時にUSD Custom Attributeでnameにしたいものを指定しないと書き出されない。
  • Lightのインスタンスの場合はInternal / External SOPで、MethodがReference, Inherit, Specializeのどれかである必要がある。
  • Lightのインスタンス時はSOP上のCdをライトの色として認識する。

複数ジオメトリを1つのUSDで書き出す

一度Assembleし、USD Export時のPacked PrimitivesでCreate Xformsにすると簡単に出せる。

Stage上だとこんな感じ。

ジオメトリの読み込み

Add Variant等を使用しなくてもMergeで繋いだものをぶっ刺してもPrototype Primitiveとして読みこめる。

もちろんUSD的には~ということもあるが、後述するUSDとSOPでIndexがずれる問題があるので、

回避するためにnameを直指定したい場合などにAdd Variantを経由するとnameの指定がとてもめんどくさい。ちゃんとしたフローを整えてアセットを読み込まないのであれば、Mergeでも良いんじゃないかと思う。

マッチングパターン

手入力は事故が起きるので、デフォルトを書き換えたほうが良い。Prototype Primitivesの方は、アセットの使用に則って%highest%kind:assemblyなども良いと思う。

マテリアルアサイ

アサインする際の仕組みに注意。(以下はPoint Instancerの場合)

先にアサインする場合

以下の画像を参考に。赤枠の方はマテリアルがちゃんと継承される。

なぜかというと、Scene Graph Tree上で以下画像赤枠がInstanceに使用されるので、その階層以下にあるマテリアルも同時に継承される。

右側は階層が並列になっているのでマテリアルが継承がおかしくなる。

あとでアサインする場合

Prototypes階層下にあるジオメトリにアサインする。

ファイルサイズ

Location SourceがInternal / External SOPの場合(SOPを経由している)と、一度PointをUSDに書き出してインスタンスした場合

どちらもちゃんと書き出せていればファイルサイズは変わらない。ただし、SOPを経由する場合は使用していないアトリビュート(例えばスケールしてない場合とか)はアトリビュートを生成しないのでその分ファイルサイズが小さくなる。

USD Pointの場合はその部分を丁寧に処理してあげたほうが良い。

参考までに10万ポイントでのファイルサイズ比較

ファイル usda usdc(usd)
SOPからのpoint 1.7GB 164.8MB
レンダーシーンUSD 917.2MB 201.2MB
レンダーシーンUSD(スケールなし) 862.1MB 82.4MB

SOPとUSD Pointどっちがいいか?

SOPの方が手間が少し少なくセットアップを組める印象。

ただし、USD Pointの場合はStage上からPointをUnloadすることによって、一度設定した後はレンダリング時以外で大量のインスタンスの計算をしないというのが手軽にできる。

SOPでももちろんできるが一度SOP階層行ったりして少し手間。

中間キャッシュを取る場合もusdaでとらなければファイルサイズはUSD Pointのが少ない。

Render Scene USDに書き込みたくない場合

必ず移動回転などの情報が配列で記録されるのでそのままだとRender Scene USDが肥大化する。

特にusdaでRender Scene USDを記録したい場合はファイルサイズの肥大化が致命的。

その場合はConfigure LayerのSave Layer PathでInstancerの結果だけusdcで保存すればファイルサイズが小さくなる。

もしくは一度手動でUSDとして書き出して再度読み込んでレンダーシーンを作成する。

USDのPointにInstanceしたものがRender Scene USDに書き込まれない(動かない)

以下画像のような構成の場合、USD ROPにインスタンサーの結果が書き込まれない。(※ローカル上では動いて見える)

Modify Point Instancesで回避

これを回避するには、Modify Point Instancesノードを以下のような設定でInstancer後に使用する。(Point InstancerはInstancer名+[*])

VEXで回避

もしくは、以下VEXで再度上書きすると回避できる。ただしこの場合は存在しない値などがあった場合の回避処理なども入れないとファイルサイズの肥大化なども招くので注意。

なぜこの現象が起きるのかというと、USD Pointに対してインスタンスした場合はorientations,scales,positionsにタイムサンプルがつかない(連続したアニメーションと認識されていない)

※緑色がタイムサンプルあり、水色がなし。アニメーションしているものは緑色である必要がある。

タイムサンプルあり
タイムサンプルなし

Index順をSOPに合わせる

Prototype Primitivesに読まれた順=Indexなので、Scene Graph Tree上は自然順でソートされていてもExpressionでの読み込み後にIndex順がずれる。

このため、数字で2桁に到達する場合は0,1,10,2,3...のようになるので末尾に英語でA,B,C,Dのほうが良い。2桁に到達しないなら問題ない。

nameに使用したいアトリビュートを書き出す

別途書き出して認識させたい場合はUSD Custom Attributeで指定する。RBD Material Fractureなどで生成される値がpiece-0-0のようになるが、USDのPrimitive Pathにはハイフン(-)は使えないのでアンダースコア(_)などに直しておく必要がある。

Stage上でTransform Piecesをする

意味あるのかって言われたらジオメトリとPoint別で出せていいかも。くらい。正直ポイントをSOPで読んだ方が早いし楽。

以下のようなシーンで一度Transform Piecesを使用する。

この際に左側のハイポリも一度Pack状態にしておく。

各破片の処理

ハイポリをそのまま以下の処理をした後に複数ジオメトリを1つのUSDで書き出すと同じ方法で書き出す。

ポイントの処理

一度Transform Piecesをした後に以下VEXでorientとscaleを取り出し、PointにPromoteする。

matrix3 trans = primintrinsic(0, "transform", @primnum);
vector cross = normalize(set(trans.xx,trans.xy,trans.xz));
vector up = normalize(set(trans.yx,trans.yy,trans.yz));
vector normal = normalize(set(trans.zx,trans.zy,trans.zz));
matrix3 rotM = set(cross, up, normal);
matrix3 scaleM =  trans * invert(rotM);

@scale = set(scaleM.xx, scaleM.yy, scaleM.zz);
p@orient = quaternion(maketransform(normal, up));

各破片のnameを別のアトリビュート名にし、不要なものを削除。(そのままだとStage上でPrimitive Pathになってしまうため)

そのままだと作成したname用のアトリビュートは認識されないので、認識できるように以下設定をして書き出す。

Stage上の設定

画像のように組む。

InstancerでPrototype IndexをName Attributeにし、Name Attributeを先ほど作成したnameようのものにする。