From fd091069468692f8310b968ab3a8b8c5195bdcda Mon Sep 17 00:00:00 2001 From: tgvarik Date: Wed, 22 Feb 2023 22:25:26 -0800 Subject: [PATCH] [UsdImaging] GetInstanceCategories should get categories for all instances Prior version did not work for nested instancing. It only fetched categories for the immediate instancer and, when nested, would prepend one or more empty category lists, confounding indexing. This change uses the existing visitor (_RunForAllInstancesToDraw) to collect category lists for the full instance hierarchy. Fixes #2002 (Internal change: 2264225) --- pxr/imaging/hd/unitTestNullRenderDelegate.cpp | 29 +++++++++ pxr/usdImaging/usdImaging/instanceAdapter.cpp | 59 +++++++++++++++---- pxr/usdImaging/usdImaging/instanceAdapter.h | 1 + 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/pxr/imaging/hd/unitTestNullRenderDelegate.cpp b/pxr/imaging/hd/unitTestNullRenderDelegate.cpp index e1a5325e2c..1d22c2a91e 100644 --- a/pxr/imaging/hd/unitTestNullRenderDelegate.cpp +++ b/pxr/imaging/hd/unitTestNullRenderDelegate.cpp @@ -25,6 +25,7 @@ #include "pxr/imaging/hd/bufferArray.h" #include "pxr/imaging/hd/camera.h" #include "pxr/imaging/hd/coordSys.h" +#include "pxr/imaging/hd/light.h" #include "pxr/imaging/hd/material.h" #include "pxr/imaging/hd/mesh.h" #include "pxr/imaging/hd/basisCurves.h" @@ -235,6 +236,29 @@ class Hd_NullMaterial final : public HdMaterial { Hd_NullMaterial &operator =(const Hd_NullMaterial &) = delete; }; +class Hd_NullLight final : public HdLight { +public: + Hd_NullLight(SdfPath const& id) : HdLight(id) {} + virtual ~Hd_NullLight() = default; + + virtual void Sync(HdSceneDelegate *sceneDelegate, + HdRenderParam *renderParam, + HdDirtyBits *dirtyBits) override + { + *dirtyBits = HdLight::Clean; + } + + virtual HdDirtyBits GetInitialDirtyBitsMask() const override + { + return HdLight::AllDirty; + } + +private: + Hd_NullLight() = delete; + Hd_NullLight(const Hd_NullLight &) = delete; + Hd_NullLight &operator =(const Hd_NullLight &) = delete; +}; + class Hd_NullCoordSys final : public HdCoordSys { public: Hd_NullCoordSys(SdfPath const& id) : HdCoordSys(id) {} @@ -290,6 +314,7 @@ const TfTokenVector Hd_UnitTestNullRenderDelegate::SUPPORTED_SPRIM_TYPES = { HdPrimTypeTokens->camera, HdPrimTypeTokens->coordSys, + HdPrimTypeTokens->domeLight, HdPrimTypeTokens->material }; @@ -369,6 +394,8 @@ Hd_UnitTestNullRenderDelegate::CreateSprim(TfToken const& typeId, { if (typeId == HdPrimTypeTokens->material) { return new Hd_NullMaterial(sprimId); + } else if (typeId == HdPrimTypeTokens->domeLight) { + return new Hd_NullLight(SdfPath::EmptyPath()); } else if (typeId == HdPrimTypeTokens->coordSys) { return new Hd_NullCoordSys(sprimId); } else if (typeId == HdPrimTypeTokens->camera) { @@ -384,6 +411,8 @@ Hd_UnitTestNullRenderDelegate::CreateFallbackSprim(TfToken const& typeId) { if (typeId == HdPrimTypeTokens->material) { return new Hd_NullMaterial(SdfPath::EmptyPath()); + } else if (typeId == HdPrimTypeTokens->domeLight) { + return new Hd_NullLight(SdfPath::EmptyPath()); } else if (typeId == HdPrimTypeTokens->coordSys) { return new Hd_NullCoordSys(SdfPath::EmptyPath()); } else if (typeId == HdPrimTypeTokens->camera) { diff --git a/pxr/usdImaging/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/usdImaging/instanceAdapter.cpp index 2b30d1d8d5..51b47ceb05 100644 --- a/pxr/usdImaging/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/usdImaging/instanceAdapter.cpp @@ -1541,21 +1541,60 @@ UsdImagingInstanceAdapter::MarkVisibilityDirty(UsdPrim const& prim, } } +struct UsdImagingInstanceAdapter::_GetInstanceCategoriesFn +{ + _GetInstanceCategoriesFn( + const UsdImagingInstanceAdapter* adapter, + const UsdImaging_CollectionCache* cc, + std::vector* result) : + _adapter(adapter), + _cc(cc), + _result(result) + { } + + void Initialize(size_t numInstances) + { + _result->resize(numInstances); + } + + bool operator()(const std::vector& ctx, size_t idx) + { + // We must query the collections cache using the instance's stage path, + // not its proxy path. _GetStagePath() reconstructs the stage path + // from the instancing context.) + const SdfPath& path = _GetStagePath(ctx); + if (path.IsEmpty()) { + return false; + } + _result->at(idx) = _cc->ComputeCollectionsContainingPath(path); + return true; + } + + SdfPath _GetStagePath(const std::vector& ctx) + { + SdfPathVector chain; + chain.reserve(ctx.size()); + for (const UsdPrim& prim : ctx) { + chain.push_back(prim.GetPath()); + } + return _adapter->_GetPrimPathFromInstancerChain(chain); + } + + const UsdImagingInstanceAdapter* _adapter; + const UsdImaging_CollectionCache* _cc; + std::vector* _result; +}; + /*virtual*/ std::vector> UsdImagingInstanceAdapter::GetInstanceCategories(UsdPrim const& prim) { HD_TRACE_FUNCTION(); - std::vector> categories; - if (const _InstancerData* instancerData = - TfMapLookupPtr(_instancerData, prim.GetPath())) { - UsdImaging_CollectionCache& cc = _GetCollectionCache(); - categories.reserve(instancerData->instancePaths.size()); - for (SdfPath const& p: instancerData->instancePaths) { - categories.push_back(cc.ComputeCollectionsContainingPath(p)); - } - } - return categories; + const UsdImaging_CollectionCache& cc = _GetCollectionCache(); + std::vector result; + _GetInstanceCategoriesFn catsFn(this, &cc, &result); + _RunForAllInstancesToDraw(prim, &catsFn); + return result; } /*virtual*/ diff --git a/pxr/usdImaging/usdImaging/instanceAdapter.h b/pxr/usdImaging/usdImaging/instanceAdapter.h index 153f1c6b14..6fb5de4e94 100644 --- a/pxr/usdImaging/usdImaging/instanceAdapter.h +++ b/pxr/usdImaging/usdImaging/instanceAdapter.h @@ -460,6 +460,7 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter struct _PopulateInstanceSelectionFn; struct _GetScenePrimPathsFn; + struct _GetInstanceCategoriesFn; // Helper functions for dealing with "actual" instances to be drawn. //