コンテンツにスキップ

UsdSkelの構造を理解する

ipynbFile usdskel_02__UsdSkelの構造を理解する.ipynb

こんな感じの最寄りのJointにweight1つけたシンプルなCubeでテスト

In [118]:

1
from pxr import Usd,UsdSkel,UsdGeom

In [107]:

1
stage = Usd.Stage.Open(r"D:\SimpleSkelB.usd")

In [108]:

1
2
rootPrim = stage.GetPrimAtPath("/World/Root")
usdRoot = UsdSkel.Root(rootPrim)

In [109]:

1
2
3
4
# UsdSkelSkeleton は、Skeletonのトポロジー定義し、BindPoseを保持する
skel = UsdSkel.Skeleton(stage.GetPrimAtPath("/World/Root/joint1"))
# Animation は、SkeletonとBlendShapeのアニメーションを保持する
anim = UsdSkel.Animation(stage.GetPrimAtPath("/World/Root/joint1/Animation"))

In [110]:

1
2
3
4
5
6
7
skelPrim = skel.GetPrim()
# SkeletonのAnimationはRelationでAnimationPrimが指定されている
animPath = skelPrim.GetRelationship("skel:animationSource").GetTargets()[0]
# Animationの値はVector
print(anim.GetRotationsAttr().Get())
print(anim.GetTranslationsAttr().Get())
print(anim.GetScalesAttr().Get())

Success

1
2
3
[(1, 0, 0, 0), (1, 0, 0, 0)]
[(0, 0, 0), (0, 2, 0)]
[(1, 1, 1), (1, 1, 1)]

In [111]:

1
2
3
4
# UsdSkelの構造を取得
# UsdSkelは、SkeletonPrimのアトリビュートとしてSkeletonの構造を持つ
for i in skel.GetJointsAttr().Get():
    print(i)

Success

1
2
joint1
joint1/joint2

In [112]:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Skelの構造は Topology を利用すると解析できる
joints = skel.GetJointsAttr().Get()
topology = UsdSkel.Topology(skel.GetJointsAttr().Get())

# Joint数を取得
print(topology.GetNumJoints())
# 引数のIndexがRootかどうか返す
print(topology.IsRoot(0))
# 引数のIndexのParentのIndexを取得する
print(joints[1])
parentIndex = topology.GetParent(1)
print(joints[parentIndex])

# ParentのIndexを全部取得 -1 がRoot
# print(topology.GetParentIndices())

Success

1
2
3
4
2
True
joint1/joint2
joint1

In [113]:

1
2
3
4
# JointsAttr の配列に対応するTransformのリスト
# 配列はWorldSpaceのMatrix(GfMatrix4d)
for i in skel.GetBindTransformsAttr().Get():
    print(i)

Success

1
2
( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )
( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 2, 0, 1) )

In [114]:

1
2
3
meshPrim = stage.GetPrimAtPath("/World/Root/Geom/pCube1")

bindingAPI = UsdSkel.BindingAPI(meshPrim)

In [115]:

1
2
3
4
# Mesh にBindされているJointをリストできる
print(bindingAPI.GetJointsAttr().Get())
# SkeletonPrimのPathを取得する
bindingAPI.GetSkeletonRel().GetTargets() 

Success

1
[joint1, joint1/joint2]

Success

1
[Sdf.Path('/World/Root/joint1')]

In [119]:

1
2
# WeightのついているMeshのVertexの値を確認してみる
mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/World/Root/Geom/pCube1"))

In [125]:

1
2
3
# 上の頂点のIndexは 2 3 4 5
for i in mesh.GetPointsAttr().Get():
    print(i)

Success

1
2
3
4
5
6
7
8
(-0.5, -0.5, 0.5)
(0.5, -0.5, 0.5)
(-0.5, 0.5, 0.5)
(0.5, 0.5, 0.5)
(-0.5, 0.5, -0.5)
(0.5, 0.5, -0.5)
(-0.5, -0.5, -0.5)
(0.5, -0.5, -0.5)

In [129]:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# MeshのSkin情報は primvars:skel:jointIndices と primvars:skel:jointWeights で保持されている。
# indeces は、あるVtxの影響をしているJointのIndex weightはそのIndexの影響力のWeightを持つ
# このIndexは、 VertexSize * JointNum 分のIndex
indicesPrimvar = bindingAPI.GetJointIndicesPrimvar() # UsdGeomPrimvar
weightPrimvar = bindingAPI.GetJointWeightsAttr() # UsdGeomPrimvar
# Indexの並び順は
# 上の頂点のWeight
print(indicesPrimvar.Get(0)[4:6])
print(weightPrimvar.Get(0)[4:6])
# 下の頂点のWeight
print(indicesPrimvar.Get(0)[0:2])
print(weightPrimvar.Get(0)[0:2])

Success

1
2
3
4
[1, 0]
[0.9998923, 0.00010770559]
[0, 1]
[0.99999505, 0.0000049471855]