Skip to content

Commit

Permalink
[Hd, UsdImaging] Replace the GetPrimPathForInstanceIndex API with Get…
Browse files Browse the repository at this point in the history
…ScenePrimPath.

GetPrimPathForInstanceIndex returned the instancer of a given rprim, or a null path if there was no instancer.  Most callers of it were expecting it to return the USD prim path to the rprim, and so it was returning the wrong results.

GetScenePrimPath returns the USD prim path of an rprim, as expected by calling code.  It also does the work of turning prims-in-master into instance proxies, which some client code was trying to do itself.

This also fixes up some long-running issues with delegateID-prefixed paths leaking into app code.

To support these changes, the UsdImagingGLEngine picking API has been updated:
- TestIntersection returns a pre-resolved (via GetScenePrimPath) USD prim path, rather than a hydra rprim path.
- GetRprimPathFromPrimId, GetPrimPathFromPrimIdColor, GetPrimPathFromInstanceIndex, and DecodeIDRenderColor have been deleted.
- A new function has been added: DecodeIntersection does the same path resolution as TestIntersection, but given a prim ID/instance ID from an ID render (needed by usdscenemetrics).
- The "element ID" (unsupported) and "worldToLocal" transform (unused) have been deleted.

(Internal change: 2051666)
  • Loading branch information
tcauchois authored and pixar-oss committed Mar 30, 2020
1 parent 8d85700 commit 82e343c
Show file tree
Hide file tree
Showing 20 changed files with 318 additions and 732 deletions.
9 changes: 3 additions & 6 deletions pxr/imaging/hd/sceneDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,10 @@ HdSceneDelegate::SampleInstancerTransform(SdfPath const &instancerId,

/*virtual*/
SdfPath
HdSceneDelegate::GetPathForInstanceIndex(const SdfPath &protoRprimId,
int protoIndex,
int *instancerIndex,
SdfPath *masterCachePath,
SdfPathVector *instanceContext)
HdSceneDelegate::GetScenePrimPath(SdfPath const& rprimId,
int instanceIndex)
{
return SdfPath();
return rprimId;
}


Expand Down
72 changes: 8 additions & 64 deletions pxr/imaging/hd/sceneDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -570,71 +570,15 @@ class HdSceneDelegate {
HD_API
virtual GfMatrix4d GetInstancerTransform(SdfPath const &instancerId);

// -----------------------------------------------------------------------//
/// \name Path Translation
// -----------------------------------------------------------------------//

/// Resolves a \p protoRprimId and \p protoIndex back to original
/// instancer path by backtracking nested instancer hierarchy.
///
/// It will be an empty path if the given protoRprimId is not
/// instanced.
///
/// (Note: see usdImaging/delegate.h for details specific to USD
/// instancing)
///
/// If the instancer instances heterogeneously, the instance index of the
/// prototype rprim doesn't match the instance index in the instancer.
///
/// For example, if we have:
///
/// instancer {
/// prototypes = [ A, B, A, B, B ]
/// }
///
/// ...then the indices would be:
///
/// protoIndex instancerIndex
/// A: [0, 1] [0, 2]
/// B: [0, 1, 2] [1, 3, 5]
///
/// To track this mapping, the \p instancerIndex is returned which
/// corresponds to the given protoIndex.
///
/// Also, note if there are nested instancers, the returned path will
/// be the top-level instancer, and the \p instancerIndex will be for
/// that top-level instancer. This can lead to situations where, contrary
/// to the previous scenario, the instancerIndex has fewer possible values
/// than the \p protoIndex:
///
/// For example, if we have:
///
/// instancerBottom {
/// prototypes = [ A, A, B ]
/// }
/// instancerTop {
/// prototypes = [ instancerBottom, instancerBottom ]
/// }
///
/// ...then the indices might be:
///
/// protoIndex instancerIndex (for instancerTop)
/// A: [0, 1, 2, 3] [0, 0, 1, 1]
/// B: [0, 1] [0, 1]
///
/// because \p instancerIndex are indices for instancerTop, which only has
/// two possible indices.
///
/// If \p masterCachePath is not NULL, then it may be set to the cache path
/// corresponding instance master prim, if there is one. Otherwise, it will
/// be set to null.
///
/// If \p instanceContext is not NULL, it is populated with the list of
/// instance roots that must be traversed to get to the rprim. If this
/// list is non-empty, the last prim is always the forwarded rprim.
HD_API
virtual SdfPath GetPathForInstanceIndex(const SdfPath &protoRprimId,
int protoIndex,
int *instancerIndex,
SdfPath *masterCachePath=NULL,
SdfPathVector *instanceContext=NULL);
/// Returns the scene address of the prim corresponding to the given
/// rprim/instance index.
HD_API
virtual SdfPath GetScenePrimPath(SdfPath const& rprimId,
int instanceIndex);

// -----------------------------------------------------------------------//
/// \name Material Aspects
Expand Down
3 changes: 2 additions & 1 deletion pxr/imaging/hd/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
// 29 -> 30: added IDRenderColor decode and direct Rprim path fetching.
// 30 -> 31: added pre-chained buffer sources
// 31 -> 32: renamed HdShader{Param} to HdMaterial{Param}
#define HD_API_VERSION 32
// 32 -> 33: Deleted GetPathForInstanceIndex; added GetScenePrimPath.
#define HD_API_VERSION 33

// 1 -> 2: SimpleLighting -> FallbackLighting
#define HD_SHADER_API 2
Expand Down
4 changes: 0 additions & 4 deletions pxr/imaging/hdx/unitTestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ _ProcessHit(AggregatedHit const& aHit,

std::cout << "Picked instance " << instanceIndex << " of "
<< "rprim " << hit.objectId << std::endl;

// we should use GetPathForInstanceIndex instead of it->objectId
//SdfPath path = _delegate->GetPathForInstanceIndex(it->objectId, it->instanceIndex);
// and also need to add some APIs to compute VtIntArray instanceIndex.
} else {
selection->AddRprim(highlightMode, hit.objectId);

Expand Down
75 changes: 14 additions & 61 deletions pxr/usdImaging/usdImaging/delegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1998,72 +1998,25 @@ UsdImagingDelegate::SetRootVisibility(bool isVisible)
}

SdfPath
UsdImagingDelegate::GetPathForInstanceIndex(const SdfPath &protoRprimId,
int protoIndex,
int *instancerIndex,
SdfPath *masterCachePath,
SdfPathVector *instanceContext)
UsdImagingDelegate::GetScenePrimPath(SdfPath const& rprimId,
int instanceIndex)
{
SdfPath cachePath = ConvertIndexPathToCachePath(protoRprimId);

TF_DEBUG(USDIMAGING_SELECTION).Msg(
"GetPathForInstanceIndex(%s, %d)\n",
cachePath.GetText(), protoIndex);

// resolve all instancer hierarchy.
int instanceCount = 0;
int origPrototypeIndex = protoIndex;
int resolvedInstancerIndex = ALL_INSTANCES; // PointInstancer may overwrite.
SdfPathVector resolvedInstanceContext;
SdfPath resolvedMasterCachePath;
do {
_HdPrimInfo *primInfo = _GetHdPrimInfo(cachePath);
if (!TF_VERIFY(primInfo, "%s\n", cachePath.GetText()) ||
!TF_VERIFY(primInfo->adapter, "%s\n", cachePath.GetText())) {
return ConvertCachePathToIndexPath(cachePath);
}

UsdImagingPrimAdapterSharedPtr const& adapter = primInfo->adapter;
cachePath = adapter->GetPathForInstanceIndex(
cachePath, protoIndex, &instanceCount, &resolvedInstancerIndex,
&resolvedMasterCachePath, &resolvedInstanceContext);

if (cachePath.IsEmpty()) {
break;
}

// reach to non-prototype node or native instancer's instance path.
if (instanceCount == 0) {
break;
}

// decode protoIndex to the next level
if (instanceCount > 0) {
protoIndex /= instanceCount;
}

} while(true);

TF_DEBUG(USDIMAGING_SELECTION).Msg("GetPathForInstanceIndex(%s, %d) = "
"(%s, %d, %s, %s)\n", protoRprimId.GetText(), origPrototypeIndex,
cachePath.GetText(), resolvedInstancerIndex,
resolvedMasterCachePath.GetText(),
resolvedInstanceContext.empty() ? "(empty)" :
resolvedInstanceContext.back().GetText());

if (instancerIndex) {
*instancerIndex = resolvedInstancerIndex;
SdfPath cachePath = ConvertIndexPathToCachePath(rprimId);
_HdPrimInfo *primInfo = _GetHdPrimInfo(cachePath);
if (!primInfo || !primInfo->adapter) {
TF_WARN("GetScenePrimPath: Couldn't find rprim <%s>",
rprimId.GetText());
return cachePath;
}

if (masterCachePath) {
*masterCachePath = resolvedMasterCachePath;
}
SdfPath protoPath = primInfo->adapter->GetScenePrimPath(
cachePath, instanceIndex);

if (instanceContext) {
*instanceContext = resolvedInstanceContext;
}
TF_DEBUG(USDIMAGING_SELECTION).Msg(
"GetScenePrimPath(%s, %d) = %s\n",
cachePath.GetText(), instanceIndex, protoPath.GetText());

return ConvertCachePathToIndexPath(cachePath);
return protoPath;
}

bool
Expand Down
75 changes: 8 additions & 67 deletions pxr/usdImaging/usdImaging/delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "pxr/pxr.h"
#include "pxr/usdImaging/usdImaging/api.h"
#include "pxr/usdImaging/usdImaging/version.h"
#include "pxr/usdImaging/usdImaging/collectionCache.h"
#include "pxr/usdImaging/usdImaging/valueCache.h"
#include "pxr/usdImaging/usdImaging/inheritedCache.h"
Expand Down Expand Up @@ -375,74 +376,13 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase {
virtual HdVolumeFieldDescriptorVector
GetVolumeFieldDescriptors(SdfPath const &volumeId) override;

// Instance path resolution

/// Resolves a \p protoRprimId and \p protoIndex back to original
/// instancer path by backtracking nested instancer hierarchy.
///
/// The "original instancer" is defined as the rprim corresponding to the
/// top-level instanceable reference prim or top-level PointInstancer prim.
/// It will be an empty path if the given protoRprimId is not
/// instanced.
///
/// If the instancer instances heterogeneously, the instance index of the
/// prototype rprim doesn't match the instance index in the instancer.
///
/// For example, if we have:
///
/// instancer {
/// prototypes = [ A, B, A, B, B ]
/// }
///
/// ...then the indices would be:
///
/// protoIndex instancerIndex
/// A: [0, 1] [0, 2]
/// B: [0, 1, 2] [1, 3, 5]
///
/// To track this mapping, the \p instancerIndex is returned which
/// corresponds to the given protoIndex. ALL_INSTANCES may be returned
/// if \p protoRprimId isn't instanced.
///
/// Also, note if there are nested instancers, the returned path will
/// be the top-level instancer, and the \p instancerIndex will be for
/// that top-level instancer. This can lead to situations where, contrary
/// to the previous scenario, the instancerIndex has fewer possible values
/// than the \p protoIndex:
///
/// For example, if we have:
///
/// instancerBottom {
/// prototypes = [ A, A, B ]
/// }
/// instancerTop {
/// prototypes = [ instancerBottom, instancerBottom ]
/// }
///
/// ...then the indices might be:
///
/// protoIndex instancerIndex (for instancerTop)
/// A: [0, 1, 2, 3] [0, 0, 1, 1]
/// B: [0, 1] [0, 1]
///
/// because \p instancerIndex are indices for instancerTop, which only has
/// two possible indices.
///
/// If \p masterCachePath is not NULL, and the input rprim is an instance
/// resulting from an instanceable reference (and not from a
/// PointInstancer), then it will be set to the cache path of the
/// corresponding instance master prim. Otherwise, it will be set to null.
///
/// If \p instanceContext is not NULL, it is populated with the list of
/// instance roots that must be traversed to get to the rprim. If this
/// list is non-empty, the last prim is always the forwarded rprim.
static constexpr int ALL_INSTANCES = -1;
// Picking path resolution
// Resolves a \p rprimId and \p instanceIndex back to the original USD
// gprim and instance index.
USDIMAGING_API
virtual SdfPath GetPathForInstanceIndex(const SdfPath &protoRprimId,
int protoIndex,
int *instancerIndex,
SdfPath *masterCachePath=NULL,
SdfPathVector *instanceContext=NULL) override;
virtual SdfPath
GetScenePrimPath(SdfPath const& rprimId,
int instanceIndex) override;

// ExtComputation support
USDIMAGING_API
Expand Down Expand Up @@ -518,6 +458,7 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase {
/// Populate HdxSelection for given \p path (root) and \p instanceIndex.
/// If indexPath is an instancer and instanceIndex is ALL_INSTANCES (-1),
/// all instances will be selected.
static constexpr int ALL_INSTANCES = -1;
USDIMAGING_API
bool PopulateSelection(HdSelection::HighlightMode const& highlightMode,
const SdfPath &usdPath,
Expand Down
Loading

0 comments on commit 82e343c

Please sign in to comment.