Skip to content

Commit

Permalink
Bringing back UsdSkel Dual Quarternion support
Browse files Browse the repository at this point in the history
This change was reverted in change 2251901 because of failures in usd opensrc manual testing.

Made some small changes to the original change 2248847 to get DQ skinning to work
in the CPU (PrMan/Embree) codepath.
Also added unit test cases to usdSkel(SkinningQuery & BakeSkinning) and regression tests for
LBS & DQ skinning in the CPU (Prman/Embree) and GPU (Storm) codepaths.

(Internal change: 2254108)
  • Loading branch information
ucbearkat authored and pixar-oss committed Nov 4, 2022
1 parent 2598536 commit 769c060
Show file tree
Hide file tree
Showing 37 changed files with 3,814 additions and 343 deletions.
157 changes: 93 additions & 64 deletions pxr/usd/usdSkel/bakeSkinning.cpp

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions pxr/usd/usdSkel/bakeSkinning.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,22 @@ struct UsdSkelBakeSkinningParms
{
/// Flags for identifying different deformation paths.
enum DeformationFlags {
DeformPointsWithLBS = 1 << 0,
DeformNormalsWithLBS = 1 << 1,
DeformXformWithLBS = 1 << 2,
DeformPointsWithSkinning = 1 << 0,
DeformNormalsWithSkinning = 1 << 1,
DeformXformWithSkinning = 1 << 2,
DeformPointsWithBlendShapes = 1 << 3,
DeformNormalsWithBlendShapes = 1 << 4,
DeformWithLBS = (DeformPointsWithLBS|
DeformNormalsWithLBS|
DeformXformWithLBS),
DeformWithSkinning = (DeformPointsWithSkinning|
DeformNormalsWithSkinning|
DeformXformWithSkinning),
DeformWithBlendShapes = (DeformPointsWithBlendShapes|
DeformNormalsWithBlendShapes),
DeformAll = DeformWithLBS|DeformWithBlendShapes,
DeformAll = DeformWithSkinning|DeformWithBlendShapes,
/// Flags indicating which components of skinned prims may be
/// modified, based on the active deformations.
ModifiesPoints = DeformPointsWithLBS|DeformPointsWithBlendShapes,
ModifiesNormals = DeformNormalsWithLBS|DeformNormalsWithBlendShapes,
ModifiesXform = DeformXformWithLBS
ModifiesPoints = DeformPointsWithSkinning|DeformPointsWithBlendShapes,
ModifiesNormals = DeformNormalsWithSkinning|DeformNormalsWithBlendShapes,
ModifiesXform = DeformXformWithSkinning
};

/// Flags determining which deformation paths are enabled.
Expand Down
18 changes: 18 additions & 0 deletions pxr/usd/usdSkel/bindingAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,23 @@ UsdSkelBindingAPI::_GetTfType() const
return _GetStaticTfType();
}

UsdAttribute
UsdSkelBindingAPI::GetSkinningMethodAttr() const
{
return GetPrim().GetAttribute(UsdSkelTokens->primvarsSkelSkinningMethod);
}

UsdAttribute
UsdSkelBindingAPI::CreateSkinningMethodAttr(VtValue const &defaultValue, bool writeSparsely) const
{
return UsdSchemaBase::_CreateAttr(UsdSkelTokens->primvarsSkelSkinningMethod,
SdfValueTypeNames->Token,
/* custom = */ false,
SdfVariabilityUniform,
defaultValue,
writeSparsely);
}

UsdAttribute
UsdSkelBindingAPI::GetGeomBindTransformAttr() const
{
Expand Down Expand Up @@ -249,6 +266,7 @@ const TfTokenVector&
UsdSkelBindingAPI::GetSchemaAttributeNames(bool includeInherited)
{
static TfTokenVector localNames = {
UsdSkelTokens->primvarsSkelSkinningMethod,
UsdSkelTokens->primvarsSkelGeomBindTransform,
UsdSkelTokens->skelJoints,
UsdSkelTokens->primvarsSkelJointIndices,
Expand Down
29 changes: 29 additions & 0 deletions pxr/usd/usdSkel/bindingAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class SdfAssetPath;
/// documentation for more about bindings and how they apply in a scene graph.
///
///
/// For any described attribute \em Fallback \em Value or \em Allowed \em Values below
/// that are text/tokens, the actual token is published and defined in \ref UsdSkelTokens.
/// So to set an attribute to the value "rightHanded", use UsdSkelTokens->rightHanded
/// as the value.
///
class UsdSkelBindingAPI : public UsdAPISchemaBase
{
public:
Expand Down Expand Up @@ -172,6 +177,30 @@ class UsdSkelBindingAPI : public UsdAPISchemaBase
USDSKEL_API
const TfType &_GetTfType() const override;

public:
// --------------------------------------------------------------------- //
// SKINNINGMETHOD
// --------------------------------------------------------------------- //
/// The skinningMethod specifies the skinning method for the prim.
///
/// | ||
/// | -- | -- |
/// | Declaration | `uniform token primvars:skel:skinningMethod = "classicLinear"` |
/// | C++ Type | TfToken |
/// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Token |
/// | \ref SdfVariability "Variability" | SdfVariabilityUniform |
/// | \ref UsdSkelTokens "Allowed Values" | classicLinear, dualQuaternion |
USDSKEL_API
UsdAttribute GetSkinningMethodAttr() const;

/// See GetSkinningMethodAttr(), and also
/// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
/// If specified, author \p defaultValue as the attribute's default,
/// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
/// the default for \p writeSparsely is \c false.
USDSKEL_API
UsdAttribute CreateSkinningMethodAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;

public:
// --------------------------------------------------------------------- //
// GEOMBINDTRANSFORM
Expand Down
11 changes: 9 additions & 2 deletions pxr/usd/usdSkel/cacheImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ UsdSkel_CacheImpl::ReadScope::_FindOrCreateSkinningQuery(
skelQuery ? skelQuery.GetJointOrder() : VtTokenArray(),
animQuery ? animQuery.GetBlendShapeOrder() : VtTokenArray(),
key.jointIndicesAttr, key.jointWeightsAttr,
key.geomBindTransformAttr, key.jointsAttr,
key.skinningMethodAttr, key.geomBindTransformAttr, key.jointsAttr,
key.blendShapesAttr, key.blendShapeTargetsRel);
}

Expand Down Expand Up @@ -300,7 +300,14 @@ UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,
key.jointWeightsAttr = std::move(attr);
}
}


if (UsdAttribute attr = binding.GetSkinningMethodAttr()) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.skinningMethodAttr = std::move(attr);
}
}

if (UsdAttribute attr = _GetAttrInPrototype(
binding.GetGeomBindTransformAttr())) {
if (attr.HasAuthoredValue()) {
Expand Down
1 change: 1 addition & 0 deletions pxr/usd/usdSkel/cacheImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class UsdSkel_CacheImpl
struct _SkinningQueryKey {
UsdAttribute jointIndicesAttr;
UsdAttribute jointWeightsAttr;
UsdAttribute skinningMethodAttr;
UsdAttribute geomBindTransformAttr;
UsdAttribute jointsAttr;
UsdAttribute blendShapesAttr;
Expand Down
4 changes: 4 additions & 0 deletions pxr/usd/usdSkel/generatedSchema.usda
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ class "SkelBindingAPI" (
*jointWeights* must match that of *jointIndices*. See UsdGeomPrimvar
for more information on interpolation and elementSize."""
)
uniform token primvars:skel:skinningMethod = "classicLinear" (
allowedTokens = ["classicLinear", "dualQuaternion"]
doc = "The skinningMethod specifies the skinning method for the prim."
)
rel skel:animationSource (
doc = """Animation source to be bound to Skeleton primitives at or
beneath the location at which this property is defined.
Expand Down
8 changes: 8 additions & 0 deletions pxr/usd/usdSkel/schema.usda
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ class "SkelBindingAPI" (
Skeleton."""
)

uniform token primvars:skel:skinningMethod = "classicLinear" (
customData = {
string apiName = "skinningMethod"
}
allowedTokens = ["classicLinear", "dualQuaternion"]
doc = """The skinningMethod specifies the skinning method for the prim."""
)

matrix4d primvars:skel:geomBindTransform (
customData = {
string apiName = "geomBindTransform"
Expand Down
40 changes: 29 additions & 11 deletions pxr/usd/usdSkel/skinningQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ UsdSkelSkinningQuery::UsdSkelSkinningQuery(
const VtTokenArray& animBlendShapeOrder,
const UsdAttribute& jointIndices,
const UsdAttribute& jointWeights,
const UsdAttribute& skinningMethod,
const UsdAttribute& geomBindTransform,
const UsdAttribute& joints,
const UsdAttribute& blendShapes,
Expand All @@ -69,6 +70,7 @@ UsdSkelSkinningQuery::UsdSkelSkinningQuery(
_interpolation(UsdGeomTokens->constant),
_jointIndicesPrimvar(jointIndices),
_jointWeightsPrimvar(jointWeights),
_skinningMethodAttr(skinningMethod),
_geomBindTransformAttr(geomBindTransform),
_blendShapes(blendShapes),
_blendShapeTargets(blendShapeTargets)
Expand Down Expand Up @@ -352,10 +354,11 @@ UsdSkelSkinningQuery::ComputeSkinnedPoints(const VtArray<Matrix4>& xforms,
}

const Matrix4 geomBindXform(GetGeomBindTransform(time));
return UsdSkelSkinPointsLBS(geomBindXform, orderedXforms,
jointIndices, jointWeights,
_numInfluencesPerComponent,
*points);
const TfToken skinningMethod = GetSkinningMethod();
return UsdSkelSkinPoints(skinningMethod, geomBindXform, orderedXforms,
jointIndices, jointWeights,
_numInfluencesPerComponent,
*points);
}
return false;
}
Expand Down Expand Up @@ -430,12 +433,13 @@ UsdSkelSkinningQuery::ComputeSkinnedNormals(const VtArray<Matrix4>& xforms,
const Matrix4 geomBindXform(GetGeomBindTransform(time));
const Matrix3 geomBindInvTransposeXform =
geomBindXform.ExtractRotationMatrix().GetInverse().GetTranspose();
const TfToken skinningMethod = GetSkinningMethod();

return UsdSkelSkinNormalsLBS(geomBindInvTransposeXform,
invTransposeXforms,
jointIndices, jointWeights,
_numInfluencesPerComponent,
*normals);
return UsdSkelSkinNormals(skinningMethod, geomBindInvTransposeXform,
invTransposeXforms,
jointIndices, jointWeights,
_numInfluencesPerComponent,
*normals);
}
return false;
}
Expand Down Expand Up @@ -484,8 +488,9 @@ UsdSkelSkinningQuery::ComputeSkinnedTransform(const VtArray<Matrix4>& xforms,
}

const Matrix4 geomBindXform(GetGeomBindTransform(time));
return UsdSkelSkinTransformLBS(geomBindXform, orderedXforms,
jointIndices, jointWeights, xform);
const TfToken skinningMethod = GetSkinningMethod();
return UsdSkelSkinTransform(skinningMethod, geomBindXform, orderedXforms,
jointIndices, jointWeights, xform);
}
return false;
}
Expand Down Expand Up @@ -550,6 +555,19 @@ UsdSkelSkinningQuery::ComputeExtentsPadding(
const VtArray<GfMatrix4f>&, const UsdGeomBoundable&) const;


TfToken
UsdSkelSkinningQuery::GetSkinningMethod() const
{
// skinning method attr is optional.
TfToken skinningMethod;
if (!_skinningMethodAttr ||
!_skinningMethodAttr.Get(&skinningMethod)) {
skinningMethod = UsdSkelTokens->classicLinear;
}
return skinningMethod;
}


GfMatrix4d
UsdSkelSkinningQuery::GetGeomBindTransform(UsdTimeCode time) const
{
Expand Down
18 changes: 15 additions & 3 deletions pxr/usd/usdSkel/skinningQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class UsdSkelSkinningQuery
const VtTokenArray& blendShapeOrder,
const UsdAttribute& jointIndices,
const UsdAttribute& jointWeights,
const UsdAttribute& skinningMethod,
const UsdAttribute& geomBindTransform,
const UsdAttribute& joints,
const UsdAttribute& blendShapes,
Expand Down Expand Up @@ -100,6 +101,10 @@ class UsdSkelSkinningQuery
USDSKEL_API
bool IsRigidlyDeformed() const;

const UsdAttribute& GetSkinningMethodAttr() const {
return _skinningMethodAttr;
}

const UsdAttribute& GetGeomBindTransformAttr() const {
return _geomBindTransformAttr;
}
Expand Down Expand Up @@ -190,7 +195,8 @@ class UsdSkelSkinningQuery
VtFloatArray* weights,
UsdTimeCode time=UsdTimeCode::Default()) const;

/// Compute skinned points using linear blend skinning.
/// Compute skinned points using specified skinning method attr
/// (fallback to linear blend skinning if not specified)
/// Both \p xforms and \p points are given in _skeleton space_,
/// using the joint order of the bound skeleton.
/// Joint influences and the (optional) binding transform are computed
Expand All @@ -203,7 +209,8 @@ class UsdSkelSkinningQuery
VtVec3fArray* points,
UsdTimeCode time=UsdTimeCode::Default()) const;

/// Compute skinned normals using linear blend skinning.
/// Compute skinned normals using specified skinning method attr
/// (fallback to linear blend skinning if not specified)
/// Both \p xforms and \p points are given in _skeleton space_,
/// using the joint order of the bound skeleton.
/// Joint influences and the (optional) binding transform are computed
Expand All @@ -216,7 +223,8 @@ class UsdSkelSkinningQuery
VtVec3fArray* points,
UsdTimeCode time=UsdTimeCode::Default()) const;

/// Compute a skinning transform using linear blend skinning.
/// Compute a skinning transform using specified skinning method attr
/// (fallback to linear blend skinning if not specified)
/// The \p xforms are given in _skeleton space_, using the joint order of
/// the bound skeleton.
/// Joint influences and the (optional) binding transform are computed
Expand All @@ -242,6 +250,9 @@ class UsdSkelSkinningQuery
float ComputeExtentsPadding(const VtArray<Matrix4>& skelRestXforms,
const UsdGeomBoundable& boundable) const;

USDSKEL_API
TfToken GetSkinningMethod() const;

USDSKEL_API
GfMatrix4d
GetGeomBindTransform(UsdTimeCode time=UsdTimeCode::Default()) const;
Expand All @@ -266,6 +277,7 @@ class UsdSkelSkinningQuery

UsdGeomPrimvar _jointIndicesPrimvar;
UsdGeomPrimvar _jointWeightsPrimvar;
UsdAttribute _skinningMethodAttr;
UsdAttribute _geomBindTransformAttr;
UsdAttribute _blendShapes;
UsdRelationship _blendShapeTargets;
Expand Down
19 changes: 19 additions & 0 deletions pxr/usd/usdSkel/testenv/testUsdSkelBakeSkinning.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@

class TestUsdSkelBakeSkinning(unittest.TestCase):

def test_DQSkinning(self):
testFile = "dqs.usda"
stage = Usd.Stage.Open(testFile)

self.assertTrue(UsdSkel.BakeSkinning(stage.Traverse()))

stage.GetRootLayer().Export("dqs.baked.usda")


def test_DQSkinningWithInterval(self):
testFile = "dqs.usda"
stage = Usd.Stage.Open(testFile)

self.assertTrue(UsdSkel.BakeSkinning(
stage.Traverse(), Gf.Interval(1, 10)))

stage.GetRootLayer().Export("dqs.bakedInterval.usda")


def test_LinearBlendSkinning(self):
testFile = "lbs.usda"
stage = Usd.Stage.Open(testFile)
Expand Down
Loading

0 comments on commit 769c060

Please sign in to comment.