SOLARIS で Inherits(継承)を扱う¶
SOLARIS の中での USD コンポジションアークは、ほぼサブレイヤー・リファレンス・バリアント
の 3 つで成り立っていて、なんか継承の影が薄いなーということで
せっかくなので継承について調べてみました。
継承のノード¶
まず、SOLARIS 上で継承を使いたい場合は
独自ノードではなく Reference ノード内の ReferenceType を使用します。
ReferenceType の Inherits From First Input を選択すると
Input1 のノードを継承して新しく Primitive を作成します。
Class と Def の違い¶
継承の説明をする前に、USD の Primitive の定義をする場合、
「def」という Specifier(指定子)を使用しますが
def 意外にも「class」という指定子が存在します。
コレが一体どう違いが出るかというと、
このように、定義するとシーングラフ上に表示されるものの
名前の左側にかがみもちみたいなアイコンが表示され、ビューポートにはなにも表示されません。
class の場合は、あくまでも定義だけで実体を作らず
Reference や Inherits を使用することで
class で定義している Primitive を作成することが出来ます。
継承について¶
そもそも USD の継承はなにかというと、その名の通りある Primitive の構造を「継承」して
あたらしい Primitive を作成します。
挙動的にはほぼ Reference と同じですが、その挙動には若干の違いがあります。
まず、Reference。
Reference は完全なカプセル化された別のレイヤーを、指定の Primitive に対してロードします。
「カプセル化」がなにかというと、
まず、こんなサンプルを用意します。
1 2 3 4 5 6 7 |
|
Reference ノードでは、↑ のようなファイルをロードしておきます。
そして、片側の inlineusd で
1 2 3 |
|
こうします。
この 2 つをサブレイヤーで合成してみます。
「Reference」の場合、
結果は Cube になります。
シーングラフをみても、Class 定義はなくロードされた Primitive のみが表示されます。
Reference で読み込まれてるレイヤー内の構造がカプセル化されているので
あとからサブレイヤーでファイルをロードしたとしても、
合成はされるものの、リファレンス内の構造には影響を与えません。
これを
1 2 3 4 5 6 7 |
|
このように「継承」にしてみます。
すると、サブレイヤーの結果は Sphere に変わりました。
つまりは、Merge ノードを使用して合成した class Sphere "BaseObj" {} が
Reference ノードを使用して読み込んだレイヤー内の class を上書きしている...ということがわかります。
この差が、Reference と Inherits の大きな違いになります。
SOLARIS 内での扱い方¶
ここまでが USD 的な挙動でしたが
では実際に SOLARIS 上での挙動を調べてみます。
まずはこんな感じで class 指定子で Class を定義します。
Primitive ノードを使用すると、指定の Type で def または class を作成できます。
ので、今回は Cube を Class で作成します。
Inherits は単独のノードではなく Reference ノードのオプションで切り替えできます。
切り替えたら、継承元の Primitive を指定します。
なお、Reference と Inherits の違いとして、Reference は別のレイヤー(別の usd)を指定して
ロードすることが出来ますが、Inherits は同じレイヤー内の Primitive を指定する
必要があります。
ので、別ファイルで定義している場合はサブレイヤーで合成してから inherits =<~~>で
Primitive を指定する必要があります。
で。
Inherits で継承した結果
1 2 3 4 5 6 7 8 9 |
|
こんな感じの usda が作成されます。
結果のシーングラフ。
Inherits という名前の Cube が作成されました。
この継承したレイヤーを USD ROP で出力します。
そのファイルをRefernceノードでロードすると、
このようにClass定義はなくなり、ファイル内の指定のPrimitive(通常はDefaultPrim)のみが
表示されます。
しかし、表示はされていないものの、継承元の TestClassA クラスはオーバーライド可能で
1 2 3 |
|
このようなファイルをサブレイヤー合成すると、
こんな感じで合成され
結果はSphereに変わります。
しかし、これを Reference From First Input にしてから再度出力して、
同じノードを確認すると
同じ構成であっても、オーバーライドされずにreference4はCubeのまま
Reference内のClassは隠蔽された状態になります。
これが、ReferenceとInheritsの挙動の差のようです。
loadLayerでの読み込み¶
レイヤーを読み込む場合、Referenceノードの場合は
Classは隠蔽され、シーングラフには表示されず、継承したクラスをオーバーライドする等は
出来ません。
loadLayer+Referenceノードを使用してリファレンス化した場合
こうすると
こうなります。
ファイルでReferenceを読み込むのではなく
LoadLayerでReferenceノードにつなぐと
あくまでも、同じレイヤー内にあるPrimitiveをリファレンスでロードした状態と同じになり
レイヤー内の隠蔽はされず
この場合は、
1 2 3 |
|
こんな感じのレイヤーをサブレイヤー合成すると
合成されてオブジェクトがCubeからSphereになります。
LoadLayerで読み込んでReferenceノードでリファレンス化(複製)しても
挙動は同じなのかなと思っていましたが、挙動は違っていて
LoadLayer+Referenceノードにノード接続の場合は
サブレイヤーで合成されたあと、同じレイヤー内にあるPrimitiveをReferenceしている状態で
Referenceノードの場合はPrimitiveで reference=@Path@\</SdfPath>している状態ということか。
というわけで、レイヤーでカプセル化してロードしたい場合は
Referenceノードを使用してロードするのが正解でした。
ノードでの表現方法、まだまだ難しい....`