08/11:hipのエラー修正
こういうことをやりたい人がどれだけいるかわからないですが、忘れないようにメモ。
かなり無理矢理解決しているのでもっと効率いいやり方がありそうな気もする。
シーンファイル
usdexportCustom_v2.hiplc - Google ドライブ
・Houdini 19.5.682 ・ファイルを使用してなにか起きても何も責任は取りません。
問題
・空フレームが存在することがあるため空フレームをVisibilityのオンオフで制御したい。
・巨大なファイルサイズでもVisibilityのオンオフで制御したい。
・レンダー効率のためにhuskの-restart-delegateは使いたくない。
⇢USD Export (1 File)で書き出したときのような動作をシーケンスで達成したい。
USD Export (1 File)
USD Export (1 File)で書き出す場合はTrack Primitive Exsistence to Set Visibilityがオンであれば自動で可視不可視のチェックをしてくれる。
ただこれも万能ではないので、タイムスライダーより狭い範囲のキャッシュを撮る場合は前後の空フレーム部分がHoldされる。
USD Export (Sequence File)
シーケンスをシーケンスのまま$F4などを使用してLOPに読み込むと警告は出るのとレンダーシーン書き出し時にStitch処理が走ることを除けば割とほしい結果が得られる。
ただし、モーションブラーがちゃんとかからない。
Cacheノード(Motion Blurノード)とかを使おうとしてもたいていエラー
Geometry Sequence ノード
これとCacheノード(Motion Blurノード)を使えばブラーも掛けられるし、シーケンスファイルで扱える。
ただし、USDファイルは読めないので基本的にbgeoでの運用になる。
しかもこの方法は問題があり、基本レンダーシーンのUSDファイル内にGeometryが書き込まれる。
そのためレンダーシーンが肥大化&ファイルサイズが大きすぎると落ちる。
一応、レンダーシーンのUSDファイルをSeparate Layersにし、Geometry SequenceのLayer Save Path等を設定しておけば所定の場所に分割してファイルを書き出せる。これでメモリ不足等は少し解消できる。少し。
huskのオプション
USD Stitch Clips ROPを使用したとしても、USD Stitch Clipsだと空フレームがあった場合のVisibilityのオンオフが記録されないため
husk(バッチレンダリング)経由でレンダリングした際に問題が発生する。
フレーム | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
キャッシュ | なし | なし | なし | なし | あり | あり | あり | あり |
上記のような状態で、1~5fをレンダリングすると5fはレンダリングされない。なぜかというとUSD Stitch ClipsはデフォルトでVisibilityにTime Sampleがないため、レンダリングを始めた最初のフレームのVisibilityの値を取得してしまい、非表示になる。
これはhuskのオプションにある--restart-delegate nのフラグを使用することによって回避できる。
ただしヘルプにもあるとおりレンダーシーンを都度再構築するためレンダリング効率が落ちる。
解決!
キャッシュ書き出し時にVisibilityのTime Sampleを含ませる方法。
USD Stitch Clipsにはそのようなオプションは見当たらないため、どうにかVisibilityにTime Sampleをいれる。まあ要はUSD Stitch Clipsの元のValue Clipを使って0から組む…
Render, Proxy
どうせ書き出す処理作るならProxy Geoも作りたいのでこんな感じに。
Houdiniで作るFXキャッシュは重いのでProxy GeoもBBOXでいいかなということでメインはBBOX
※BBOXの形状をしたポリゴンです。
path Attributeがある場合の回避
このpath階層でいいかはどうかはおいておいて単純な回避の方法。
何もないとpathがこうなりがちで/render階層が消失する。
SOPの段階で以下VEXを使用してpath階層をちょっと書き換える。
string path = s@path; int check = re_find("/", path, 0, 1); if(check == 1) { s@path = slice(path, 1, len(path), 1); }
そうすることで自動的に/render/path〜〜になる。
USD Stitch
TOPを使い各種必要なファイルを書き出したものをUSD Fileとして結合する部分。
TOPで書き出したtopologyファイルをSublayerで読み込み、
別途元々のシーケンスファイルをValue Clipで読み込む。
Configure PrimitiveでPurposeをRenderとProxyにする。
同じことをProxyでも行い、WrangleノードでProxyのValue Clipファイルから取得した値からVisibilityを設定する。
Run on Elements of Array Attributes等を忘れずに設定する。
usd_setvisibilityは0か2で設定しないと正しく親の値を継承できないので注意
string children[] = usd_childnames(0, "/proxy"); string path = "/proxy/" + children[0]; int check = usd_attriblen(0, path, "points"); if(check == 0) { usd_setvisibility(0, @primpath, 0); }else{ usd_setvisibility(0, @primpath, 2); }
この部分はPayloadやAssemblyの階層を作っているだけなので省略
TOP
RenderとProxyのGeoを両方シーケンスで書き出して両方終わるのを待機
その後以下Pythonでtopologyとmanifestを書き出す。
※雑なのでたまにエラーで落ちます。ちゃんと使う場合は見直しましょう。
import os import glob from pxr import Sdf, UsdUtils out_path = str(work_item.attribValue("outputDir")) purpose = str(work_item.attribValue("purpose")) result = out_path + "data/" + purpose + ".usda" clipPath = "/" + purpose seq = glob.glob(out_path + purpose +"/*") topologyLayerName = UsdUtils.GenerateClipTopologyName(result) topologyLayer = Sdf.Layer.FindOrOpen(topologyLayerName) if not topologyLayer: topologyLayerGenerated = True topologyLayer = Sdf.Layer.CreateNew(topologyLayerName) manifestLayerName = UsdUtils.GenerateClipManifestName(result) manifestLayer = Sdf.Layer.FindOrOpen(manifestLayerName) if not manifestLayer: manifestLayerGenerated = True manifestLayer = Sdf.Layer.CreateNew(manifestLayerName) UsdUtils.StitchClipsTopology(topologyLayer, seq) UsdUtils.StitchClipsManifest(manifestLayer, topologyLayer, seq, clipPath)
元となっているPythonは$HFS/bin/usdstitchclips
です。必要そうな記述の箇所を抜き出して作ってるのでちゃんと読んで再構築しましょう。
Pythonでのtopologyとmanifestの書き出しが終わったら、すべてをStitchのUSDファイルを書き出します。
完成
取り敢えずこんな感じの階層になるように書き出してます。
Proxyを書き出しているのでViewport上は設定した軽いジオメトリが表示されます。
レンダリングすると実ジオメトリに。
/geo階層をPayloadしているのでUnloadも可
VisibilityのTime Sampleもあるのでちゃんと表示非表示が切り替わります。
もちろんMotion Blurも。