Skip to main content

USDPython ドキュメントの読み方

概要まわりの文章化がうまくいかないので 最近大分 USD を Python で弄るのも分かってきた
ので、よく使うコマンド類とざっくりと公式ドキュメントから
Python のコードを書く時にはまったりわかりにくいところなどをメモをば。

モジュールの Import と、使い方

USD の API ドキュメントは
https://graphics.pixar.com/usd/docs/api/index.html
こちらにあるのですが、基本 C++なのと説明もとても難解なのでわかりにくいです。
ので、ものすごいざっくりと Python への読み替え方を説明。

まず、Python の Import について。

from pxr import Usd, UsdGeom, Sdf, Gf

USD のモジュールは pxr モジュールで、その中の各種スキーマやツール類を
インポートします。

ドキュメントの「Classes」下にライブラリのクラスや各種関数が並んでいるのですが
Python から使用する場合は頭の文字が import で読み込むモジュール名になります。
上の画像のよく使う UsdStage の場合は Usd モジュールの Stage になります。

from pxr import Usd
prim = Usd.Stage.CreateInMemory()

こうなります。

クラスの関数の調べ方

USD の各種クラスは、クラスの継承によって構造化されています。
「Inheritance diagram for #### 」を確認するとその継承関係がどのようになっているのか
ダイアグラムで確認することが出来ます。

例えば図の UsdGeomCube というクラスは UsdGeomCube に、使用できる関数が羅列されています。 ですが、ここにおあるのは UsdGeomCube 固有の機能だけであって移動したりバウンディングボックスを取得したりといった 機能は書かれています。

そのような、ほかのオブジェクトでも共通している機能は親のクラス (~ able という名前のことが多い)で定義されています。 Xformable なら移動を可能にするし、GeomBoundable には BoundingBox を取得する機能があります。

なので、ヘルプを見るときには、調べたいクラスのページを確認した後 Inheritance diagram を確認して、欲しい値がありそうな親クラスを確認します。

スキーマ関係の継承関係について

スキーマを定義したい場合、主に UsdGeom を使用することになります。

このスキーマの定義は「IsASchema」と呼ばれる 「A は B です」の関係によって定義されています。
たとえば、
UsdGeomXform は、UsdGeomImageable で UsdXformable です。
これらのダイアグラムの末端以外は「AbstractSchema」と呼ばれるもので
共通の定義をしてある基底クラスです。
ので、これらのクラスのインスタンスを作る事はできません。

これに対して、末端の UsdGeomXform や UsdLuxDistantLight 、UsdGeomCamera などのスキーマは
「ConcreteSchema」と呼ばれるスキーマで
実際にスキーマとして定義(Define)することができるスキーマになります。

stage = Usd.Stage.CreateInMemory()
xform = UsdGeom.Xform.Define(stage, "/hello")

たとえば Xform スキーマを定義したい場合はこうなります。

UsdGeom.Xformable.Define(stage,'/hello')

これはエラーになります。

stage = Usd.Stage.CreateInMemory()
xform = UsdGeom.Xform.Define(stage, "/hello")
xform.GetXformOpOrderAttr() # Xformableで定義
xform.GetPrim() # UsdSchemaBaseで定義

当然のことですが、Xform は Xformable の関数も使えます。
すべてのスキーマで共通して使用する GetPrim などのような関数は UsdSchemaBase に定義されているので
ドキュメントを見るときは、継承関係を確認します。

引数の確認方法

USD のドキュメントは、C++のドキュメントのため Python のライブラリドキュメントと比べて非常に見づらいです。

その中でいくつか見方を紹介します。

ただし、そもそもドキュメントにある関数がなかったり、全く別の名前になっていることも 結構あるので、あくまでも参考までに。

const ~ <型>

const は、C++の 編集不可で参照渡しをするときに使用するものですが Python のドキュメントとして読み替えると <型> の値を引数で指定しろという意味になります。

たとえば、 ApplyAPI(const TfToken ~)とすると TfToken 型(↓ に詳細を書いてますが、Tftoken は string 型)を引数として渡せば OK です。

UsdGeomCube の場合、 const UsdPrim &prim=UsdPrim() のように、 = UsdPrim() とあります。 これは、Python の

def hogehoge(arg = 0):
return

このような、デフォルト設定付きの引数と同じで、指定がなければ prim=UsdPrim() の UsdPrim がデフォルトとして使用されます。

cube = UsdGeom.Cube()

なので、これでもエラーになりません。

指定したい場合は「Prim」型なので

prim = stage.GetPrimAtPath("/cube")
cube = UsdGeom.Cube(prim)

このようにすると、指定の Prim のスキーマオブジェクトを取得する...といったコードを書くことができます。

複数同じような関数が定義されてるケース

ドキュメントの中には、このように同じ関数なのに複数定義されているようなケースがあります。 これは、C++は引数が違うものであれば同じ関数名でも定義できるからこのようになっていて 厳密な型定義がある C++で string や int 配列のように引数で型が違うようなものを定義したい場合などで このようになっています。 この場合、何かしらの型の値か、char 型か、配列(VtValue)が個別に定義されているのですが Python の場合は、型定義をせずになんでも関数に対して渡すことができるので この場合 Set(配列 or 文字列・数字) と読み替えられます。

Stage

const UsdStagePtr ~ となっているものは、 UsdStage オブジェクトを渡すという意味です。

# 空のステージを作る
stage = Usd.Stage.CreateInMemory()
# Cubeを作る
cube = UsdGeom.Cube.Define(stage,Sdf.Path("/sampleCube"))

UsdGeomCube で Stage に Cube を作りたい場合だと、 const UsdStagePtr &stage , const SdfPath &path なので、作成対象の stage と、その Stage のどこに Cube を作りたいかを指定します。

VtValue VtArray VtDictionary

VtValue とは、型がきちんと決められている C++の中で、自由な型を入れたい場合に使用されます。 なので、Python 的には「何かしらの変数」が入ります。 VtArray は、VtValue の配列版、VtDictionary は辞書型で、複数の異なった型の変数を配列で持ちたい場合に使用できます。

Enum 型

たとえばこの UsdInterpolationType のようにある決められた選択肢からいずれか選択したい場合は、 Enum 型を指定します。 interpolation.h FileReference をみると

UsdInterpolationType とあります。 これはに入っているうちいずれかを指定してくれ という意味なので、

stage.SetInterpolationType(Usd.InterpolationTypeHeld)

このようになります。 引数の Type のリンクをクリックして、その先が enum になっているものはこのように指定します。

おおむね、補完方法であったり

RotationOrder のように、Maya で ComboBox で指定するようになっているものが Enum 型になっているイメージです。

TfToken

https://graphics.pixar.com/usd/docs/api/class_tf_token.html

TfToken とは、C++で文字列を扱うためのクラスです。
Usd では文字列を非常に多く扱いますが、きちんと扱わないと非常に効率が悪くなってしまいます。
ので、Python のディクショナリのように Index を作成して文字列を扱うのが TfToken です。
(あまり C++詳しくないので具体的にどうとかはワカラナイ)

ドキュメントを見ると、このように引数で TfToken 型を求められることがありますが
Python の場合はそもそもこの Tf.Token は存在しませんので
基本 str 型として読み替えを行います。

では、Python 側では Token は無関係かというとそんなこともなくて

print(UsdGeom.Tokens.type)

各クラス内には Token クラスを取得定義されている関数名などを、文字列で取得することができます。

Usd の AttributeType 定義について

Prim に対してアトリビュートを追加したい場合には
そのアトリビュートの型がなにかを定義する必要があります。

https://graphics.pixar.com/usd/docs/api/class_usd_prim.html#a1e25b831b0e54e1d59ba2da969e165fa

ドキュメントを見ると、 SdfValueTypeName で定義しろと書いてありますが
この SdfValueType も Python と C++では大きく違っていて、クラスメソッドの構成そのものがだいぶ
違うのでうまくいきません。

では Python の場合はどうするかというと

str_attr = prim.CreateAttribute("testStr", Sdf.ValueTypeNames.String)

Python の場合、 Sdf.ValueTypeNames という Enum が存在していて
これを使用して型を定義します。
(しかしドキュメントにこの ValueTypeNames はない)

Asset AssetArray
Bool BoolArray
Color3d Color3dArray Color3f Color3fArray
Color3h Color3hArray Color4d Color4dArray
Color4f Color4fArray Color4h Color4hArray
Double Double2 Double2Array
Double3 Double3Array
Double4 Double4Array DoubleArray
Find
Float Float2 Float2Array
Float3 Float3Array
Float4 Float4Array FloatArray
Frame4d Frame4dArray
Half Half2 Half2Array
Half3 Half3Array
Half4 Half4Array HalfArray
Int Int2 Int2Array
Int3 Int3Array
Int4 Int4Array
Int64 Int64Array
IntArray
Matrix2d Matrix2dArray Matrix3d Matrix3dArray Matrix4d Matrix4dArray
Normal3d Normal3dArray Normal3f Normal3fArray Normal3h Normal3hArray
Point3d Point3dArray Point3f Point3fArray Point3h Point3hArray
Quatd QuatdArray Quatf QuatfArray Quath QuathArray
String StringArray
TexCoord2d TexCoord2dArray TexCoord2f TexCoord2fArray TexCoord2h TexCoord2hArray
TexCoord3d TexCoord3dArray TexCoord3f TexCoord3fArray TexCoord3h TexCoord3hArray
Token TokenArray
UChar UCharArray
UInt UInt64 UInt64Array UIntArray
Vector3d Vector3dArray
Vector3f Vector3fArray
Vector3h Vector3hArray

print(dir(Sdf.ValueTypeNames))をすると、一応使える型がリストできるので
これを見ながら頑張って CreateAttribute の型定義をします。
(しました)