Skip to content

Commit

Permalink
Adding UsdImagingPrimAdapter::ShouldIgnoreNativeInstanceSubtrees(), w…
Browse files Browse the repository at this point in the history
…hich allows

an adapter to disable instancing of itself and its descendants.
This is used by UsdSkelImagingSkelRootAdapter to cause instancing to be ignored
beneath SkelRoot prims. Using this, users are able to construct scenes that
take advantage of instancing in UsdSkel (benefiting from deduplication of
USD scene graph), while allowing imaging to continue to work.
This does not implement imaging support in the way we would like, but
at least allows some benefits of instancing to be realized while waiting
for an architecture that allows for proper bind-state instancing.

Fixing bug in UsdSkelImagingSkelRootAdapter where bindings were discovered
without respecting the delegate's prim predicate.

Adding `predicate` flag to Populate, ComputeBinding and ComputeBindings
methods of UsdSkelCache. All args take UsdPrimDefaultPredicate by default,
for backwards-compatibility.

Updating relevant code sites that call ComputeBinding/ComputeBindings
to traverse instance proxies.

Adding missing python bindings for UsdSkelSkinningQuery::GetBlendShapeOrder

(Internal change: 2090395)
  • Loading branch information
sgustafso authored and pixar-oss committed Aug 12, 2020
1 parent ae3b8f9 commit 08ceaf5
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 143 deletions.
10 changes: 6 additions & 4 deletions pxr/usd/usdSkel/bakeSkinning.cpp
Expand Up @@ -2445,9 +2445,10 @@ UsdSkelBakeSkinning(const UsdPrimRange& range, const GfInterval& interval)
it->GetPath().GetText());

const UsdSkelRoot skelRoot(*it);
skelCache.Populate(skelRoot);
skelCache.Populate(skelRoot, UsdPrimDefaultPredicate);

if (skelCache.ComputeSkelBindings(skelRoot, &bindings)) {
if (skelCache.ComputeSkelBindings(
skelRoot, &bindings, UsdPrimDefaultPredicate)) {
parms.bindings.insert(parms.bindings.end(),
bindings.begin(), bindings.end());
}
Expand Down Expand Up @@ -2488,9 +2489,10 @@ UsdSkelBakeSkinning(const UsdSkelRoot& skelRoot, const GfInterval& interval)
skelRoot.GetPrim().GetPath().GetText());

UsdSkelCache skelCache;
skelCache.Populate(skelRoot);
skelCache.Populate(skelRoot, UsdPrimDefaultPredicate);

if (skelCache.ComputeSkelBindings(skelRoot, &parms.bindings)) {
if (skelCache.ComputeSkelBindings(
skelRoot, &parms.bindings, UsdPrimDefaultPredicate)) {
if (parms.bindings.empty()) {
// Nothing to do.
return true;
Expand Down
34 changes: 13 additions & 21 deletions pxr/usd/usdSkel/cache.cpp
Expand Up @@ -36,12 +36,11 @@

#include "pxr/base/arch/hints.h"


PXR_NAMESPACE_OPEN_SCOPE


UsdSkelCache::UsdSkelCache(bool includeInstances)
: _impl(new UsdSkel_CacheImpl), _includeInstances(includeInstances)
UsdSkelCache::UsdSkelCache()
: _impl(new UsdSkel_CacheImpl)
{}

void
Expand Down Expand Up @@ -80,10 +79,10 @@ UsdSkelCache::GetSkelQuery(const UsdSkelSkeleton& skel) const


bool
UsdSkelCache::Populate(const UsdSkelRoot& root)
UsdSkelCache::Populate(const UsdSkelRoot& root,
Usd_PrimFlagsPredicate predicate) const
{
return UsdSkel_CacheImpl::ReadScope(_impl.get()).Populate(root,
_includeInstances);
return UsdSkel_CacheImpl::ReadScope(_impl.get()).Populate(root, predicate);
}


Expand All @@ -108,7 +107,8 @@ struct _CompareSkels

bool
UsdSkelCache::ComputeSkelBindings(const UsdSkelRoot& skelRoot,
std::vector<UsdSkelBinding>* bindings) const
std::vector<UsdSkelBinding>* bindings,
Usd_PrimFlagsPredicate predicate) const
{
TRACE_FUNCTION();

Expand Down Expand Up @@ -138,13 +138,9 @@ UsdSkelCache::ComputeSkelBindings(const UsdSkelRoot& skelRoot,
// This is done to handle inherited skel:skeleton bindings.

std::vector<UsdSkelSkeleton> skelStack(1);

Usd_PrimFlagsPredicate pred(UsdPrimDefaultPredicate);
if (_includeInstances) {
pred.TraverseInstanceProxies(true);
}

const auto range = UsdPrimRange::PreAndPostVisit(
skelRoot.GetPrim(), pred);
skelRoot.GetPrim(), predicate);
for (auto it = range.begin(); it != range.end(); ++it) {

if (ARCH_UNLIKELY(!it->IsA<UsdGeomImageable>())) {
Expand Down Expand Up @@ -208,7 +204,8 @@ UsdSkelCache::ComputeSkelBindings(const UsdSkelRoot& skelRoot,
bool
UsdSkelCache::ComputeSkelBinding(const UsdSkelRoot& skelRoot,
const UsdSkelSkeleton& skel,
UsdSkelBinding* binding) const
UsdSkelBinding* binding,
Usd_PrimFlagsPredicate predicate) const
{
TRACE_FUNCTION();

Expand All @@ -227,21 +224,16 @@ UsdSkelCache::ComputeSkelBinding(const UsdSkelRoot& skelRoot,
return false;
}


// Traverse over the prims beneath the skelRoot.
// While traversing, we maintain a stack of 'bound' skeletons,
// and map the last item on the stack to descendant prims.
// This is done to handle inherited skel:skeleton bindings.
// This is done to handle inherited skel bindings.

std::vector<UsdSkelSkeleton> skelStack(1);
VtArray<UsdSkelSkinningQuery> skinningQueries;

Usd_PrimFlagsPredicate pred(UsdPrimDefaultPredicate);
if (_includeInstances) {
pred.TraverseInstanceProxies(true);
}
const auto range = UsdPrimRange::PreAndPostVisit(
skelRoot.GetPrim(), pred);
skelRoot.GetPrim(), predicate);
for (auto it = range.begin(); it != range.end(); ++it) {

if (ARCH_UNLIKELY(!it->IsA<UsdGeomImageable>())) {
Expand Down
58 changes: 35 additions & 23 deletions pxr/usd/usdSkel/cache.h
Expand Up @@ -30,6 +30,7 @@
#include "pxr/usd/usdSkel/api.h"

#include "pxr/usd/usd/prim.h"
#include "pxr/usd/usd/primFlags.h"

#include "pxr/usd/usdSkel/animQuery.h"
#include "pxr/usd/usdSkel/binding.h"
Expand All @@ -49,31 +50,37 @@ class UsdSkelSkinningQuery;
TF_DECLARE_REF_PTRS(UsdSkelBinding);


/// \class UsdSkelCache
///
/// Thread-safe cache for accessing query objects for evaluating skeletal data.
///
/// This provides caching of major structural components, such as skeletal
/// topology.
/// In a streaming context, this cache is intended to persist.
/// topology. In a streaming context, this cache is intended to persist.
class UsdSkelCache
{
public:
USDSKEL_API
UsdSkelCache(bool includeInstances=false);
UsdSkelCache();

USDSKEL_API
void Clear();

/// Populate the cache for the skeletal data beneath prim \p root.
/// Populate the cache for the skeletal data beneath prim \p root,
/// as traversed using \p predicate.
///
/// Population resolves inherited skel bindings set using the
/// UsdSkelBindingAPI, making resolved bindings available through
/// GetSkinningQuery(), ComputeSkelBdining() and ComputeSkelBindings().
USDSKEL_API
bool Populate(const UsdSkelRoot& root);
bool Populate(const UsdSkelRoot& root,
Usd_PrimFlagsPredicate predicate) const;

/// Get a skel query for computing properties of \p skel.
///
/// This does not require Populate() to be called on the cache.
USDSKEL_API
UsdSkelSkeletonQuery GetSkelQuery(const UsdSkelSkeleton& skel) const;

/// Get an anim query corresponding to \p anim.
///
/// This does not require Populate() to be called on the cache.
USDSKEL_API
UsdSkelAnimQuery GetAnimQuery(const UsdSkelAnimation& anim) const;
Expand All @@ -83,40 +90,45 @@ class UsdSkelCache
USDSKEL_API
UsdSkelAnimQuery GetAnimQuery(const UsdPrim& prim) const;

/// Get a skinning query at \p prim. Skinning queries are defined at any
/// skinnable prims (I.e., boundable prims with fully defined joint
/// influences).
/// Get a skinning query at \p prim.
///
/// Skinning queries are defined at any skinnable prims (I.e., boundable
/// prims with fully defined joint influences).
///
/// The caller must first Populate() the cache with the skel root containing
/// \p prim in order for any skinning queries to be discoverabble.
/// \p prim, with a predicate that will visit \p prim, in order for a
/// skinning query to be discoverable.
USDSKEL_API
UsdSkelSkinningQuery GetSkinningQuery(const UsdPrim& prim) const;

/// Compute the set of skeleton bindings beneath \p skelRoot.
/// Compute the set of skeleton bindings beneath \p skelRoot,
/// as discovered through a traversal using \p predicate.
///
/// Skinnable prims are only discoverable by this method if Populate()
/// has already been called for \p skelRoot, with an equivalent predicate.
USDSKEL_API
bool ComputeSkelBindings(const UsdSkelRoot& skelRoot,
std::vector<UsdSkelBinding>* bindings) const;
std::vector<UsdSkelBinding>* bindings,
Usd_PrimFlagsPredicate predicate) const;

/// Compute the bindings corresponding to a single skeleton,
/// bound beneath \p skelRoot.
/// Compute the bindings corresponding to a single skeleton, bound beneath
/// \p skelRoot, as discovered through a traversal using \p predicate.
///
/// Skinnable prims are only discoverable by this method if Populate()
/// has already been called for \p skelRoot, with an equivalent predicate.
USDSKEL_API
bool ComputeSkelBinding(const UsdSkelRoot& skelRoot,
const UsdSkelSkeleton& skel,
UsdSkelBinding* binding) const;

/// Does this cache include instances?
USDSKEL_API
bool IncludesInstances() const { return _includeInstances; }
UsdSkelBinding* binding,
Usd_PrimFlagsPredicate predicate) const;

private:
std::shared_ptr<class UsdSkel_CacheImpl> _impl;
bool _includeInstances;


friend class UsdSkelAnimQuery;
friend class UsdSkelSkeletonQuery;
};


PXR_NAMESPACE_CLOSE_SCOPE

#endif // USDSKEL_EVALCACHE_H
62 changes: 40 additions & 22 deletions pxr/usd/usdSkel/cacheImpl.cpp
Expand Up @@ -37,10 +37,8 @@
#include "pxr/usd/usdSkel/root.h"
#include "pxr/usd/usdSkel/utils.h"


PXR_NAMESPACE_OPEN_SCOPE


// ------------------------------------------------------------
// UsdSkel_CacheImpl::WriteScope
// ------------------------------------------------------------
Expand Down Expand Up @@ -203,12 +201,34 @@ _DeprecatedBindingCheck(bool hasBindingAPI, const UsdProperty& prop)
}
}

/// If \p attr is an attribute on an instance proxy, return the attr on the
/// instance master. Otherwise return the original attr.
UsdAttribute
_GetAttrInMaster(const UsdAttribute& attr)
{
if (attr && attr.GetPrim().IsInstanceProxy()) {
return attr.GetPrim().GetPrimInMaster().GetAttribute(attr.GetName());
}
return attr;
}

/// If \p rel is an attribute on an instance proxy, return the rel on the
/// instance master. Otherwise return the original rel.
UsdRelationship
_GetRelInMaster(const UsdRelationship& rel)
{
if (rel && rel.GetPrim().IsInstanceProxy()) {
return rel.GetPrim().GetPrimInMaster().GetRelationship(rel.GetName());
}
return rel;
}

} // namespace


bool
UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,
bool includeInstanceable)
Usd_PrimFlagsPredicate predicate)
{
TRACE_FUNCTION();

Expand All @@ -222,12 +242,8 @@ UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,

std::vector<std::pair<_SkinningQueryKey,UsdPrim> > stack(1);

Usd_PrimFlagsPredicate pred(UsdPrimDefaultPredicate);
if (includeInstanceable) {
pred.TraverseInstanceProxies(true);
}
const UsdPrimRange range =
UsdPrimRange::PreAndPostVisit(root.GetPrim(), pred);
UsdPrimRange::PreAndPostVisit(root.GetPrim(), predicate);

for (auto it = range.begin(); it != range.end(); ++it) {

Expand Down Expand Up @@ -260,38 +276,40 @@ UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,

UsdSkelSkeleton skel;
if (binding.GetSkeleton(&skel)) {
key.skel = skel.GetPrim();
if (key.skel.IsInstanceProxy()) {
key.skel = key.skel.GetPrimInMaster();
}
key.skel = !skel.GetPrim().IsInstanceProxy() ?
skel.GetPrim() : skel.GetPrim().GetPrimInMaster();
}

// XXX: When looking for binding properties, only include
// properties that have an authored value. Properties with
// no authored value are treated as if they do not exist.

if (UsdAttribute attr = binding.GetJointIndicesAttr()) {
if (UsdAttribute attr = _GetAttrInMaster(
binding.GetJointIndicesAttr())) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.jointIndicesAttr = std::move(attr);
}
}

if (UsdAttribute attr = binding.GetJointWeightsAttr()) {
if (UsdAttribute attr = _GetAttrInMaster(
binding.GetJointWeightsAttr())) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.jointWeightsAttr = std::move(attr);
}
}

if (UsdAttribute attr = binding.GetGeomBindTransformAttr()) {
if (UsdAttribute attr = _GetAttrInMaster(
binding.GetGeomBindTransformAttr())) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.geomBindTransformAttr = std::move(attr);
}
}

if (UsdAttribute attr = binding.GetJointsAttr()) {
if (UsdAttribute attr = _GetAttrInMaster(
binding.GetJointsAttr())) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.jointsAttr = std::move(attr);
Expand All @@ -304,15 +322,16 @@ UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,
// skel:blendShapeTargets are *not* inherited, so we only check
// for them on skinnable prims.
if (isSkinnable) {
if (UsdAttribute attr = binding.GetBlendShapesAttr()) {
if (UsdAttribute attr = _GetAttrInMaster(
binding.GetBlendShapesAttr())) {
if (attr.HasAuthoredValue()) {
_DeprecatedBindingCheck(hasBindingAPI, attr);
key.blendShapesAttr = std::move(attr);
}
}

if (UsdRelationship rel =
binding.GetBlendShapeTargetsRel()) {
if (UsdRelationship rel = _GetRelInMaster(
binding.GetBlendShapeTargetsRel())) {
if (rel.HasAuthoredTargets()) {
_DeprecatedBindingCheck(hasBindingAPI, rel);
key.blendShapeTargetsRel = std::move(rel);
Expand All @@ -333,14 +352,13 @@ UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root,
_MakeIndent(stack.size()).c_str(),
it->GetPath().GetText());

// TODO: How should nested skinnable primitives be handled?
// Should we prune traversal at this point?
// Don't allow skinnable prims to be nested.
it.PruneChildren();
}

stack.emplace_back(key, *it);
}
return true;
}


PXR_NAMESPACE_CLOSE_SCOPE
3 changes: 2 additions & 1 deletion pxr/usd/usdSkel/cacheImpl.h
Expand Up @@ -103,9 +103,10 @@ class UsdSkel_CacheImpl

/// Method for populating the cache with cache properties, for
/// the set of properties that depend on inherited state.
///
/// Returns true if any skinnable prims were populated.
bool Populate(const UsdSkelRoot& root,
bool includeInstanceable);
Usd_PrimFlagsPredicate predicate);

// Getters for properties added to the cache through Populate().

Expand Down

0 comments on commit 08ceaf5

Please sign in to comment.