Houdini 18.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レンダーノードの Separate File Per Frame パラメータは、フレーム毎に個々にファイルを書き出すか(例えば、lamp_0001.usdlamp_0002.usdなど)または全フレームのタイムサンプルデータを含んだファイルを書き出すかを制御します。

出力プロセッサ

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

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

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

  1. $HOUDINI_USER_PREFS_DIR/python2.7libs/husdoutputprocessorsという新しいディレクトリを作成します。

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

  2. $HOUDINI_USER_PREFS_DIR/python2.7libs/husdoutputprocessors内で、__init__.pyという名前のファイルを作成し、以下のPythonコードを貼り付けます:

    __path__ = __import__('pkgutil').extend_path(__path__, __name__)
    

    // NOTE: 私どもがPython3に移行した時、これはもはや不要になることでしょう。

    // その場合、pkgutilの代わりにネイティブのPythonネームスペースを使用してください。

  3. $HOUDINI_USER_PREFS_DIR/python2.7libs/husdoutputprocessors内で、出力プロセッサプラグインのPythonファイルを作成します。例:

    $HOUDINI_USER_PREFS_DIR/python2.7libs/husdoutputprocessors/outputreview.py
    
  4. Pythonプラグインファイルで、husdoutputprocessors.base.OutputProcessorBaseクラスをサブクラスにします。

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

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

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

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

    Note

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

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

    import hou
    from husdoutputprocessors.base import OutputProcessorBase
    
    
    class ReviewOutputProcessor(OutputProcessorBase):
        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を返します。

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のような命名規則を使用するのが良いでしょう(modulenamehusdoutputprocessors下のPythonモジュールの名前です)。

beginSave(self, config_node, t)

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

config_node

レンダーノードを表現したhou.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の場合、そのアセットは他の何かです(例えば、テクスチャやボリュームのファイル)。

endSave(self)

このプロセッサを使ったレンダーノードがファイルの書き出しを終了した時にコールされます。

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

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

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

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

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

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

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

USDレンダーノードの Separate File Per Frame パラメータは、フレーム毎にデータを含んだ個々のファイルを書き出すか、全フレームのタイムサンプルデータを含んだファイルを書き出すかを制御します。

USDレンダーノードの Separate File Per Frame を無効にしてフレーム範囲を書き出す時:

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

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

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

アニメーションUSDを書き出す際にHoudiniでメモリが足りないようであれば、代わりに、フレーム毎に別々のレイヤーファイルを保存して、USD StitchまたはUSD Stitch Clipsを使用することで、一括でそれらのファイルからタイムサンプルを含んだレイヤーまたはValue Clipセットに結合することができます。

USDを書き出す他の方法

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

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

Solaris

USD

チュートリアル

Karma