Houdini 19.0 Solaris

USDへ書き出す方法

On this page

概要

USDの背景情報、LOPノードがUSDレイヤーを生成する方法については、USDの基本LOPノードについてを参照してください。

LOPネットワークは、USDステージをゼロから、または、トップレベルのUSDファイルから生成し、場合によってはファイルからUSDレイヤーを追加します。 ネットワークの最後では、完了したUSDを書き出すことができます。これには、トップレベルのファイルとレイヤー毎のファイルといった複数ファイルの書き出しを伴うことが多いです。

ディスクから読み込まれたレイヤーは、保存工程では常に変更なしのままになります。とはいっても、LOPノードで生成された匿名レイヤーは、既存のディスク上のレイヤーファイルを上書きすることができます。

How to

  • USDを書き出すメインノードは、USDレンダーノードです。このノードは、LOP(LOPネットワークの最後に配置することができます)またはROP(レンダーネットワーク内に配置して、出力したいLOPネットワークを指すことができます)として利用可能です。

    (特別なオプションの詳細は、以下のUSDを書き出す別の方法を参照してください。)

  • USD Zipレンダーノードを使用することもできます。これは自己完結型のUSDZファイルを出力します。このファイルは、すべてのトップレベルのUSD、レイヤーファイル、(テクスチャなどの)外部ファイルなどを含んだアーカイブです。

    USDZは、単一ファイルの利便性を持ちつつ“緩い”ファイルのすべての編集性を保持します。 また、アーカイブから効率的にUSDを直接読み込む機能もあります。これは、インターネット上でUSDを公開するのに非常に便利です。

ファイルの出力先

  • USDレンダーノードでは、ルートレイヤーのデータを含んだ“トップレベル”のUSDファイルのファイルパス( Output File パラメータ)を指定します。

    このファイルの他にも、このノードは、ファイルパスメタデータでUSDファイルの出力先が設定されているレイヤーを書き出します。

  • ディスクから取り込まれたレイヤーは、そのファイルのパスを記憶し、トップレベルのファイルを基準にそのパスにレイヤーが書き出されます。

  • Configure Layer LOPを使用することで、ネットワーク内のレイヤーのファイルパスを割り当て/変更することができます。USDを出力する時、そのレイヤーがディスクに書き出されるようになります。

  • SOP Import LOPSOP Create LOPでも、USDを書き出す時に書き出されるジオメトリのファイルパスを指定することができます。

  • Houdiniのファイルパスは通常ではHIPファイルを基準に指定($HIP/props/lamp.usd)するのに対して、USDのパスはトップレベルのファイルを基準(./props/lamp.usd)にすることを推奨します。USDレンダーノードは、このノードがUSDを書き出す時に、パスをトップレベルのファイルを基準に変換するデフォルトの出力プロセッサを持っています。

  • USDレンダーノードの Flush Data After Each Frame パラメータは、各フレームを計算した後にデータをディスクに書き出すかどうかを制御します。 このオプションを使用することで、それぞれ単一タイムサンプルを含んだUSDファイルのシーケンス(例えば、lamp_0001.usdlamp_0002.usdなど)または全フレームのタイムサンプルデータを含んだ単一ファイルを生成することができます。

出力プロセッサ

出力プロセッサは、外部ファイルで使用されているファイルの場所とファイルパス文字列を変更することができるPythonプラグインです。

USDレンダーノードは、レイヤーファイル内のファイルパス参照を相対パスに変換するデフォルトの出力プロセッサを使って開始します。

独自の出力プロセッサを記述する方法

  1. $HOUDINI_USER_PREFS_DIR/husdplugins/outputprocessorsという新しいディレクトリを作成します。

    (この例では、私どもはユーザープリファレンスディレクトリ内にこのプラグインを作成していきます。もちろん、Houdiniパス上の任意のディレクトリ下にhusdplugins/outputprocessorsディレクトリを配置しても構いません。)

  2. $HOUDINI_USER_PREFS_DIR/husdplugins/outputprocessors内に、出力プロセッサプラグイン用のPythonファイルを作成します。例:

    $HOUDINI_USER_PREFS_DIR/husdplugins/outputprocessors/outputreview.py
    
  3. Pythonプラグインファイル内で、husd.outputprocessor.OutputProcessorクラスをサブクラスにします。

    このサブクラス内で、固有名を返すname()メソッド、出力プロセッサの処理内容(例えば、出力パスを基準にパスを保存)を記述した文字列を返すdisplayName()メソッドを実装します。

    import hou
    from husd.outputprocessor import OutputProcessor
    
    class ReviewOutputProcessor(OutputProcessor):
        def name(self):
            return "review"
        def displayName(self):
            return "Manually Review Every Output Path"
    
  4. このファイルの最後に、引数なしで受け取り、コールされる度にクラスの 単一インスタンス を返すusdOutputProcessor()という名前の関数を定義します。

    この関数は、このモジュールを出力プロセッサの実装としてマーク(Houdiniは、この関数を含んだモジュールを検索します)、Houdiniが出力プロセッサオブジェクトの取得方法(Houdiniはクラスを直接インスタンス化せず、常にこの関数を使用します)を示すためにあります。

    import hou
    from husd.outputprocessor import OutputProcessor
    
    class ReviewOutputProcessor(OutputProcessor):
        def name(self):
            return __class__.__name__
        def displayName(self):
            return "Display the list of output files"
    
    # 以下の記述が必須です: プロセッサインスタンスを返すモジュールレベルの関数
    outputprocessor = ReviewOutputProcessor()
    def usdOutputProcessor():
        return outputprocessor
    

    Note

    現在のところ、レンダーノードはオブジェクトに対してメソッドをコールする必要がある度にファクトリーメソッドを何度もコールするので、単一インスタンスを維持して返さなければなりません。 そのため、現在のところ、常に同じインスタンスを返す場合はコール間で情報を維持することしかできません。 これはおそらく今後のバージョンのHoudiniで変更されます。

  5. あなたの出力プロセッサを実装できるようにAPIメソッドをオーバーライドします。以下の出力プロセッサAPIを参照してください。

    import hou
    from husd.outputprocessor import OutputProcessor
    
    class ReviewOutputProcessor(OutputProcessor):
        def name(self):
            return "displayoutputfiles"
        def displayName(self):
            return "Display the list of output files"
    
        def processSavePath(self, asset_path, asset_is_layer):
            # アセットパスを絶対パスにします。
            asset_path = hou.text.abspath(asset_path)
    
            # このプロセッサは、ユーザーに手動ですべてのファイルパスを書き換えるように促します。
            # これは単なるサンプルなので、実行しないでください! 面倒くさいことになります!
            return hou.ui.readInput(
                message="Rewrite this output file path if you want",
                initial_contents=asset_path,
                buttons=("OK",),
            )
    
        def processReferencePath(self, asset_path, source_path, asset_is_layer):
            # ファイルパスがソースファイルの位置を基準に指すようにします。
            return hou.text.relpath(asset_path, source_path)
    
    # 以下の記述が必須です: プロセッサインスタンスを返すモジュールレベルの関数
    outputprocessor = ReviewOutputProcessor()
    def usdOutputProcessor():
        return outputprocessor
    

出力プロセッサメソッドAPI

hidden(self)bool

このメソッドがTrueを返すと、このプロセッサは、ユーザーに表示される出力プロセッサのリストに含まれません。 デフォルトの実装は常にFalseを返します。

name(self)str (REQUIRED)

プロセッサの固有名を返します。

Note

必ずサブクラス内でこのメソッドをオーバーライドしてください。 そうしないと、Houdiniがあなたのクラスをインスタンス化しようとした時にNotImplementedError例外が発生します。

displayName(self)str (REQUIRED)

ユーザーに表示される出力プロセッサのリスト内でそのプロセッサについて記述したラベルを返します。

このラベルには、プロセッサの機能について記述してください。例えば、Save Paths Relative to Output Pathです。

Note

必ずサブクラス内でこのメソッドをオーバーライドしてください。 そうしないと、Houdiniがあなたのクラスをインスタンス化しようとした時にNotImplementedError例外が発生します。

parameters(self)str

このプロセッサがユーザー側で設定できるように表示するパラメータを記述したHoudini“ダイアログスクリプト”を含んだ文字列を返します。

デフォルトの実装は、空っぽのパラメータグループのスクリプトを返すので、 あなたのプロセッサが何もパラメータを必要としないなら、このメソッドをオーバーライドする必要はありません

hou.ParmTemplateオブジェクトを中で使ってhou.ParmTemplateGroupを構築して、hou.ParmTemplateGroup.asDialogScript()から値を返すことで、ダイアログスクリプトを生成することができます。

group = hou.ParmTemplateGroup()
group.append(hou.StringParmTemplate(
    "texturedir",
    "Texture Directory",
    string_type=hou.stringParmType.FileReference
))
return group.asDialogScript()

ここで作成するパラメータの内部名は、必ずレンダーノード上の他のすべてのパラメータ間で固有でなければならないので、 modulename_parmnameのような命名規則を使用するのが良いでしょう(modulenamehusdplugins/outputprocessors下のPythonモジュールの名前です)。

beginSave(self, config_node, config_overrides, t)

このプロセッサを使ったレンダーノードがファイルの書き出しを始めた時にコールされます。 この時にパラメータ値(必要な情報に基づいてparameters()で追加されたコンフィグパラメータまたはレンダーノード自体のパラメータのどれか)を読み込む機会が得られます。

config_node

レンダーノードを表現したhou.Nodeオブジェクト。

config_overrides

このノード上に設定可能な値を上書きする際に使用する値のdictOutputProcessor.evalConfigメソッドを使用することで、config_node上のマッチしたパラメータを評価して設定値を照会し、 利用可能であればこの辞書からオーバーライド値を受け入れ、利用不可であれば代替値を使用します。

t

このノードがレンダリングするタイムラインに沿った時間(秒)を表現した浮動小数点値。 このノードからパラメータ値を読み込む時、そのパラメータがアニメーションしている場合はParm.evalAtTime(t)を使用してください。

processSavePath(self, asset_path, is_layer)str

レンダーノードがアセットを保存するディスク上の場所を決定する必要がある時にコールされます。 asset_pathは、Houdiniが(例えば、USDメタデータまたはHoudiniパラメータから)理解できるファイルパスです。

これは、アセットの保存先となる絶対パスを返してください。 (このメソッドで相対パスを返した場合、そのパスは現行ディレクトリ(os.getcwd())を基準にしたパスになります。おそらくそれはあなたが求めているものではないでしょう)

asset_path

Houdiniで指定されたとおりのアセットのパス。 この文字列は、エクスプレッションと環境変数(例えば$HIP)が既に展開された状態になるので、 他のパスと比較したい場合は、(例えば、os.path.expandvars()hou.text.expandString()を使って)そのパスも展開してください。

is_layer

このアセットがUSDレイヤーファイルかどうかを示したブール値。 これがFalseの場合、そのアセットは他の何かです(例えば、テクスチャやボリュームのファイル)。

Note

行内の最初のプロセッサのみが、元々Houdiniに存在したかのようにasset_pathを見ます。 行内のそれ以外のすべてのプロセッサに関しては、最初のコールが返した絶対パスを受け取ります。

processReferencePath(self, asset_path, asset_saved_path, source_path, is_layer)str

レンダーノードがアセット(ファイル内のサブレイヤーまたは参照)を指したファイルパスを書き出す必要がある時にコールされます。

asset_path

Houdiniで指定されたとおりのアセットのパス。 これは、アセットが保存された時にprocessSavePath()に渡されるものと同じ文字列です。 そのコールから返された値は、このメソッドにasset_saved_pathとして渡します。

asset_saved_path

アセットの処理された絶対保存場所。 この文字列は、エクスプレッションと環境変数(例えば$HIP)が既に展開された状態になるので、 他のパスと比較したい場合は、(例えば、os.path.expandvars()hou.text.expandString()を使って)そのパスも展開してください。

source_path

書き出されるポインタを含んだ“ソース”ファイルの処理された絶対保存場所。 これを使用することで、そのパスを相対パスにすることができます。(例えば、hou.text.relpath(asset_saved_path, source_path))。

is_layer

このアセットがUSDレイヤーファイルかどうかを示したブール値。 これがFalseの場合、そのアセットは他の何かです(例えば、テクスチャやボリュームのファイル)。

スクリプトで出力プロセッサを追加する方法

  • Houdiniは、USDレンダーノードインスタンスのenableoutputprocessor_modulename(modulenamehusdplugins/outputprocessors下のPythonモジュールの名前)という名前のSpareチェックボックスパラメータが有効になっていれば、そのノード上の出力プロセッサを使用します。

    例えば、$HOUDINI_USER_PREFS_DIR/husdplugins/outputprocessors/myprocessor.pyで独自のクラスを実装した場合、ノード上にプロセッサをアクティブ化するためのenableoutputprocessor_myprocessorという名前のSpareチェックボックスパラメータを用意する必要があります。

  • これは、ユーザーインターフェース内のプロセッサリストでプロセッサが非表示(上記のhidden()メソッドを参照)になっていたとしても、スクリプトなどで正しいパラメータを作成してそれを有効にすることで、そのプロセッサを有効にすることができることを意味します。

    Spareチェックボックスを無効またはSpareパラメータを削除することで、プロセッサを無効にすることができます。

  • 出力プロセッサが設定用の追加パラメータ(上記のparameters()メソッドを参照)を持っている場合でも、スクリプトでそれらのパラメータを作成して値を設定することができます。

アニメーションを保存する方法

USDレンダーノードの Flush Data After Each Frame パラメータは、各フレームのデータを生成した後にデータを書き出すのかどうかを制御します。 この機能を使用することで、各フレームのデータを含んだファイルを個々に作成したり、制限なくすべてのフレームのタイムサンプルデータを含んだ大きなファイルを作成することができます。

USDレンダーノードの Flush Data After Each Frame を無効にしてフレーム範囲を書き出す時:

  1. このROPは、フレーム毎に、ディスクへの保存の準備をした一連のレイヤーを生成しますが、まだIn-Memoryレイヤーのままです。

  2. USD Stitchを使って、前フレームでクックされたIn-Memoryレイヤーと現在クックされたIn-Memoryレイヤーを結合します。

LOPネットワークが膨大なデータを生成する場合、(USD Stichはフレーム間で同じデータを複製しませんが)これだと即座に大量のメモリを消費してしまいます。

アニメーションUSDを書き出す際にHoudiniでメモリが足りないようであれば、このオプションを有効にすることで、Houdiniが常に単一フレーム分のデータのみをメモリに格納するように制限することができます。 その結果として、ディスクへの書き込み時間が長くなり、最終ファイルサイズはこのオプションを無効にした場合よりも大きくなってしまいます。 しかし、書き出し可能なデータ量は、コンピュータが利用可能なメモリ量に制限されません。

他にも、それぞれ単一タイムサンプルデータを含んだUSDファイルのシーケンスを書き出してから、USD Stitch Clips ROPを使用してUSD Value Clipを生成する方法があります。 この方法は、その巨大なデータセットが存在するシーングラフツリー内に独立したブランチが存在する場合にのみ機能し、このブランチのデータを別のUSDファイルに書き出すことができます。

USDを書き出す他の方法

  • Python(Pythonシェルでインタラクティブに、または、Python Script LOPでプロシージャルに)を使って、個々のファイルに書き出すことができます。

  • ノード上で右クリックして、 LOP Actions サブメニューを開いて、 Inspect flattened stage または Inspect active layer を選択することができます。これらのメニュー項目は、ステージ/レイヤーをusdaコードとして表示するビューアウィンドウを開きます。 このウィンドウからusdaコードをファイルに保存することができます。

Solaris

USD

ジオメトリ

  • SOPをUSDに取り込む方法

    HoudiniがSOPジオメトリをUSDに変換する方法、その工程を制御する方法の詳細。

  • Component Builder

    Component Builderツールは、マテリアル、バリアント、ペイロード、レイヤーをサポートし、SOPからUSDモデルを作成するためのネットワークスニペットを配置します。

レイアウト

  • Editノード

    ビューア内でインタラクティブにPrimsをトランスフォームさせます。物理衝突を使用して、プロップを現実的に配置することができます。

  • Layoutノード

    インスタンス化されたUSDアセットをシーンに取り込むツールが備わっています。個々にコンポーネントを配置したり、カスタマイズ可能なブラシを使って色々な方法でコンポーネントをペイント/スキャッターしたり、既存のインスタンスを編集することができます。

  • カスタムレイアウトブラシ

    Layout LOPの挙動をカスタマイズして利用可能なレイアウトブラシデジタルアセットの作成方法。

シェーディング

  • シェーダフレームワーク

    シェーダノードのUSDプリミティブへの変換を含む、Solarisシェーディングフレームについて説明しています。

  • KarmaでのMaterialXの使い方

    HoudiniにはMaterialXシェーダノードに呼応させたVOPノードが用意されています。これらのノードを使用してシェーダネットワークを構築したり、既存のMaterialXシェーダをインポートすることで、(HoudiniのUSDレンダラーの)KarmaでMaterialXシェーダノードを利用することができます。

  • /solaris/materialx_nodes

Karmaレンダリング

チュートリアル