void UsdSkel_CacheImpl::ReadScope::_RecursivePopulate(const UsdPrim& prim, SkinningQueryKey key, UsdSkelAnimQuery animQuery, size_t depth) { if(!prim.IsA<UsdGeomImageable>()) { TF_DEBUG(USDSKEL_CACHE).Msg( "[UsdSkelCache]: %sPruning traversal at <%s> " "(prim types is not a UsdGeomImageable)\n", _MakeIndent(depth).c_str(), prim.GetPath().GetText()); return; } TF_DEBUG(USDSKEL_CACHE).Msg("[UsdSkelCache]: %sVisiting <%s>\n", _MakeIndent(depth).c_str(), prim.GetPath().GetText()); UsdSkelBindingAPI binding(prim); if(UsdRelationship rel = binding.GetAnimationSourceRel()) { SdfPathVector targets; if(rel.GetForwardedTargets(&targets)) { animQuery = FindOrCreateAnimQuery(_GetFirstTarget(rel, targets)); } } if(UsdRelationship rel = binding.GetSkeletonRel()) { SdfPathVector targets; if(rel.GetForwardedTargets(&targets)) { _PrimToSkelQueryMap::accessor a; if(_cache->_skelQueryCache.insert(a, prim)) { a->second = _FindOrCreateSkelQuery( _GetFirstTarget(rel, targets), animQuery); } key.skelQuery = a->second; TF_DEBUG(USDSKEL_CACHE).Msg( "[UsdSkelCache]: %sNew skeleton bound at <%s>: %s\n", _MakeIndent(depth).c_str(), prim.GetPath().GetText(), key.skelQuery.GetDescription().c_str()); } } if(UsdAttribute attr = binding.GetJointIndicesAttr()) key.jointIndicesAttr = attr; if(UsdAttribute attr = binding.GetJointWeightsAttr()) key.jointWeightsAttr = attr; if(UsdAttribute attr = binding.GetGeomBindTransformAttr()) key.geomBindTransformAttr = attr; if(UsdAttribute attr = binding.GetJointsAttr()) { VtTokenArray jointOrder; if(attr.Get(&jointOrder)) { key.jointOrder = jointOrder; } } if(prim.IsA<UsdGeomBoundable>() && (key.jointIndicesAttr && key.jointWeightsAttr)) { _PrimToSkinningQueryMap::accessor a; if(_cache->_primSkinningQueryCache.insert(a, prim)) { a->second = _FindOrCreateSkinningQuery(prim, key); } TF_DEBUG(USDSKEL_CACHE).Msg( "[UsdSkelCache]: %sFound skinnable prim <%s> (valid? %d)\n", _MakeIndent(depth).c_str(), prim.GetPath().GetText(), a->second.IsValid()); // Skinnable prims cannot be nested. return; } UsdPrim traversalPrim = !prim.IsInstance() ? prim : prim.GetMaster(); for(const auto& child : prim.GetChildren()) { _RecursivePopulate(child, key, animQuery, depth+1); } }
bool UsdSkel_CacheImpl::ReadScope::Populate(const UsdSkelRoot& root) { TRACE_FUNCTION(); TF_DEBUG(USDSKEL_CACHE).Msg("[UsdSkelCache] Populate map from <%s>\n", root.GetPrim().GetPath().GetText()); if(!root) { TF_CODING_ERROR("'root' is invalid."); return false; } std::vector<std::pair<SkinningQueryKey,UsdPrim> > stack(1); UsdPrimRange range = UsdPrimRange::PreAndPostVisit(root.GetPrim(), UsdPrimDefaultPredicate); // UsdPrimIsInstance); for (auto it = range.begin(); it != range.end(); ++it) { if (it.IsPostVisit()) { if (stack.size() > 0 && stack.back().second == *it) { stack.pop_back(); } continue; } if (ARCH_UNLIKELY(!it->IsA<UsdGeomImageable>())) { TF_DEBUG(USDSKEL_CACHE).Msg( "[UsdSkelCache] %sPruning traversal at <%s> " "(prim is not UsdGeomImageable)\n", _MakeIndent(stack.size()).c_str(), it->GetPath().GetText()); it.PruneChildren(); continue; } // TODO: Consider testing whether or not the API has been applied first. UsdSkelBindingAPI binding(*it); SkinningQueryKey key(stack.back().first); UsdSkelSkeleton skel; if (binding.GetSkeleton(&skel)) key.skel = skel.GetPrim(); if (UsdAttribute attr = binding.GetJointIndicesAttr()) key.jointIndicesAttr = attr; if (UsdAttribute attr = binding.GetJointWeightsAttr()) key.jointWeightsAttr = attr; if (UsdAttribute attr = binding.GetGeomBindTransformAttr()) key.geomBindTransformAttr = attr; if (UsdAttribute attr = binding.GetJointsAttr()) key.jointsAttr = attr; if (UsdAttribute attr = binding.GetBlendShapesAttr()) key.blendShapesAttr = attr; if (UsdRelationship rel = binding.GetBlendShapeTargetsRel()) key.blendShapeTargetsRel = rel; if (UsdSkelIsSkinnablePrim(*it)) { _PrimToSkinningQueryMap::accessor a; if (_cache->_primSkinningQueryCache.insert(a, *it)) { a->second = _FindOrCreateSkinningQuery(*it, key); } TF_DEBUG(USDSKEL_CACHE).Msg( "[UsdSkelCache] %sAdded skinning query for prim <%s>\n", _MakeIndent(stack.size()).c_str(), it->GetPath().GetText()); // TODO: How should nested skinnable primitives be handled? // Should we prune traversal at this point? } stack.emplace_back(key, *it); } return true; }