USDの基礎


この記事では、USDの概念と、それに関連するHoudiniの機能について紹介します。

オーバービュー

USDは、レイヤー構造で3Dシーンを記述するソフトウェアおよびファイル形式のシステムです。
たとえば、キッチンシーン(kitchen.usd)を「記述」するマスターUSDファイルは、プロップ(chair.usd、table.usd)、ライト、キャラクタなどを含むレイヤーファイルを参照し、それらを単一のステージとして構成できます。

レイヤーパラダイムの主となる特徴は、非破壊編集にあります。既存のシーンはそのままに、その編集を行う新しいレイヤーを作成することができます。これらの編集は、作成された新しいレイヤーを利用/参照していない限り、同じシーンを使用している他の人には影響しません。また、レイヤーのひとつ(たとえば、アセットの新しいバージョンや更新されたライト)を置き換え、その上にある既存の変更をすべて自動的に再適用することもできます。
これにより、複数の部門が互いに干渉することなく、共同作業、データの共有、アセットの更新を行うことができます。

HoudiniのUSDサポートツールは、Solarisと総称されます。 Solarisでは、ビューにUSDがサポートされ、新しいネットワークタイプであるLOPs(Light Operators)がサポートされます。 LOPネットワークはSOPに少し似ており、SOPでは、各ノードは入力ジオメトリを受け入れ、修正し、新しいジオメトリを出力します。 それに対しLOPでは、各ノードは入力USDシーンを受け入れ、変更し、新しいシーンを出力します。

USDは包括的なフレームワークであるため、単純ではありませんが、 LOPsは、基になるUSD構造について知る必要がないように設計されています。ただし、可能な限りLOPパラメータはUSDの用語を使用しており、USDに組み込まれた機能に対する簡易的なラッパーである場合もあります。 USDの概念と機能を基本的に理解することで、LOPsは更に理解しやすくなります。

 

クイックサンプル

通常、.usd(または.usdc)ファイルは効率を高めるためにバイナリ形式でエンコードされていますが、USDシーン記述形式には、人間が読めるプレーンテキストに相当するもの(.usda)があります。 この章で説明するUSDの概念を紹介する非常に簡単な.usdaの例を次に示します。

box.usda

#usda 1.0
def Cube “box” {
    double size = 4.0
}

 

この例では、defは新しいプリミティブを定義するキーワードです。(USDにはdefに似た、over演算子があります。これは、新しいプリミティブが既存のプリミティブをオーバーライドする際の定義です。)
Cubeはプリミティブのタイプです。 「Cubeであること」の意味とCubeのプロパティは、スキーマによって定義されます。 boxはプリミティブの名前です。(このプリミティブはシーンツリーに/boxとして表示されます。)
Cubeプリミティブタイプは、組み込みのUSD Geometryスキーマによって定義されます。ボリューム、シェーディング、ライティング、ボーンアニメーション、およびレンダリング用の追加の組み込みスキーマがあります。カスタムスキーマを作成して独自のプリミティブタイプを定義することにより、USDを拡張できます。

中括弧{} 内のコードは、新しいプリミティブの子プリミティブとプロパティを定義します。
(Cubeには多くのプロパティがありますが、指定しないプロパティにはタイプスキーマのデフォルトが設定されます。)

USDの専門用語では、これは「/boxのサイズについて意見を述べる」と言われるかもしれません。
レイヤーを構成するときに、レイヤーにプロパティの値に関する「意見」が含まれている場合、複数のレイヤーが同じプロパティに対して異なる意見(値)を持っている場合、意見が強い方のレイヤーの値でオーバーライドされます。

次に、2番目の.usdaファイルについて考えます。

two_boxes.usda

#usda 1.0
def “box1” ( references = @box.usda@ ) {

}
def “box2” ( references = @box.usda@ ) {
    float size = 2.0
}

 

このファイルでは、上記のbox.usdaファイルの内容を2つのプリム /box1 及び /box2 として2回インポートします。
/box1は、参照元のレイヤーからそのsize
アトリビュートを継承しています。 /box2は、サイズを新しい値で上書きしています。

  • 低レベルの編集を行うためのノードは存在しますが、Houdiniでは、一般的に直接プリミティブのアトリビュートの値を操作しません。代わりに、LOPノードはより高いレベルの操作を指定でき、(例:「このジオメトリに取り込む」、「このオブジェクトにこのライトを向ける」、「物理学に基づいて、テーブルに小道具を置く」など)LOPは対応するUSDを自動的に作成します。
     
  • インラインのUSD LOPを使用して、LOPネットワークによって構築されたステージにプレーンテキストUSDコードを挿入することは可能ですが、 これはデバッグには役立つ場合がありますが、通常の作業方法ではありません。

  • 拡張子が.usdのファイルは、バイナリ形式またはプレーンテキスト形式のいずれかです。 これにより、アセットの追跡やバージョン管理をに影響を与えることなく、ある表現から別の表現にファイルを簡単に切り替えることができます。 これに対し、拡張子が.usdaのファイルは常にプレーンテキスト形式で、.usdcは常にバイナリである必要があります。

 

コンセプト

プリミティブ(Primitives / Prims)

プリミティブは、USDの基本的な「単位」です。 「Primitive」は、USDについて話すときは「prim」と短縮されることがよくあります。 HTMLの「element」と同様に、プリミティブには名前、0個以上の名前付きプロパティ、および0個以上の子があります。

たとえば、ポリゴンメッシュはプリミティブ、ライトはプリミティブ、マテリアルはプリミティブです。
「xform」プリミティブは、その子プリミティブに適用されるTransformを保存します。

プリミティブは、ステージを定義するオブジェクトのツリー内の「ノード」です。

プロパティ

「プロパティ」は、プリミティブにアタッチできる2つのタイプの名前付きデータの一般名です。

アトリビュート

アトリビュートは、プリミティブを記述する型付きの値(整数、色、変換行列、配列など)です。
(たとえば、float size = 1.0はCubeプリミティブの均一なサイズを定義します。
これは、プロパティの最も一般的な形式です。

リレーションシップ

リレーションシップは、1つのプリミティブと別のプリミティブとの間にリンクを確立します。(たとえば、メッシュプリミティブをシェーディングするときに使用するマテリアルを指定したり、コレクション内のプリミティブを指定したりします。)

 USDでは、アトリビュートはプリミティブに付加されたデータです。 Houdiniがアトリビュート(ジオメトリにアタッチされたデータ)と呼ぶものは、USDではprimvarsと呼ばれます。

メタデータ

プロパティ自体にメタデータという名前付きの値をアタッチすることで、動作方法を変更することができます。 たとえば、メッシュのポイントカラーprimvarを指定する場合、レンダラがポイントのカラー間でブレンドする方法を指定する補間メタデータを追加できます。
メタデータは、特定のDCCに固有の「追加」データを添付したり、デバッグやユーザーインターフェイスの構築に役立つ場合もあります。 たとえば、さまざまなアトリビュートのドキュメントはメタデータに保存されます。

 

レイヤー

.usdファイルにはレイヤーがひとつだけ存在します。(一方、.usdzファイルは、単一のファイルに複数のレイヤーを含むことができます。) レイヤーは、プロップ、キャラクタ、リグの一部、ライティング設定などのシーンの「部品」を意味しています。 また、ベースラインを作成するために参照できる「デフォルト」を定義しておくこともできます。たとえば、シーケンス内の各ショットを表すファイルで参照するショットシーケンスの設定を含むレイヤーなどがこれに該当します。
詳細については、USDの整理を参照してください。

Houdiniでは、さまざまなノードが新しいインメモリレイヤーを作成して既存のデータを上書きします。 Layer Break LOPを使用して「手動で」新しいレイヤーを作成することもできます。 典型的なLOPネットワークには、多くのレイヤーが含まれます。一部はディスクからインポートされ、一部はノードによってメモリー内に作成され、最後に一緒に合成されます。 (ネットワークエディターのオプションの視覚化により、ネットワーク内のどのノードが異なるレイヤーで機能するかがわかります。)

 

コンポジションアーク

ある層から別の層へのリファレンスです。 たとえば、シーンレイヤーは、プロップ、ライトなどを含むレイヤーを取り込むことができます。 これらのレイヤーは、独自のサブレイヤーを参照する場合があり、これらのサブレイヤーは更にサブレイヤーを取り込む場合があります。

レイヤーは一緒に合成され、各レイヤーのプリミティブがマージされます。 上位層のプロパティは値をオーバーライドします。

たとえば、シーンファイルはライティングレイヤーを参照することを考えた時、ラィテング部門は「ベースデフォルト」、「完成したライティング」、および「進行中のライティング」を表す3つのサブレイヤーからそのレイヤー自体を構成している場合があります。しかし、 他の部門は、ライティングレイヤがどのように構成されているかを知る必要はなく、トップレベルの「ライティング」レイヤを参照するだけで正しい参照が可能になります。

Reference LOPを使用して、LOPネットワークのノードを使用して、メモリ内に構築しているレイヤーに参照を追加できます。Sublayer LOPを使用して、既存のサブレイヤー(.usdファイル)を現在のステージのレイヤースタックにロードできます。

 

ステージ

USDファイルをロードし、システムがすべてのレイヤーをまとめてプリミティブの最終シーングラフを計算する場合、その結果はステージと呼ばれます。
ステージは単に、結果についている名前であることに注意してください。 「ステージファイル」と「レイヤーファイル」に違いはありません.。 .usdファイルを「トップレベル」ファイルとしてロードすると、ステージが作成されます。 別の状況では、同じファイルを異なるステージのレイヤーとして参照する場合があります。

Houdiniでは、ネットワークの最上部にあるLOPノードがステージを作成し、後続の各LOPがそのステージのコンテンツをプロシージャルに変更して、新しいステージを作成します。 そのため、LOPノードでは、hou.LopNode.stage()関数を使用して、そのノードからステージオブジェクトの出力を取得できます。 LOPノードを右クリックし、LOP Actions  -> Inspect Flattened Stageを選択すると、ノードによるステージ出力をusda構文として表示できます。

 

AttributeとPrimvar

USDでは、アトリビュートは多くの場合、プリミティブの「設定」を含むスカラー値となります。たとえば、Sphereプリミティブでは、Radiusアトリビュートが球体のサイズを制御します。ある意味、アトリビュートはHoudiniのノードパラメータ、またはMayaのアトリビュートに似ているとも考えられます。

USDでは、ポイントごとの変数などのジオメトリ設定もプリミティブのアトリビュートとして保存されます。これらは配列として保存され、コンポーネントごとに1つの要素があります。たとえば、メッシュプリミティブのポイントアトリビュートは、座標の配列にポイント位置を格納します。これはHoudiniジオメトリアトリビュートと同一です。

USDは、primvarと呼ばれる特定のタイプのアトリビュートも認識します。
(primvarという名前はRendermanに由来し、「primitive variable(プリミティブ変数)」の略です。)
ベーシックツリーレベルでは、primvarsはprimvars(スキーマ 名前空間 プレフィックス)を持つ単なるアトリビュートです。それらを特別なものにしているのは、レンダリング中にHydraがそれらをどのように処理するか、という段階です。主な目的は、マテリアルパラメータをオーバーライドすることですが、マテリアル以外のジオメトリレンダリングに影響する可能性のあるオブジェクトごとのプロパティを表すためにも使用されます。たとえば、Karmaでは、primvarsを使用して、オブジェクトごとのモーションブラーフレームの数を指定できます。

 

Primvar補間

Primvarは、プレーンなUSDアトリビュートよりも、従来のHoudiniレンダリングでマテリアルパラメーターをオーバーライドできるHoudiniジオメトリアトリビュートに似ています。 Houdiniのジオメトリアトリビュートと同様に、曲線/サーフェスの特定の部分に利用可能なprimvarデータがない場合、システムは最も近い利用可能なprimvarの間を補間します。

システムがprimvarを補間する方法は、HoudiniがVertexアトリビュート、ポイントアトリビュート、プリミティブアトリビュート、グローバル(Detail)アトリビュートをどのように持つかなど、primvarの「レベル」を本質的に定義します。 USDでは、定数補間はHoudiniのDetailアトリビュートと同等です。均一補間は、Houdiniプリミティブアトリビュートと同等です。 FaceVarying補間は、HoudiniのVertexアトリビュートと同等です。
そしてprimvarの配列の値の数は、選択された補間方法に対応するコンポーネントの数に対応する必要があります。たとえば、立方体の均一(面ごと)primvarには6個の値が必要ですし、立方体の頂点(点ごと)primvarには8個の値が必要です。 primvar値を適用して、指定されたマテリアルパラメーターをオーバーライドするのはレンダラ側の処理となります。

 

Primvar継承

primvarsをプレーンなアトリビュートから分離するもう1つの方法は、「Constant」primvarsをシーングラフツリーで継承することです。

たとえば、プリミティブ /Geometry/props がprimvars:displayColorの定数値を持っている場合、/Geometry/props のすべての子孫は、オーバーライドされない限り同じ色を使用します。

この継承が、オブジェクトごとのレンダリング設定にprimvarsが使用される理由です。高レベルのプリミティブにダイシングの品質を下げるなどの設定し、シーンの大部分に影響を与えることができます。

使用可能な値間の補間は、primvarsの主な機能です。これが、メッシュプリミティブでは、ポイントアトリビュートはプレーンアトリビュートですが、primvars:displayColorはprimvarです。ポイントの位置は「補間」できません。その配列の長さは、メッシュ内のポイントの数を定義します。ただし、表示色はプリミティブ全体で一定であるか、各ポリゴン、ポイント、または頂点の値を持つことができます。

 

Primvarとインスタンス化

ポイントインスタンサーに「頂点」(ポイントごと)配列primvarがある場合、インスタンスごとに配列内の対応する値を検索し、それをインスタンスの「定数」primvarとして扱います。これは、ポイントインスタンスごとのマテリアルオーバーライドがUSDで機能する方法です。

同様に、インスタンス化可能なプリミティブに「定数」primvarを設定できます。そのprimvarは継承され、インスタンス内のプリミティブのマテリアルパラメータに影響します(そうでなければ編集できません)。これは、インスタンス化可能なプリミティブの外部からのデータによって、インスタンス下のプリミティブの外観に影響を与える唯一の方法です。

 

コンポジション / 合成

すべてのUSDファイルには、完全な「シーン」が含まれています。 USDファイルは、他のUSDファイルのコンテンツをレイヤーとしてインポートできます。

USDライブラリには、最上位ファイルによって作成されたフルシーン(ステージ)に複数のレイヤーを構成/オーバーレイするためのソフトウェアが含まれています。 合成には、レイヤー間の以下のようなの違いをマージすることが含まれます。

  • 新しいプリミティブ
  • プリミティブの順番
  • プリミティブがアクティブか非アクティブかの状態
  • プリミティブの変異(バリアント
  • 新しいプロパティ(アトリビュートとリレーションシップ)
  • アトリビュートの値(上位レイヤーはアトリビュート値を「ブロック」(設定解除)することも可能なので、割り当てられていないようにも見えます。)
  • メタデータの値

Houdiniは、USDの編集時に作成されるさまざまなディスク上およびメモリ内のレイヤーを自動的に合成します。 ツールを使用して、各レイヤーの内容とレイヤーの合成方法を把握することもできます。

サブレイヤー / リファレンス

USDには、別のUSDファイルのコンテンツを「インポート」するための2つの異なるアプローチがあります。サブレイヤーは、インポートされたファイルのツリーを現在のツリーにオーバーレイします。

サブレイヤー

インポートされたファイルのコンテンツを既存のコンテンツにオーバーレイします。同じパスのプリミティブに関する各ツリーの「意見」、および同じ名前の(それらのプリミティブ上の)プロパティ/メタデータは、意見の強さに基づいてマージされます(以下を参照)。

これは、完成シーンに利用されるファイルを結合するときに役立ちます。たとえば、レイアウト、プロップ、キャラクタ、エフェクト、ライトを表す個別のレイヤーを構成します。

サブレイヤーの固有の機能は、「すべてが同じ場所に留まる」ことです。プリミティブには、ソースファイルと同じパスが新しいファイルにあります。

これらの各部門は別々のサブレイヤーで作業しているため、ファイルの共有や編集の競合について心配する必要はありません。しかし、これらはすべて同じシーングラフレイヤーで機能しているため、各部門は他の部門が作成したコンテンツに変更を適用することは可能です。

 

Sublayer LOPは、新しいサブレイヤーをシーンにロードします。一般に、LOPネットワークは常に空のルートレイヤーを最強のサブレイヤーとみなしており、これを編集しています。一部のLOPノードは、新しい強力なサブレイヤーを開始し、その後、すべての後続のLOPノードによって変更されます。これらのネットワーク出力は、このサブレイヤースタックの合成結果になります。

Top-level file that specifies sublayers

#usda 1.0
(
    subLayers = [
        @shotLighting.usd@,
        @shotFX.usd@,
        @shotAnimation.usd@,
        @shotSetDressing.usd@,
        @sequence.usd@
    ]
)

 

 

リファレンス(参照)

リファレンスは、参照ファイルのツリーを取得し、現在のツリーのブランチに「グラフト」します。
たとえば、以下のシーンを考えます。

box.usda

#usda 1.0
Lights
    light1
    light2
Models
    tableside_lamp

        

lamp.usd

lamp
    base
    bulb
    shade
    socket
    switch

 

この時、/Models/tableside_lamp がlamp.usdを参照すると、ツリーは次のようになります。

Lights
    light1
    light2
Models
    tableside_lamp
        base
        bulb
        shade
        socket
        switch

 

  • リファレンスを含むプリミティブ(/Models/tableside_lamp)と参照されるプリミティブ(lamp.usdの/lamp)は一緒に合成されます(重複するプロパティ値は意見の強さによって決定されます)が、プリミティブは元の参照プリミティブの名前を保持します。
  • コンテンツで参照する場合、参照ファイルでプリミティブ(上記の例では/lamp)を指定する必要があり、そのプリミティブをルート(/)にすることはできません。 そのため、他のレイヤーで参照されることを意図したファイルを作成するときは、ルートプリミティブの下にコンテンツを整理する必要があります。
    (ファイルの「デフォルトプリミティブ」を指定することは可能です。ファイルを参照し、ファイル内の特定のプリミティブを指定しない場合、ファイルの「デフォルトプリミティブ」を取得します。)

リファレンスは、小さな個々のアセットを大きなシーンに移植するのに役立ちます。
特に、リファレンスは、異なる場所で同じレイヤーファイルを複数回読み込む唯一の方法です。
(サブレイヤーはツリー全体で機能するため、同じファイルを複数回サブレイヤー化しても効果はありません。)

Reference LOPとStage Manager LOPはリファレンスを作成します。 Graft LOPも似ていますが、ファイルから参照する代わりに、LOPネットワークの他の場所からシーングラフツリーにブランチを挿入します。

単一のシーングラフの特定の場所でプリミティブの最終的な意見を生成するための、サブレイヤーとリファレンスの複数のレベルがどのように連携するかを追跡作業は複雑になる可能性があります。
[Scene Graph Details]ペインの[Layer Stack]タブと[Composition]タブを使用して、どのレイヤーがプリミティブに寄与するか、およびそれらの異なるレイヤーがどのように合成されたかを調べることができます。

 

ペイロード

ペイロードは基本的にリファレンスですが、特にリクエストされるまでペイロードをロードしないようにすることも可能です。 これにより、シーンのどの部分をメモリにロードするかを制御でき、関心のあるシーンの部分に焦点を当てることにより、メモリの使用と処理時間を抑えることが可能です。

Houdiniでは、ファイルを参照するノードのパラメータで、参照ファイルがリファレンスであるかペイロードであるかを指定します。
デフォルトでは、Houdiniはすべてのペイロードをロードします(したがって、リファレンスとまったく同じように動作します)。 ただし、シーングラフツリーのConfigure Stage LOPおよびLoad Masks controls を使用すると、ペイロードのデフォルトのロードを無効にしてから、ロードする特定のペイロードを選択できます。

 

アクティベーションと可視性

USDは非破壊編集用に設計されているため、USDではプリミティブを削除できません。 ただし、プリミティブを新しい値でオーバーライドしたり、プリミティブを無効にして効果をなくしたりすることは可能です。

シーン内のオブジェクトの可視性を編集することもできます。 デフォルトでは、USDプリミティブが表示されます。 可視性オプションには、「inherit」と「invisible」の2つの設定しかありません。 そのため、プリミティブを「invisible」とマークすると、常にすべての子孫も非表示となります。

Houdiniでは、Scene Graph Tree ペインでプリミティブをアクティブと非アクティブ、および表示/非表示をインタラクティブに切り替えて、プリミティブの効果を確認することができます。 Houdiniはこれらの編集をメモリ内の未保存のレイヤーで実行するため、最終的に生成されるUSDに影響を与えません。

 

意見の強さ

アトリビュートは「strongest wins」ルールに従って解決されるため、アトリビュートの値は一番強い意見のPrimSpec(レイヤー内で未合成のプリミティブ)から取得されます。 たとえば、デフォルト値のある「弱いレイヤー」は、アニメーションのある、より強いレイヤーによってマスクされます。 これは、たとえば、レイアウト部門がシーンにプロップを配置し、その後アニメーション部門がそのプロップをアニメーション化するレイヤーを追加することを指します。

意見の強さを決定する最も一般的な方法は、レイヤースタックの順序です。

たとえば、一例として、最も弱いレイヤーとしてレイアウトレイヤーを作成します。ここではアセットが結合されて配置されます。 次に、アニメーション部門のシーンにキャラクターを追加するレイヤーを作成します。(既存のプリミティブの一部に強い意見を適用することにより、必要に応じてレイアウトを移動または調整することができます。) 次に、FXレイヤーを作成します。シーングラフに追加された新しいジオメトリや、レイアウト部門またはアニメーション部門によって追加された既存のプリミティブにRBDシミュレーションを適用します。

意見の順序付けは、LIVRPSニーモニック「liver peas」に従います。 これらは、合成における、強弱に基づいて、1つのレイヤーが別のレイヤーをオーバーライドする方法です。

Local: ローカル

プロパティに対して独自の意見を持つレイヤーは、それが参照するサブレイヤーの同じプロパティに対する意見をオーバーライドします。

Inheritance: 継承

「継承」を使用して、プリミティブのデフォルト値を再定義できますが、これはレイヤーのコンテキストでのみです。 継承はローカル参照に似ていますが、複数レベルのリファレンスを介しても「ライブ」のままです。 マテリアルは、「継承」および「specializes: 特化」の主な使用例です。

Pixar’s USD の継承についての詳細はこちら。(英語)

Variants: 変異

バリアントについてはこの後詳しく解説します。 現在のバリアントは、バリアントセットを含むプリムのアトリビュートをオーバーライドします。

References: 参照

小さいユニットをシーンに「インポート」します。 たとえば、ドレスセットファイルは本棚のプロップファイルを参照し、本棚ファイルはいくつかの異なる本のプロップファイルを参照する場合があります。
 
Pixar’s USD の参照についての詳細はこちら。(英語)

Payloads: ペイロード

基本機能は参照と同様ですが、ペイロードの場合、オプションでシーンの表示/レンダリングを高速化するためにアンロードし、後でリロードすることができます。 アセットの重い部分(高解像度のポリゴンメッシュスキンなど)はペイロードとして参照することで、アンロードすることができます。
 
ペイロードがロードされると、「アンロードされた」バージョンがオーバーライドされます。
 
Pixar’s USD の参照についての詳細はこちら。(英語)

Specializes: 特化 

継承(上記参照)と同様に、元のソースを変更せずに、レイヤー内のプリミティブのデフォルト値を再定義します。 「特化」は、これらの変更をブロードキャストする方法ですが、「継承」の意見を無視することはありません。 マテリアルは、「継承」および「特化」の主な使用例です。
 
Pixar’s USD の参照についての詳細はこちら。(英語)

尚、Houdiniでは、常に最強の意見で構築を行っているため、通常、オーバーライドの強さについて考える必要はありません。
Pixar’s USD のLIVRPSについての詳細はこちら。(英語)

 

Houdiniでの低レベルUSDアクセス

  • usda形式のコードを記述して評価し、Inline USDノードを使用してメモリ内のシーングラフツリーに結果のプリミティブを直接挿入できます。

  • Python Usd APIを用いて、Python Script LOP内にコードを記述してインメモリステージを直接操作できます。

 

拡張性

ファイルフォーマットプラグイン

USDのオープンソースライブラリは、さまざまなファイル形式からデータをロードするプラグインを提供します。

Houdiniでは、通常、LOPノードを使用して、USDのファイルインポートコードを使用せずに、ジオメトリなどのデータを別のネットワークまたはディスクから直接USDにインポートします。 HoudiniにはHoudiniファイル形式用のUSDプラグインも含まれているため、Houdiniの外部のパイプラインでも使用することが可能です。(これらのプラグインはバッチライセンスを消費します。)

アセットレゾルバ

明示的なファイルパスに加えて、USDでは、不透明なアセットID(usda形式では@ my_asset_name@のようになります)を使用してファイル参照をエンコードできます。 アセットレゾルバと呼ばれるプラグインは、アセットIDをロード可能なオブジェクトに変換する役割を果たします。

たとえば、スタジオがGitサーバにアセットを保存する場合、そのサーバに関連して意味のあるパスおよびリビジョン情報を含むアセットIDとしてファイル参照を保存する場合があります。(@/models/tintoy#bf452ac@など。) 

カスタムスキーマ

スキーマはカスタムタイプ、アトリビュート、APIをUSDに追加し、その動作を定義します。
詳細は下記を参照してください。

レンダーデリゲート

ソフトウェアはHydraと呼ばれるAPIを使用して、レンダーデリゲートにUSDをレンダリングするよう指示します。
レンダラのレンダーデリゲートが存在する限り、どのソフトウェアでも、そのレンダーデリゲートが存在するレンダラを介してUSDをレンダリングできます。
詳細は下記を参照してください。

シーンデリゲート

プログラムがレンダーデリゲートを介してレンダリングを指示するように、レンダラがシーンからの情報を必要とする場合、APIを使用してシーンデリゲートから要求することができます。 
これにより、レンダリング時にシーンを変更する間接参照のレベルを提供できます。

プリミティブアダプター

USDプリミティブの各タイプは、プリミティブアダプタータイプによってHydra互換のレンダリング可能な表現に変換されます。

 

Houdiniでカスタムファイルフォーマットプラグインとアセットレゾルバを使用するには、次の2つの方法があります。

  • Houdiniに同梱されているUSDヘッダとライブラリを使用してプラグインを構築します。 (これらのヘッダとライブラリはHDKの一部として含まれています。)

  • HoudiniのバージョンのUSDライブラリを独自のバージョンに置き換えます。 これを行うには、SideFX GitHubからHoudiniUsdBridgeリポジトリをダウンロードする必要があります。 このリポジトリには、USDを呼び出すすべてのHoudiniソースコードが含まれています。 独自のUSDライブラリを使用してそのコードを再構築し、その結果を使用して、Houdiniインストールの同等のライブラリを直接をコピーするか、LD_LIBRARY_PATHを設定することで置き換えます。

Solaris出力プロセッサは、$HIPに関連するパスを取得して、ルートUSDファイルに関連するようにしたり、ファイル拡張子を調整したりと、ファイルの保存方法をカスタマイズできます。

 

USDのジオメトリ

USDでは、ジオメトリを表すプリミティブをgprimと呼びます。これらは、レンダリングすると、たとえばTransformプリミティブとは対照的に、実際に画像に何かを描画するプリミティブです。 これらのプリミティブタイプのスキーマ(UsdGeomGprim)には、バウンディングボックスの検索などの便利なメソッドが含まれています。

USDには、数学的に定義された形状(capsule, cone, cube, cylinder)を表すプリミティブのセットと、ポリゴンメッシュやサブディビジョンサーフェスなどのジオメトリを保持するような、より複雑なプリミティブが含まれます。

シーングラフツリーの他のgprimの下にgprimを置かないように注意してください。 アクティベーション、可視性など、USDの多くの主要な機能は階層的に適用されます。これらの操作を個々のgprimに適用できないと、USDの構造をフルに活用することができません。

Kinds(種類)

Kindは、USDの理解が難しい概念の1つです。 下にジオメトリがあるすべてのプリムには「Kind」が必要です。

「モデルのKind」は、モデルと呼ばれる「抽象的な」Kindのサブクラスです。 よって、モデルをKindとして割り当てないでください。 モデルには下記の3種類があります。

アセンブリ(グループのサブクラス)
重要なグループモデルです。多くの場合、公開されたアセットまたは公開されたアセットへの参照になります。

グループ
コンポーネント、アセンブリ、または他のグループなどの、他のモデルのグループです。 モデル階層の「ブランチ」アイテムになります。

コンポーネント
モデル階層の「リーフ」アイテムです。この種類のプリミティブには他のモデル(グループまたはアセンブリ、または他のコンポーネント)を含めることはできません。

Kindは、シーン内のジオメトリをモデル階層に整理することをサポートします。 これは、シーン内のモデルの「目次」です。 この階層を適切に維持することで、ソフトウェアパッケージは選択などを行う際により優れたUIを提供でき、シーン内のモデルのより効率的な走査が可能になります。 (たとえば、ソフトウェアがシーン内のすべてのモデルをユーザーに表示する場合、Kindのあるルートでツリーの検索を開始するだけでよく、コンポーネントのKindにヒットしたときにツリーの下降を停止できます。)

シーングラフツリーのモデル階層は、次のようになります。

/Models ← グループ
    /Characters ← グループ
        /Lady ← アセンブリ
            /Skin ← コンポーネント
                /mesh
            /Purse ← コンポーネント
                /mesh
        /Dog ← アセンブリ
            /Skin ← コンポーネント
                /mesh
            /Collar ← コンポーネント
                /mesh
    /Props ← グループ
        …

モデル階層を維持するには、シーンが次の条件を満たす必要があります。

  • 配下のジオメトリを処理するすべてのプリミティブには、ルートプリムミティブ(たとえば、/Models)を含むKindから始まる必要があります。
  • グループ/アセンブリの種類のみ、他のモデルのKindを含める必要があります。 コンポーネントの種類にグループ、アセンブリ、またはモデルを含めることはできません。 (サブコンポーネントの種類を含めることができます。)

Houdiniでは、プリミティブを作成/編集するノードには、プリミティブの種類を設定できるパラメータがあります。 モデル階層ルールにより、モデルをKindとして使用することはできません。 現在、Houdiniはユーザーにモデル階層の維持を支援したり強制したりすることは何もしていません。

 

Primvars

primvarという名前はRendermanに由来し、「プリミティブ変数」の略です。 各「変数」は、ジオメトリの各ポイント、面、または頂点ごとの値を格納します。
primvarsのUSDコンセプトは、Houdiniのジオメトリアトリビュートと同等です。 (上記のように、USDはアトリビュートという言葉を使用して他のものを指します。)Houdiniでアトリビュートが行うように、Primvarsは同じ名前のシェーダーパラメータをオーバーライドすることもできます。

以下のように、HoudiniとUSDではこれらの補間の名前が異なります。

Houdini USD
Point Attribute 頂点補間を備えたPrimvar
Vertex Attribute 面の変化に対する補間を備えたPrimvar
Primitive Attribute 均一補間を備えたPrimvar
Detail Attribute 定数補間を備えたPrimvar

 

インスタンス

USDには、さまざまな形式の「インスタンス化」(効率的なコピー)があります。
USDには、ツリー内の1つのプリミティブが別のプリミティブを参照するという概念が本質的にあります。 これは、ブランチ内のすべてのプリミティブを実際にコピーするよりも効率的ですが、サブプリミティブをオーバーライドする機能を保持するために、USDは参照の下に各サブプリミティブの参照も作成する必要があります。
シーンのコピー/バリエーションを手動で多数作成するより効率的な方法を提供するために、USDには2つのインスタンス化方法が用意されています。

インスタンサブルプリム(「ネイティブ」インスタンス化とも呼ばれる)
こちらは、インスタンス化可能なプリミティブのことになります。プリミティブには、プリミティブがインスタンス化可能であること(つまり、「インスタンス化の対象と見なすことができる」こと)を指定するメタデータが少し存在します。

instanceable = trueのプリミティブを読み込むたびに、USDはプリミティブ(およびその子孫)の仮想「マスター」コピーを作成し、インスタンス化可能なプリミティブをこのマスタープリミティブへの参照にします。 次に、USDはシーングラフで同一のインスタンス化可能なプリミティブに遭遇するたびに、同じマスタープリミティブへのポインタを自動的に作成し、「duplicates」が実際のスペースをほとんど消費しないようにします。

欠点は、インスタンス化可能なプリミティブの下では、プリミティブを変更できないことです。 ただし、インスタンス化可能なプリム自体のアトリビュートを変更できます。 これにより、たとえば、各インスタンスに一意のTransfromを与えたり、シェーディングに使用するprimvarsを設定したりできます。

Pixar’s USD のインスタンスについての詳細はこちら。(英語)

 

ポイントインスタンサー
ポイントインスタンサープリミティブでは、ジオメトリの各ポイントは、インスタンサーと「プロトタイプ」の関係を持つプリミティブの1つのジオメトリのインスタンスによって、ビューまたはレンダリング時に置き換えられます。 ポイントインスタンサープリミティブは、ポイントへのマッピングを非常に効率的にプリミティブの配列に格納します。

 Houdiniのインスタンス作成ノードは、Houdini独自のポイントインスタンス作成と同様に、USDの基本ポイントインスタンサーが提供する機能を超える追加機能をサポートします。 これらの「追加」機能はノードで計算され、その後USDに「ベイク」されます。

Pixar’s USD のポイントインスタンサーについての詳細はこちら。(英語)

インスタンサブルプリムは、ポイントインスタンサーよりも簡単に使用できます。 ただし、各「エイリアス」はプリミティブのコピーと比較すると、非常に少量のメモリ消費ですが、非常に多くのインスタンスが追加されるとメモリ消費が大きくなる可能性があります。 これに対し、ポイントのインスタンス化は、一定のメモリ使用量で数十億のインスタンスを処理するように設計されています。
どちらのタイプのインスタンスも、各プリミティブのトップレベルのTransformをサポートし、primvars(各ネイティブインスタンス上、またはポイントインスタンサープリミティブ上)がインスタンスごとにマテリアルパラメータをオーバーライドできるようにします。

ジオメトリプリミティブを直接インスタンス化しないでください。 代わりに、実際のジオメトリ(その親のTransformなど)の上のプリムをインスタンス化するようにします。

Houdiniは、インスタンサーでのインスタンス化と、インスタンス化ノードを異なるインスタンス化方法に設定するさまざまなタブメニューツールの両方のインスタンス化をサポートしているため、インスタンス化の方法は、主に必要なインスタンス数に基づいて選択します。 Houdiniは、ネストされたポイントのインスタンス化(インスタンサーを含むプロトタイプをインスタンス化する1つ以上のインスタンス化されたレベルのインスタンス化)、およびインスタンスを昇格して「実際の」モデルにすることもサポートします。

 

バリアント

USDでは、プリミティブの複数の名前付きバリアントをプリミティブに保存できます。 各バリアントは、異なるアトリビュート、リレーションシップ、および子を持つことができます。 異なるレイヤーの異なるバリアント間でプリミティブを切り替えることができます。 各プリミティブは、複数のバリアントグループを名前付きバリアントセットに格納できます。

以下は、バリアントの一般的な使用例です。

  • さまざまなジオメトリのファミリ(たとえば、さまざまな種類のツリーを切り替えることができるプリミティブです。

  • Detailレベル(バリアントと同じジオメトリの低解像度バージョンを段階的に保存し、カメラまでの距離に基づいて切り替えます。)

    Houdiniには、このワークフローを自動化するためのCreate LODおよびAuto Select LODノードが含まれています。

  • マテリアルの割り当て(プリミティブの外観を簡単に切り替えることができるように、異なるマテリアルが割り当てられたバリアントを保存します。)

Pixar’s USD のバリアントについての詳細はこちら。(英語)

 

アニメーション

USDでのアニメーションは、Houdiniでのアニメーションが時変ノードパラメータを介して行う方法と同様に、時変アトリビュート値を使用します。

各アトリビュートは、単一の「デフォルト」値を持つほか、「タイムサンプル」のコレクション、つまり時間でインデックス付けされた値のリストを持つことができます。 アトリビュートのメタデータは、サンプル間の補間方法を指定します。

「デフォルト」時にUSDに値を要求すると、デフォルト値が設定されている場合はデフォルト値が返され、そうでない場合は空の値が返されます。 すべてのタイムサンプル値は無視されます。 それ以外のときに値を要求し、デフォルト値またはタイムサンプル値が設定されている場合、値が返されます。 この値は、デフォルト(最初のタイムサンプルの前の値を要求する場合)、最も近いタイムサンプル値、または周囲の2つのタイムサンプルの線形補間になります。

LOPノードでHoudiniパラメーターをアニメーション化できます。また、USDをディスクに書き出すと、アニメーション化された値がタイムサンプルとして書き込まれます。

 

スキーマ

スキーマは、新しいプリミティブタイプを定義したり、新しいアトリビュートの意味/動作を定義したりできるカスタム拡張機能です。

「ツリー」レベルでは、USDは非常に一般的で「自由形式」となります。 アトリビュートを任意の型付き値に直接設定できます。 スキーマでは、制約と不変条件を強制する方法を提供します。 より高レベルのAPIを使用することにより、アトリビュートが「正しく」構築されるようにします(値を特定の範囲内に保つ、不可能な構成を許可しないなど)。

USDは、独自のプリミティブタイプを定義するスキーマを型付きスキーマと呼びます。
USDは、異なるタイプのプリミティブの上に適用できるAPIを定義するだけのスキーマをAPIスキーマと呼びます。 このタイプのスキーマには通常、APIで終わる名前が付いています。
APIスキーマは、単独適用と多重適用にさらに分けられます。

  • 単独適用のスキーマの例はUsdLuxShapingAPIで、ライトプリミティブにはシェーピングコントロールの追加の有無が指定できます。
    プリミティブには、適用されたすべての単独適用のAPIスキーマのリストを記録するメタデータがあります。

  • 多重に適用されるスキーマの例は、CollectionAPIです。 指定したプリミティブの一意の名前の付いたcollection:アトリビュートを必要な数だけ定義できます。

Houdiniは通常、カスタムアトリビュートを使用しません。 代わりに、プリミティブのメタデータの「カスタムデータ」辞書に情報を保存することがよくあります。 このスペースは、ソフトウェアパッケージおよびスタジオが独自に使用するためのものです。 Houdiniは、USDをディスクに保存したり、シーンをナビゲートしたりするのに役立つ簿記情報をここに保存しますが、このカスタムデータは通常、ディスクに書き込まれた際にUSDから削除されます。

 

Hydraとレンダリング

USDは、特定の時点でUSDシーンから画像を生成するためのAPI(Hydraと呼ばれます)を定義しています。
プログラム(Houdini、usdview、レンダラーなど)がこのAPIを実装している限り、USDシーンの表示/レンダリングが利用できます。

このAPIを実装するソフトウェアの一部は、レンダーデリゲートと呼ばれます。

Houdiniでは、HoudiniのOpenGLビューアー、PixarのStorm OpenGLビューアー、Karma IPRなどの使用可能なレンダーデリゲート間でシーンビューを切り替えることができるという大きな利点があります。 さらに、Hydra APIを実装したサードパーティのレンダラーを使用してシーンを表示できます。 特にHoudiniと統合するために特別な作業をする必要はありません。

 

USDの整理

通常、「トップレベル」のUSDファイルはショットを表します。 スタジオでは、トップレベルのファイルは通常、部門(キャラクター、セット/プロップ、ライト)ごとに分類されたファイルを参照し、個々のアセットへの独自の参照を持っています。 小規模な環境または1人の環境では、最上位ファイルがアセットを直接参照する場合があります。

「リファレンスの深さ」はそのファイルの「遅さ」(または複雑さ)の尺度としては役に立ちません。 USDの構成エンジンは非常に高速です。 パフォーマンス(ロード時間など)は、リファレンスレベルの数よりも、レイヤーの内容とインフラストラクチャ(ローカルまたはネットワーク経由でのファイルのロードなど)に依存します。

 

Tips

  • USDドキュメントでは、シーンツリーをネームスペースと呼ぶ場合があります。

  • 絶対ファイルパスの使用を避け、Windowsでもスラッシュを使用します。
    相対パス参照(たとえば、 ./chair.usd)は、参照を含むレイヤーファイル(たとえば、/Users/Aisha/Work/kitchen.usdに対して相対的です。

大規模なスタジオや複雑なファイル管理の場合は、複雑なファイルパスを使用するよりも、アセットIDとカスタムレゾルバを使用する方がおそらく良いでしょう。

 Houdiniでは、通常、シーンファイルに関連するファイルを$HIP下に保存します。 HoudiniがUSDを書き出すとき、出力プロセッサを呼び出してファイルパスを変換します。 デフォルトの出力プロセスは、$HIPを基準としたファイルパスを、USDの規則に従って、最上位のUSDファイルを基準としたパスに変換します。