Skip to content

usdSkel

Syoyo Fujita edited this page Feb 14, 2026 · 3 revisions

This note summarizes the USD spec evaluation and the Blender import evaluation for skinned meshes. The equations are written with generic prim names so they can be applied to any skinned asset.

Notation

  • p_local : mesh point in mesh-local space (as stored in the Mesh prim)

  • G : primvars:skel:geomBindTransform on the Mesh prim (world-space bind transform)

  • w_i : skin weight for joint i

  • J_i(t) : joint skeleton-space transform for joint i at time t

  • B_i : bindTransforms[i] from the Skeleton (world-space bind pose)

  • S(t) : Skeleton prim world transform at time t (a.k.a. skelLocalToWorldTransform)

  • M_meshLocal : mesh prim's authored xformOps (mesh-local Xform)

  • M_parentBelowSkel : any parent Xforms below the SkelRoot that are ancestors of the mesh

  • M_parentAboveSkel : any ancestors of the Skeleton prim (including SkelRoot if it is an ancestor)


USD-Spec Evaluation (Correct)

In USD, skinned prim xformOps are ignored. The only transforms participating in skinning are: geomBindTransform, joint transforms, and the Skeleton prim's world transform.

Skinning transform per joint

K_i(t) = inv(B_i) * J_i(t)

Skinned point in skeleton space

p_skel(t) = Σ_i [ w_i * K_i(t) * G * p_local ]

Final world-space point

p_world(t) = S(t) * p_skel(t)

Expanded

p_world(t) = S(t) * Σ_i [ w_i * inv(B_i) * J_i(t) * G * p_local ]

Important:

  • M_meshLocal and M_parentBelowSkel are ignored for skinned rendering.
  • S(t) includes any ancestors of the Skeleton prim, which may include a SkelRoot if it is an ancestor of the Skeleton.


Blender Import Evaluation (Observed)

Blender (for this USD import) applies the object transform chain on top of armature deformation. So transforms authored on the mesh prim and its parents below the SkelRoot are applied in addition to skinning.

Blender-style evaluation

p_world_blender(t) = M_parentAboveSkel(t) * M_parentBelowSkel(t) * M_meshLocal * p_skin(t)

Where p_skin(t) is the armature-deformed point Blender computes from the Skeleton animation. This is effectively:

p_skin(t) = Σ_i [ w_i * K_i(t) * G * p_local ]

So the full Blender-style equation becomes:

p_world_blender(t) = M_parentAboveSkel(t) * M_parentBelowSkel(t) * M_meshLocal
                      * Σ_i [ w_i * inv(B_i) * J_i(t) * G * p_local ]

Key difference vs USD spec:

  • Blender applies M_meshLocal and M_parentBelowSkel (mesh and parent XformOps)
  • USD spec does not apply those transforms to skinned geometry

Summary

  • USD spec: only geomBindTransform, joint transforms, and Skeleton world transform affect skinned output.
  • Blender import: applies mesh + parent Xforms in addition to skinning, which can create double transforms.

Clone this wiki locally