diff --git a/Changes.md b/Changes.md index 03ab8116757..3af292d8281 100644 --- a/Changes.md +++ b/Changes.md @@ -23,6 +23,7 @@ Fixes - Fixed undo for image reordering via drag & drop. - Fixed bugs caused by reordering images using `GraphComponent::reorderChildren()`. - InteractiveRender : Fixed context used to evaluate scene globals when renderer is set to "Default" [^1]. +- Instancer : Fixed handling of unindexed primvars in RootPerVertex mode [^1]. API --- @@ -363,6 +364,7 @@ Fixes ----- - InteractiveRender : Fixed context used to evaluate scene globals when renderer is set to "Default". +- Instancer : Fixed handling of unindexed primvars in RootPerVertex mode. 1.3.14.0 (relative to 1.3.13.1) ======== diff --git a/python/GafferSceneTest/InstancerTest.py b/python/GafferSceneTest/InstancerTest.py index be44bf621fa..933b83257d6 100644 --- a/python/GafferSceneTest/InstancerTest.py +++ b/python/GafferSceneTest/InstancerTest.py @@ -1326,6 +1326,11 @@ def updateRoots( roots, indices ) : self.assertRootsMatchPrototypeSceneChildren( script ) self.assertEncapsulatedRendersSame( script["instancer"] ) + # We should be able to get the same result with an un-indexed primvar + updateRoots( IECore.StringVectorData( [ "/foo", "/bar", "/bar", "/foo" ] ), None ) + self.assertRootsMatchPrototypeSceneChildren( script ) + self.assertEncapsulatedRendersSame( script["instancer"] ) + updateRoots( IECore.StringVectorData( [ "/foo/bar", "/bar" ] ), IECore.IntVectorData( [ 0, 1, 1, 0 ] ) ) self.assertConflictingRootNames( script ) self.assertEncapsulatedRendersSame( script["instancer"] ) @@ -2201,18 +2206,10 @@ def quant( x, q ): self.assertEncapsulatedRendersSame( instancer ) instancer["prototypeRoots"].setValue( "unindexedRoots" ) - """ - # How things should work self.assertEqual( uniqueCounts(), { "" : 3 } ) self.assertEqual( childNameStrings( "points/instances/cube" ), [ str(i) for i in range( 0, 34 ) ] ) self.assertEqual( childNameStrings( "points/instances/plane" ), [ str(i) for i in range( 34, 68 ) ] ) self.assertEqual( childNameStrings( "points/instances/sphere" ), [ str(i) for i in range( 68, 100 ) ] ) - """ - # How things currently work - self.assertEqual( uniqueCounts(), { "" : 1 } ) - self.assertEqual( childNameStrings( "points/instances/cube" ), [ str(i) for i in range( 100 ) ] ) - self.assertEqual( childNameStrings( "points/instances/plane" ), [] ) - self.assertEqual( childNameStrings( "points/instances/sphere" ), [] ) self.assertEncapsulatedRendersSame( instancer ) diff --git a/src/GafferScene/Instancer.cpp b/src/GafferScene/Instancer.cpp index 158df7ede80..b4fb4c7946c 100644 --- a/src/GafferScene/Instancer.cpp +++ b/src/GafferScene/Instancer.cpp @@ -816,6 +816,7 @@ class Instancer::EngineData : public Data void initPrototypes( PrototypeMode mode, const std::string &prototypeIndex, const std::string &rootsVariable, const StringVectorData *rootsList, const ScenePlug *prototypes ) { const std::vector *rootStrings = nullptr; + std::vector rootStringsAlloc; switch( mode ) { @@ -879,6 +880,28 @@ class Instancer::EngineData : public Data m_prototypeIndices = view->indices(); rootStrings = &view->data(); + + if( !m_prototypeIndices ) + { + std::unordered_map duplicateRootMap; + + m_prototypeIndicesAlloc.reserve( rootStrings->size() ); + for( const std::string &i : *rootStrings ) + { + auto insertResult = duplicateRootMap.try_emplace( i, rootStringsAlloc.size() ); + if( insertResult.second ) + { + m_prototypeIndicesAlloc.push_back( rootStringsAlloc.size() ); + rootStringsAlloc.push_back( i ); + } + else + { + m_prototypeIndicesAlloc.push_back( insertResult.first->second ); + } + } + rootStrings = &rootStringsAlloc; + m_prototypeIndices = &m_prototypeIndicesAlloc; + } break; } } @@ -933,6 +956,7 @@ class Instancer::EngineData : public Data Private::ChildNamesMapPtr m_names; std::vector m_roots; std::vector m_prototypeIndexRemap; + std::vector m_prototypeIndicesAlloc; const std::vector *m_prototypeIndices; const std::vector *m_ids; const std::vector *m_positions;