Skip to content

Commit

Permalink
Merge pull request #6081 from danieldresser-ie/instancerInvis
Browse files Browse the repository at this point in the history
Instancer : Support inactive ids
  • Loading branch information
johnhaddon authored Nov 4, 2024
2 parents a9f0121 + 3132819 commit a70e659
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 47 deletions.
4 changes: 3 additions & 1 deletion Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
Improvements
------------

- Instancer : Added support for 64 bit ints for ids ( matching what is loaded from USD ).
- Instancer :
- Added `inactiveIds` plug for selecting primitive variables to disable some instances.
- Added support for 64 bit integer ids (matching what is loaded from USD).

Fixes
-----
Expand Down
3 changes: 3 additions & 0 deletions include/GafferScene/Instancer.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class GAFFERSCENE_API Instancer : public BranchCreator
Gaffer::StringPlug *scalePlug();
const Gaffer::StringPlug *scalePlug() const;

Gaffer::StringPlug *inactiveIdsPlug();
const Gaffer::StringPlug *inactiveIdsPlug() const;

Gaffer::StringPlug *attributesPlug();
const Gaffer::StringPlug *attributesPlug() const;

Expand Down
78 changes: 78 additions & 0 deletions python/GafferSceneTest/InstancerTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,84 @@ def testTransform( self ) :
)
self.assertEncapsulatedRendersSame( instancer )

def testInactiveIds( self ) :

points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x, 0, 0 ) for x in range( 0, 10 ) ] ) )
points["inactiveIdsTest"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Constant,
IECore.IntVectorData( [ 3, 5, 7 ] )
)
points["inactiveIdsTest64"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Constant,
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 ] )
)
points["alternateIds"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex,
IECore.IntVectorData( [ i + 7 for i in range( 10 ) ] )
)

objectToScene = GafferScene.ObjectToScene()
objectToScene["object"].setValue( points )

sphere = GafferScene.Sphere()

pointsFilter = GafferScene.PathFilter()
pointsFilter["paths"].setValue( IECore.StringVectorData( [ "/object" ] ) )

instancer = GafferScene.Instancer()
instancer["in"].setInput( objectToScene["out"] )
instancer["prototypes"].setInput( sphere["out"] )
instancer["filter"].setInput( pointsFilter["out"] )

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" ] ) )

instancer["inactiveIds"].setValue( "inactiveIdsTest64" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "2", "3", "5", "7", "8", "9" ] ) )

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" ] ) )

instancer["inactiveIds"].setValue( "inactiveIdsTest inactiveIdsTest64 inactive" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1" ] ) )

# If the id is out of bounds, nothing happens
instancer["inactiveIds"].setValue( "badInactive" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] ) )

instancer["id"].setValue( "alternateIds" )
# A vertex variable applies based on vertex position in the list
instancer["inactiveIds"].setValue( "inactive" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "7", "8", "10", "11", "14" ] ) )

# An id list matches based on ids
instancer["inactiveIds"].setValue( "inactive inactiveIdsTest" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "8", "10", "11", "14" ] ) )

instancer["inactiveIds"].setValue( "badInactive" )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "7", "8", "9", "10", "11", "12", "14", "15", "16" ] ) )


def testAnimation( self ) :

pointA = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [
Expand Down
20 changes: 20 additions & 0 deletions python/GafferSceneUI/InstancerUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ def __init__( self, headings, toolTipOverride = "" ) :

"layout:section:Settings.General:collapsed", False,
"layout:section:Settings.Transforms:collapsed", False,
"layout:section:Settings.Inactive Ids:collapsed", False,
"layout:section:Settings.Attributes:collapsed", False,

"layout:activator:modeIsIndexedRootsList", lambda node : node["prototypeMode"].getValue() == GafferScene.Instancer.PrototypeMode.IndexedRootsList,
Expand Down Expand Up @@ -546,6 +547,25 @@ def __init__( self, headings, toolTipOverride = "" ) :

],

"inactiveIds" : [

"description",
"""
A space separated list of names of primitive variables specifying instances to make inactive.
Inactive instances are not output from the instancer or rendered.
Each primitive variable either must be a constant vector of type Int or Int64 with a list of
matching ids to deactivate, or it must be a vertex bool primitive variable, in which case it
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",

],

"attributes" : [

"description",
Expand Down
Loading

0 comments on commit a70e659

Please sign in to comment.