PythonUSD チートシート
Python を使用して USD を操作するやり方がだいぶ分かってきたので
よく使う物とかをまとめ。
全般
Import
| import os.path
from pxr import Usd, UsdGeom, Sdf, Gf
|
Stage 関係
New シーン
| stage = Usd.Stage.CreateInMemory()
|
usda を作らずにとりあえずステージを作る場合。
| stage = Usd.Stage.CreateNew(USD_PATH_ROOT + '/HelloWorld.usda')
|
usda を作って、新しいステージを作る。
USD を開く
| stage = Usd.Stage.Open(USD_PATH_ROOT + '/HelloWorld.usda')
|
すでにある USD ファイルをステージとして開く。
Payload をロードせずに USD を開く
| stage = Usd.Stage.Open(USD_PATH_ROOT + '/HelloWorld.usda',Usd.Stage.LoadNone)
|
保存する
| stage = Usd.Stage.CreateNew(USD_PATH_ROOT + '/HelloWorld.usda')
stage.Save()
|
開いている usd をそのまま保存。
| stage = Usd.Stage.CreateInMemory()
stage.GetRootLayer().Export(USD_PATH_ROOT + '/HelloWorld.usda')
|
メモリ上のみで作成している USD を Export する。
CreateNew して開いて保存する場合、すでに USD があると Error になってしまうが
こちらの場合はエラーにならない。
現在の USD の中身を確認する
| print(stage.GetRootLayer().ExportToString())
|
ExportToString をすると、げんざいの USD をプリントすることができる
全コンポ結果を反映した USD を確認する
| stage.Flatten().ExporToString()
|
通常の ExportToString()の場合、コンポ情報が残った状態で表示される。
が、すべてのコンポジションの結果をすべて判定(Flatten)した状態で見たい場合は
上のようにする。
当然のことながら、複雑なコンポを行っている場合 Flatten するとファイルサイズは増大する。
Stage 関係
ステージ内の Prim をトラバースする
| compStage = Usd.Stage.Open(USD_PATH_ROOT + "/sample.usda")
for prim in compStage.Traverse():
print(prim)
|
実行すると、このようなシーングラフなら
このように全 Prim を深さ優先で取得することができる。
Payload がロードされていないノードも Traverse する
Prim の状態をチェックしつつ検索するには GetFilteredChildren を使用する。
このコマンドの場合は、引数に Traverse するノードの状態を指定することで
該当するノードを取得することができる。
| for i in prim.GetFilteredChildren(Usd.PrimIsActive & Usd.PrimIsDefined & ~Usd.PrimIsAbstract):
print(i)
|
通常の Traverse や GetChildren は、上のフラグに+して Usd.PrimIsLoaded も ON になっている。
なので、Payload で読まれていない Prim は取得できない。
Layer をミュートする
| # Layerのusdファイルは identifer で取得できる
# パス指定でLayerをミュート(コンポ処理から除外)できる
compStage.MuteLayer(layer.identifier)
|
ミュートは現在のステージ上のみで有効で、USD ファイル内には保存されない。
→ ミュートした状態で Flatten すると、ミュート状態のレイヤーは無効化される。
Layer 関係
RootLayer を取得
| openUsd = Usd.Stage.Open(USD_PATH + "/baseUSD.usda")
print(openUsd.GetRootLayer())
|
Composition の Root の Layer(.usda)を取得する。
ここで取得出来る Sdf.Find()で取得出来る Layer の Prim は
いわゆる PrimSpec。
指定 Layer オブジェクトの usd ファイルパスを取得する
Prim 操作
Prim/Class/Over を作る
| stage.DefinePrim("/hogehoge")
stage.OverridePrim("/over")
stage.CreateClassPrim("/class")
|
スキーマなしの Prim が作成される。
Stage から Prim を取得する
| prim = stage.GetPrimAtPath('/hogehoge')
print(prim)
|
スキーマありの Prim を定義する
| stage = Usd.Stage.CreateInMemory()
# Xformを作る
xform = UsdGeom.Xform.Define(stage, '/xform')
# Cubeを作る
cube = UsdGeom.Cube.Define(stage, '/hello')
|
ConcreteSchema には Define 関数があるので、↑ のように定義する。
Schema オブジェクトから Prim を取得
SdfPath 関係
SdfPath の基本操作
| sdfPath = Sdf.Path("/base")
xform = UsdGeom.Xform.Define(stage, sdfPath)
|
SdfPath は、 / スタートで Stage 内のシーングラフを定義する。
定義した Path で、Prim やスキーマの定義を作ることができる。
各オブジェクトから Path 取得
| attr = prim.CreateAttribute("test", Sdf.ValueTypeNames.Bool)
xformPath = xform.GetPrim().GetPath()
attrPath = attr.GetPath()
|
Path を取得したい Prim や Attribute、Prim オブジェクトで .GetPath() する。
Attribute の Path は /base.test のように . で表現される。
SdfPath が何を指しているか確認する
| print(sdfPath.IsPropertyPath())
print(sdfPath.IsPrimPath())
print(sdfPath.IsTargetPath())
|
Is ~ Path で、SdfPath が何をしてしているのかチェックできる。
SdfPath 操作
| # 子に対して引数の階層を追加する
cldPath = sdfPath.AppendChild('hoge')
# 子に対してAttributeを追加する
cldAttrPath = sdfPath.AppendProperty('hogeAttr')
|
Attribute 操作
Attribute を作る/セットする
| # Boolの場合
attr = prim.CreateAttribute("test", Sdf.ValueTypeNames.Bool)
attr.Set(False)
# Colorの場合
color_attr = prim.CreateAttribute("color", Sdf.ValueTypeNames.Color3d)
color_attr.Set(Gf.Vec3d(1, 1, 1))
|
ValueTypeNames での型指定方法は こちらを参照。
Color や Vector などの型は Gf モジュールにある定義を使用してセットする。
Attribute から値を取得する
| attr = prim.GetAttribute('test')
print(attr.Get())
|
Namespace を使用する
| # Namespaceつきのアトリビュートを作る
prim.CreateAttribute("ns:testVal", Sdf.ValueTypeNames.Bool)
props = prim.GetPropertiesInNamespace('ns')
print(props)
|
プロパティ名・アトリビュート名には Namespace をつけることができる。
つけかたは Namespace:hogehoge のように : で区切れば OK。
Namespace をつけておくと、GetPropertiesInNamespace 関数を使用して
指定の Namespace のプロパティやアトリビュートを取得することができる。
Namespace や Nmaespace 無しのプロパティ名を取得
| print(attr.GetBaseName())
print(attr.GetNamespace())
print(attr.SplitName())
|
この Namespace やプロパティ名は、プロパティオブジェクトで取得することができる。
Relationship を使用する
Relationship を作成
| # RelationshipでPrimを入れる
rel = prim.CreateRelationship('test')
rel.AddTarget(relSdfPath)
rel.AddTarget(relSdfPathB)
# AttributeもRelにできる
relAttr = prim.CreateRelationship('attr_test')
relAttr.AddTarget(attr.GetPath())
|
Relationship 先を取得
GetTargets()を使用すると、接続先の SdfPath を取得できる。
SdfPath から Attribute の値を取得する
| relPrim = stage.GetObjectAtPath(attrPath.GetTargets()[0])
print(relPrim.Get())
|
SdfPath から Prim または Attribute を取得したい場合は、Stage の GetObjectAtPath()を使用する。
Object で取得したばあい、Prim の場合は Prim オブジェクトが帰ってくるし
Attribute だったら Attribute オブジェクトが帰ってくる。
Metadata は Prim や Attribute などに対して設定できる付加情報。
| # 指定のPrim・Attribute・PropertyのMetadataをDictで取得
print(prim.GetAllMetadata())
|
| newScn.SetMetadata('comment', 'Hello World')
|
CustomData を使用する
| # 指定のオブジェクトに対してCustomDataを指定する
prim.SetCustomDataByKey('userCustomMeta', 'fuga')
# 取得する
print(prim.GetCustomData())
# namespaceを指定した場合
prim.SetCustomDataByKey('test:userCustomMeta', 'fuga')
|
CustomData で Namespace をつけると、Dict 型をネストできる。
val['test']['usercustomdata']
アクセスするときはこんな感じにできる。
Transforrm 操作
| stage = Usd.Stage.CreateInMemory()
xform = UsdGeom.Xform.Define(stage, '/xform')
xform.AddTranslateOp().Set((50, 0, 0))
|
Xformable クラスに各種 Tranlsform 操作用の関数があるので
それを使用すれば Transform ができる。
| path = Sdf.Path("/xform")
prim = stage.GetPrimAtPath(path)
UsdGeom.XformCommonAPI(prim).SetRotate((90, 0, 0))
|
Xform オブジェクトではなく、Prim オブジェクトから
Transform 処理をしたい場合は XformCommonAPI を使用する。
コンポジション関係
VariantSet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | vset = prim.GetVariantSets().AddVariantSet('hogehoge')
vset.AddVariant('red')
vset.AddVariant('blue')
vset.AddVariant('green')
colorAttr = UsdGeom.Gprim.Get(newScn, '/World/Cube').GetDisplayColorAttr()
vset.SetVariantSelection('red')
with vset.GetVariantEditContext():
colorAttr.Set([(1, 0, 0)])
vset.SetVariantSelection('blue')
with vset.GetVariantEditContext():
colorAttr.Set([(0, 0, 1)])
vset.SetVariantSelection('green')
with vset.GetVariantEditContext():
colorAttr.Set([(0, 1, 0)])
|
Reference
| refPrimA = stage.DefinePrim("/World/BookGrp/Book")
refPrimA.GetReferences().AddReference(kitchenSetRoot + 'Book/Book.usd')
|
Reference で読み込みたい usd を Prim に対してセットする
Inherits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | # クラスを定義して保存する
classPrim = stage.CreateClassPrim('/TestClass')
attr = classPrim.CreateAttribute('hoge', Sdf.ValueTypeNames.Bool)
attr.Set(True)
stage.GetRootLayer().Export(USD_PATH + 'usdClass.usda')
# 定義したクラスをSubLayerでロードして、継承する
inheritStage = Usd.Stage.CreateInMemory()
rootLayer = inheritStage.GetRootLayer()
rootLayer.subLayerPaths = [USD_PATH + 'usdClass.usda']
prim = inheritStage.DefinePrim('/hoge')
path = Sdf.Path('/TestClass')
prim.GetInherits().AddInherit(path)
print(inheritStage.GetRootLayer().ExportToString())
|
継承したいクラスが別ファイルに存在する場合は
ファイルをサブレイヤーでロードして、それから継承先の Prim に対して
GetInherits().AddInherit(path)
で読み込む。
出力結果はこんな感じに。
1
2
3
4
5
6
7
8
9
10
11
12 | #usda 1.0
(
subLayers = [
@C:/pyEnv/JupyterUSD_py27/usd/usdClass.usda@
]
)
def "hoge" (
prepend inherits = </TestClass>
)
{
}
|
SubLayer
| stage = Usd.Stage.CreateInMemory()
rootLayer = stage.GetRootLayer()
rootLayer.subLayerPaths = [kitchenSetRoot + "/Book/Book.usd", kitchenSetRoot + "/Ball/Ball.usd"]
|
アニメーション関係
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | newScn.SetStartTimeCode(0)
newScn.SetEndTimeCode(100)
# Mem上に作成したUSDファイルを色々コントロール
worldGeom = UsdGeom.Xform.Define(newScn, "/World")
cubeGeom = UsdGeom.Cube.Define(newScn, "/World/Cube")
# PrimのPath(sdfPath)の作成。
worldPath = Sdf.Path("/World")
helloPath = worldPath.AppendChild("hello")
# Cubeをアニメーション
spin = cubeGeom.AddRotateZOp(opSuffix='spin')
spin.Set(time=0, value=0)
spin.Set(time=100, value=360)
|
マテリアル関係
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | stage = Usd.Stage.CreateInMemory()
rootLayer = stage.GetRootLayer()
sphere = UsdGeom.Sphere.Define(stage, '/test/sphere')
matPath = Sdf.Path("/Model/Material/MyMat")
mat = UsdShade.Material.Define(stage, matPath)
shader = UsdShade.Shader.Define(stage, matPath.AppendChild('testShader'))
# Shaderのアトリビュート設定
# 色をつけただけの基本のPBRシェーダーを作る
shader.CreateIdAttr('UsdPreviewSurface')
shader.CreateInput('diffuseColor', Sdf.ValueTypeNames.Color3f).Set(Gf.Vec3f(0, 1, 0))
shader.CreateInput('metalic', Sdf.ValueTypeNames.Float).Set(0.9)
shader.CreateInput('roughness', Sdf.ValueTypeNames.Float).Set(0.2)
# Shaderの結果をMatにつなげる
mat.CreateSurfaceOutput().ConnectToSource(shader, "surface")
# Bind
UsdShade.MaterialBindingAPI(sphere.GetPrim()).Bind(mat)
|
Mesh 関係
1
2
3
4
5
6
7
8
9
10
11
12 | UsdGeom.Xform.Define(stage, '/hoge')
mesh = UsdGeom.Mesh.Define(stage, '/hoge/hogehoge')
# %%
mesh.CreatePointsAttr([(-5, -5, 5), (5, -5, 5), (5, 5, 5), (-5, 5, 5)])
# 1Faceあたりの頂点数
mesh.CreateFaceVertexCountsAttr([3, 3])
# 結線情報?
mesh.CreateFaceVertexIndicesAttr([0, 1, 2, 0, 2, 3])
# BoundingBoxをセット?
mesh.CreateExtentAttr(UsdGeom.PointBased(mesh).ComputeExtent(mesh.GetPointsAttr().Get()))
|
Plugin 関係
ロードされている Plugin をリストする
| for i in Plug.Registry().GetAllPlugins():
print(i.name)
print(i.path)
print(i.resourcePath)
|