From 38a4b770a8e0484853ff7b31f38eadde5d742b84 Mon Sep 17 00:00:00 2001 From: Daniel Dresser Date: Mon, 28 Oct 2024 16:42:42 -0700 Subject: [PATCH] FIX : Instancer --- python/GafferSceneTest/InstancerTest.py | 11 +++++-- python/GafferSceneUI/InstancerUI.py | 3 ++ src/GafferScene/Instancer.cpp | 38 ++++++++++++++++++------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/python/GafferSceneTest/InstancerTest.py b/python/GafferSceneTest/InstancerTest.py index 9ac9139880a..0a2a213ca35 100644 --- a/python/GafferSceneTest/InstancerTest.py +++ b/python/GafferSceneTest/InstancerTest.py @@ -734,12 +734,16 @@ def testInactiveIds( self ) : ) points["inactiveIdsTest64"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Constant, - IECore.IntVectorData( [ 4, 6 ] ) + IECore.Int64VectorData( [ 4, 6 ] ) ) points["inactive"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.BoolVectorData( [ 0, 0, 1, 0, 0, 1, 1, 0, 1, 1 ] ) ) + points["inactiveInt"] = IECoreScene.PrimitiveVariable( + IECoreScene.PrimitiveVariable.Interpolation.Vertex, + IECore.IntVectorData( [ 0, 0, 1, 0, 0, 1, 1, 0, 1, 1 ] ) + ) points["badInactive"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Constant, IECore.IntVectorData( [ 13 ] ) @@ -762,7 +766,7 @@ def testInactiveIds( self ) : instancer["prototypes"].setInput( sphere["out"] ) instancer["filter"].setInput( pointsFilter["out"] ) - self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "%i" % i for i in range( 10 ) ] ) ) + self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ str( i ) for i in range( 10 ) ] ) ) instancer["inactiveIds"].setValue( "inactiveIdsTest" ) self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "2", "4", "6", "8", "9" ] ) ) @@ -773,6 +777,9 @@ def testInactiveIds( self ) : instancer["inactiveIds"].setValue( "inactive" ) self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "3", "4", "7" ] ) ) + instancer["inactiveIds"].setValue( "inactiveInt" ) + self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "3", "4", "7" ] ) ) + instancer["inactiveIds"].setValue( "inactiveIdsTest inactiveIdsTest64" ) self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "2", "8", "9" ] ) ) diff --git a/python/GafferSceneUI/InstancerUI.py b/python/GafferSceneUI/InstancerUI.py index 1ea282c7c9b..59c94586f42 100644 --- a/python/GafferSceneUI/InstancerUI.py +++ b/python/GafferSceneUI/InstancerUI.py @@ -559,6 +559,9 @@ def __init__( self, headings, toolTipOverride = "" ) : will deactivate the instance for the corresponding vertex if the value is true. """, + # This user default will pick up any of the standard USD ways of controlling this. + "userDefault", "inactiveIds invisibleIds", + "layout:section", "Settings.Inactive Ids", ], diff --git a/src/GafferScene/Instancer.cpp b/src/GafferScene/Instancer.cpp index 768cf2d60ac..15ab8535796 100644 --- a/src/GafferScene/Instancer.cpp +++ b/src/GafferScene/Instancer.cpp @@ -495,13 +495,14 @@ class Instancer::EngineData : public Data const PrimitiveVariable *vertexInactiveVar = findVertexVariable( m_primitive.get(), inactiveIdVarName ); if( vertexInactiveVar ) { + if( IECore::size( vertexInactiveVar->data.get() ) != numPoints() ) + { + throw IECore::Exception( fmt::format( "Inactive primitive variable \"{}\" has incorrect size", inactiveIdVarName ) ); + } + if( const auto *vertexInactiveData = IECore::runTimeCast( vertexInactiveVar->data.get() ) ) { const std::vector &vertexInactive = vertexInactiveData->readable(); - if( vertexInactive.size() != numPoints() ) - { - throw IECore::Exception( fmt::format( "Inactive primitive variable \"{}\" has incorrect size", inactiveIdVarName ) ); - } if( !m_indicesInactive.size() ) { @@ -515,7 +516,7 @@ class Instancer::EngineData : public Data } else { - for( unsigned int i = 0; i < vertexInactive.size(); i++ ) + for( size_t i = 0; i < vertexInactive.size(); i++ ) { if( vertexInactive[i] ) { @@ -523,9 +524,26 @@ class Instancer::EngineData : public Data } } } + } + else if( const auto *vertexInactiveIntData = IECore::runTimeCast( vertexInactiveVar->data.get() ) ) + { + const std::vector &vertexInactiveInt = vertexInactiveIntData->readable(); - continue; + if( !m_indicesInactive.size() ) + { + m_indicesInactive.resize( numPoints(), false ); + } + + for( size_t i = 0; i < vertexInactiveInt.size(); i++ ) + { + if( vertexInactiveInt[i] ) + { + m_indicesInactive[ i ] = true; + } + } } + + continue; } IdData idData; @@ -639,9 +657,9 @@ class Instancer::EngineData : public Data if( m_indicesInactive.size() ) { - // If there are duplicates in the id list, then some point indices will be omitted - we - // need to check each point index to see if it got assigned an id correctly // TODO - + // If this point is tagged as inactive ( could be due to a user specified inactiveIds, + // or due to an id collision when omitDuplicateIds is set ), then we return -1 for + // the prototype, which means to omit this point. if( m_indicesInactive[pointIndex] ) { return -1; @@ -1352,7 +1370,7 @@ Instancer::Instancer( const std::string &name ) addChild( new StringPlug( "position", Plug::In, "P" ) ); addChild( new StringPlug( "orientation", Plug::In ) ); addChild( new StringPlug( "scale", Plug::In ) ); - addChild( new StringPlug( "inactiveIds", Plug::In, "inactiveIds invisibleIds" ) ); + addChild( new StringPlug( "inactiveIds", Plug::In, "" ) ); addChild( new StringPlug( "attributes", Plug::In ) ); addChild( new StringPlug( "attributePrefix", Plug::In ) ); addChild( new BoolPlug( "encapsulate", Plug::In ) );