Skip to content

Commit

Permalink
Merge pull request #6088 from danieldresser-ie/instancer64
Browse files Browse the repository at this point in the history
Instancer : Support Int64VectorData for Ids
  • Loading branch information
johnhaddon authored Oct 31, 2024
2 parents 70968dd + 85b334a commit 59206b6
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 58 deletions.
3 changes: 3 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
1.5.x.x (relative to 1.5.0.1)
=======

Improvements
------------

- Instancer : Added support for 64 bit ints for ids ( matching what is loaded from USD ).

1.5.0.1 (relative to 1.5.0.0)
=======
Expand Down
80 changes: 71 additions & 9 deletions python/GafferSceneTest/InstancerTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1498,11 +1498,17 @@ def testSetsWithDeepPrototypeRoots( self ) :
)

def testIds( self ) :
with self.subTest( useInt64 = False ):
self.runTestIds( False )
with self.subTest( useInt64 = True ):
self.runTestIds( True )

def runTestIds( self, useInt64 ) :

points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x, 0, 0 ) for x in range( 0, 4 ) ] ) )
points["id"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex,
IECore.IntVectorData( [ 10, 100, 111, 5 ] ),
( IECore.Int64VectorData if useInt64 else IECore.IntVectorData)( [ 10, 100, 111, 5 ] ),
)
points["index"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex,
Expand Down Expand Up @@ -1560,16 +1566,16 @@ def testIds( self ) :

self.assertEncapsulatedRendersSame( instancer )

def testNegativeIdsAndIndices( self ) :
def testExtremeIdsAndIndices( self ) :

points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x, 0, 0 ) for x in range( 0, 2 ) ] ) )
points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x, 0, 0 ) for x in range( 0, 4 ) ] ) )
points["id"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex,
IECore.IntVectorData( [ -10, -5 ] ),
IECore.Int64VectorData( [ -10, -5, 8000000000, 8000000001 ] ),
)
points["index"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex,
IECore.IntVectorData( [ -1, -2 ] ),
IECore.IntVectorData( [ -1, -2, 1, 0 ] ),
)

objectToScene = GafferScene.ObjectToScene()
Expand All @@ -1582,24 +1588,57 @@ def testNegativeIdsAndIndices( self ) :
instances["children"][0].setInput( cube["out"] )
instances["parent"].setValue( "/" )

allFilter = GafferScene.PathFilter()
allFilter["paths"].setValue( IECore.StringVectorData( [ '/*' ] ) )

customAttributes = GafferScene.CustomAttributes()
customAttributes["in"].setInput( instances["out"] )
customAttributes["filter"].setInput( allFilter["out"] )
customAttributes["attributes"].addChild( Gaffer.NameValuePlug( "intAttr", Gaffer.IntPlug( "value", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ), True, "member1" ) )

customAttributes["ReadContextExpression"] = Gaffer.Expression()
customAttributes["ReadContextExpression"].setExpression(
'parent["attributes"]["member1"]["value"] = context.get( "seed", -1 )'
)

instancer = GafferScene.Instancer()
instancer["in"].setInput( objectToScene["out"] )
instancer["prototypes"].setInput( instances["out"] )
instancer["parent"].setValue( "/object" )
instancer["prototypes"].setInput( customAttributes["out"] )
instancer["filter"].setInput( allFilter["out"] )
instancer["prototypeIndex"].setValue( "index" )
instancer["id"].setValue( "id" )
instancer["seedEnabled"].setValue( True )
instancer["rawSeed"].setValue( True )

self.assertEqual( instancer["out"].childNames( "/object/instances" ), IECore.InternedStringVectorData( [ "sphere", "cube" ] ) )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "-5" ] ) )
self.assertEqual( instancer["out"].childNames( "/object/instances/cube" ), IECore.InternedStringVectorData( [ "-10" ] ) )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere" ), IECore.InternedStringVectorData( [ "-5", "8000000001" ] ) )
self.assertEqual( instancer["out"].childNames( "/object/instances/cube" ), IECore.InternedStringVectorData( [ "-10", "8000000000" ] ) )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere/-5" ), IECore.InternedStringVectorData() )
self.assertEqual( instancer["out"].childNames( "/object/instances/cube/-10" ), IECore.InternedStringVectorData() )
self.assertEqual( instancer["out"].childNames( "/object/instances/sphere/8000000001" ), IECore.InternedStringVectorData() )
self.assertEqual( instancer["out"].childNames( "/object/instances/cube/8000000000" ), IECore.InternedStringVectorData() )

self.assertEqual( instancer["out"].object( "/object/instances" ), IECore.NullObject.defaultNullObject() )
self.assertEqual( instancer["out"].object( "/object/instances/sphere" ), IECore.NullObject.defaultNullObject() )
self.assertEqual( instancer["out"].object( "/object/instances/cube" ), IECore.NullObject.defaultNullObject() )
self.assertEqual( instancer["out"].object( "/object/instances/sphere/-5" ), sphere["out"].object( "/sphere" ) )
self.assertEqual( instancer["out"].object( "/object/instances/cube/-10" ), cube["out"].object( "/cube" ) )
self.assertEqual( instancer["out"].object( "/object/instances/sphere/8000000001" ), sphere["out"].object( "/sphere" ) )
self.assertEqual( instancer["out"].object( "/object/instances/cube/8000000000" ), cube["out"].object( "/cube" ) )

self.assertEqual( instancer["out"].attributes( "/object/instances/sphere/-5" )["intAttr"].value, -5 )
self.assertEqual( instancer["out"].attributes( "/object/instances/cube/-10" )["intAttr"].value, -10 )

# We want to fully support int64 typed ids, but for reasons of backwards compatiblity and OSL support,
# we're still using int32 for the seed context variable, so these ids get wrapped around even in raw seeds
# mode.
self.assertEqual( instancer["out"].attributes( "/object/instances/sphere/8000000001" )["intAttr"].value, -589934591 )
self.assertEqual( instancer["out"].attributes( "/object/instances/cube/8000000000" )["intAttr"].value, -589934592 )

self.assertEqual(
instancer["variations"].getValue(),
IECore.CompoundData( { 'seed' : IECore.IntData( 4 ), '' : IECore.IntData( 4 ) } )
)

self.assertSceneValid( instancer["out"] )

Expand Down Expand Up @@ -2430,6 +2469,29 @@ def quant( x, q ):

self.assertEncapsulatedRendersSame( instancer )


# We get different results if we change the id the seeds are based on
points["idTest"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.IntVectorData(
[ i * 37 for i in range( 100 ) ]
)
)
pointsSource["object"].setValue( points )
instancer["id"].setValue( "idTest" )
self.assertEqual( uniqueCounts(), { "floatVar" : 5, "color4fVar" : 4, "seed" : 64, "" : 98 } )

# Works the same using int64 ids
points["idTest"] = IECoreScene.PrimitiveVariable(
IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.Int64VectorData(
[ i * 37 for i in range( 100 ) ]
)
)
pointsSource["object"].setValue( points )
self.assertEqual( uniqueCounts(), { "floatVar" : 5, "color4fVar" : 4, "seed" : 64, "" : 98 } )

instancer["id"].setToDefault()


# Now turn on time offset as well and play with everything together
instancer["seeds"].setValue( 10 )
instancer["timeOffset"]["enabled"].setValue( True )
Expand Down
9 changes: 3 additions & 6 deletions python/GafferSceneUI/InstancerUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,9 @@ def __init__( self, headings, toolTipOverride = "" ) :

"description",
"""
The object on which to make the instances. The
position, orientation and scale of the instances
are taken from per-vertex primitive variables on
this object. This is ignored when a filter is
connected, in which case the filter specifies
multiple objects to make the instances from.
Using the `parent` plug to select the source is now deprecated, please use a filter instead.
This plug is still supported for backwards compatibility, but is incompatible with recent features,
like accurately reporting variation counts.
""",

"layout:section", "Settings.General",
Expand Down
4 changes: 2 additions & 2 deletions python/GafferTest/TestRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,12 @@ def filterCategories( test, inclusions = "*", exclusions = "" ) :
testMethod = getattr( test, test._testMethodName )
## \todo Remove `standard` fallback (breaking change).
categories = getattr( testMethod, "categories", { "standard" } )
if not any( IECore.StringAlgo.match( c, inclusions ) for c in categories ) :
if not any( IECore.StringAlgo.matchMultiple( c, inclusions ) for c in categories ) :
setattr(
test, test._testMethodName,
unittest.skip( f"Categories not included by `{inclusions}`" )( testMethod )
)
elif any( IECore.StringAlgo.match( c, exclusions ) for c in categories ) :
elif any( IECore.StringAlgo.matchMultiple( c, exclusions ) for c in categories ) :
setattr(
test, test._testMethodName,
unittest.skip( f"Categories excluded by `{exclusions}`" )( testMethod )
Expand Down
Loading

0 comments on commit 59206b6

Please sign in to comment.