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 ファイルパスを取得する
print(layer.identifier)
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 を取得
prim = xform.GetPrim()
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 先を取得
attrPath.GetTargets()
GetTargets()を使用すると、接続先の SdfPath を取得できる。
SdfPath から Attribute の値を取得する
relPrim = stage.GetObjectAtPath(attrPath.GetTargets()[0])
print(relPrim.Get())
SdfPath から Prim または Attribute を取得したい場合は、Stage の GetObjectAtPath()を使用する。
Object で取得したばあい、Prim の場合は Prim オブジェクトが帰ってくるし
Attribute だったら Attribute オブジェクトが帰ってくる。
Metadata
Metadata は Prim や Attribute などに対して設定できる付加情報。
Metadata の取得
# 指定のPrim・Attribute・PropertyのMetadataをDictで取得
print(prim.GetAllMetadata())
Metadata に値をセットする
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 操作
Xform オブジェクトを使用する場合
stage = Usd.Stage.CreateInMemory()
xform = UsdGeom.Xform.Define(stage, '/xform')
xform.AddTranslateOp().Set((50, 0, 0))
Xformable クラスに各種 Tranlsform 操作用の関数があるので
それを使用すれば Transform ができる。
Prim から Transform する場合
path = Sdf.Path("/xform")
prim = stage.GetPrimAtPath(path)
UsdGeom.XformCommonAPI(prim).SetRotate((90, 0, 0))
Xform オブジェクトではなく、Prim オブジェクトから
Transform 処理をしたい場合は XformCommonAPI を使用する。
コンポジション関係
VariantSet
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
# クラスを定義して保存する
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)
で読み込む。
出力結果はこんな感じに。
#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"]
アニメーション関係
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)
マテリアル関係
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 関係
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)