メインコンテンツまでスキップ

Schemaについて

Universal Scene Description 7 日目は、Schema(スキーマ)についてです。

Schema とは

USD defines a schema as an object whose purpose is to author and retrieve structured data from some UsdObject. 引用: https://graphics.pixar.com/usd/release/glossary.html#usdglossary-schema

とあるとおり、あるUsdObject(Prim)に対して共通の機能・特性を指定するものです。

たとえば、UsdGeomMesh なら、この Prim には Mesh を作るのに必要な Property が定義されているから 表示するツールは Mesh として扱っていいよ この UsdGeomXform なら、これはいわゆる TransformNode だからそのつもりで扱っていいよ というような、各 Prim に対して役割(構造)を与えます。

当然、DCC ツールからデータを Export する時には、Prim に対しては Schema が定義されています。 そのため、Schema やその分類については意識しなくても大丈夫ですが、 Python 等で USD を操作しようとした場合はその限りではありません。

stage.DefinePrim('/hogehoge')

たとえば、このように UsdStage から DefinePrim した場合。 構造化されていない野良データになります。

その場合、ツールによっては Type の解釈がうまくいかなくて問題になったりするので Schema は定義するようにしましょう。

Schema の種類

なんとなく Schema がどんなものか理解できてきたとおもいますが、 Schema と一言で言っても、様々な種類があります。

分類すると、このようになります。

多くの場合 は Prim Schema と呼ばれる Prim に対して指定する Schema ですが この PrimSchema も、役割や対象によって細かくいくつかの種類に分かれます。 さらに理解を深めるために、分類について見ていきます。

Prim Schema

PrimSchema は、その名の通り Prim に対して指定される Schema のことを指します。 多くの場合、Schema はこの PrimSchema です。

# 野良Primを作った場合
stage.DefinePrim("/noraPrim")

最初に説明した通り、UsdStage から DefinePrim した場合は、Schema の定義されていない空の野良 Prim になります。 この Prim に対して Type(Prim Schema)を指定します。

作成するには、各 Schema のクラスの Define から Prim 作成を実行します。 すると、指定された Schema で Prim を定義することができます。

例として、Cube を作成したい場合。

stage = Usd.Stage.CreateInMemory()
geom = UsdGeom.Cube.Define(stage,'/sample')
print(stage.ExportToString())

このように UsdGeomCubeDefineすると、 Prim は指定した Schema の Prim(UsdGeomCube)になります。

この CubeSchema を適応した Prim を作成すると、ほかになんの指定がなかったとしても このような例のように、 Prim に機能を与えるものが PrimSchema です。

Xform ならUsdGeomXform、Mesh ならUsdGeomMeshなど、デフォルトでよく使われる機能は デフォルトで用意されていますし、もちろん自分で定義することも可能ですが そのあたりの詳細はまた別途書こうと思います。

多くの場合が PrimSchema と書きましたが、 UsdGeomPrimvar UsdShadeInput は例外で、PropertySchema と呼ばれます。

IsA Schema / API Schema

Prim Schema は、さらに2つに分類することができます。 それが、 IsA Schema と API Schema です。

IsA

IsA とは、その名の通り A は B です という = の関係になるような Schemaです。 別名を Typed Schema と呼びます。

例えば、「この Prim は Cube です」「この Prim は Mesh です」 のように、 Prim の定義を(この Prim は ### です)のように決めます。

つまりは、Maya の NodeType(mesh transform 等)のように Prim の Type を表すのがこの IsASchema になります。

API で扱う場合の分類

普通に扱う場合は IsA Schema がある というのを理解していればよいですが、 Python や C++などで API を扱う場合は、この IsA Schema は2つに分けることができます。

それが、 Abstract SchemaConcrete Schema です。

たとえば、UsdGeomCube を例に見た場合、 UsdGeomCube は IsASchema です。

この UsdGeomCube の Inheritance diagram を見てみると、 UsdGeomCube の親クラスに ~ able といった クラスが存在しているのがわかります。

このような、~ able となっているクラスは、「abstract schema」と呼ばれるいわゆる基底クラスで ある IsASchema に対して機能を追加するものになります。 たとえば Imageable ならレンダリングしたり、ビジュアライゼーションする必要がある Prim に対して指定されるものだし Xformable なら、Transform できるようにする Prim に対して指定される...といった複数の Schema に対して共通する機能を 与えるためのクラスが、AbstractSchema です。

この AbstractSchema は、Prim を(インスタンスを)つくることができません。

対して、実際に Prim を作成できるものを Concrete Schema と呼び、

geom = UsdGeom.Cube.Define(stage,'/sample')

このように、Stage に対して Define することができます。

API Schema

API Schema は、IsA とは違いある一連のデータをオーサリングしたり抽出したりするためのインターフェースとして 機能する Prim Schema のことです。 APISchema は、 IsA に対して HasA Schema とも呼ばれます。

stage = Usd.Stage.CreateInMemory()
geom = UsdGeom.Cube.Define(stage,'/sample')

xformAPI = UsdGeom.XformCommonAPI(geom.GetPrim())
xformAPI.SetTranslate([0,100,0])

シンプルな例として、スケール・回転・移動などのオーサリングや取得をすることができる XformCommonAP を みてみます。 この API は、指定の Prim( samplePrim ) に対して、Y 方向に 100 移動する処理を適応しています。

stage = Usd.Stage.CreateInMemory()
rootLayer = stage.GetRootLayer()

# Mesh作成
sphere = UsdGeom.Sphere.Define(stage, '/test/sphere')

matPath = Sdf.Path("/Model/Material/MyMat")
mat = UsdShade.Material.Define(stage, matPath)

# ~もろもろ略~

# Bind
UsdShade.MaterialBindingAPI(sphere.GetPrim()).Bind(mat)

このほかに、 UsdShadeMaterialBindingAPI のように、ある Mesh に対して Material を Assign する といったような操作のインターフェースも、この API Schema を使用します。

API Schema にも、大きく分けると non-applied single-apply multi-apply の3種類があります。

XformCommonAPI や、UsdShaderMaterial は Single-Apply APISchema です。 これはその名の通り1つの Prim に対して1つしか適応できないものだからです。 例えば1つの Mesh には複数のマテリアルはアサインできないし、 複数の Xform を適応することはできません。

non-Applied

non-applied は、プロパティをセットするためなどに存在する API で、PrimType や定義には影響しないもののことを指します。 例として、 UsdModelAPI 等があり、 などで、

from pxr import Usd
api = Usd.ModelAPI(usdviewApi.prim)
api.SetKind('chargroup')

Prim に対して Kind を指定していますが、これはあくまでも決められた値をセットするためにあるもので APISchema が適応されているわけではありません。

Multi-Apply

最後の Multi-Apply は、ある Prim に対して複数適応することができる APISchema です。

MultiApply の APISchema の例としては、 UsdCollectionAPI があげられます。 詳細は、過去に にまとめたのでそちらをみればわかるかと思いますが、 Collection は、1つの Prim に対して複数の Collection を適応することができます。(いわゆる Sets)

まとめ

以上 USDSchema についてでした。

USD を扱っていると、デフォルト容易されている Schema だけではなかったり 不空数の Prim に対してなにかしらのオーサリングをするときについかの拡張をしたいケースが出てくると思います。 そうでなかったとしても、Python や C++から USD のシーングラフを扱う場合、 専用のカスタム Schema を定義したい場合などは、 この Schema の定義、Property 関連を理解しておくと公式の API ドキュメントがかなり理解しやすくなると思います。