Skip to content

Commit 3f08eee

Browse files
RendererAlgo::objectSamples : Output single samples for static objects
1 parent 42814c5 commit 3f08eee

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

Changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Improvements
88
- OSLShader :
99
- Improved loading of spline parameters with additional duplicate endpoints.
1010
- Added support for loading splines from RenderMan shaders.
11+
- Rendering : Improved detection of static objects. This fixes messages from Arnold like "discarded X duplicate deformation keys", and may improve performance in some cases.
1112

1213
Fixes
1314
-----

python/GafferSceneTest/RendererAlgoTest.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,42 @@ def testObjectSamples( self ) :
6161

6262
self.assertEqual( [ s.radius() for s in samples ], [ 0.75, 1.25 ] )
6363

64+
def testObjectSamplesMatchingHash( self ) :
65+
66+
# If the input object has a hash that doesn't vary with time, then we just get one sample when
67+
# we try to sample over time.
68+
sphere = GafferScene.Sphere()
69+
sphere["type"].setValue( sphere.Type.Primitive )
70+
71+
with Gaffer.Context() as c :
72+
c["scene:path"] = IECore.InternedStringVectorData( [ "sphere" ] )
73+
samples = GafferScene.Private.RendererAlgo.objectSamples( sphere["out"]["object"], [ 0.75, 1.25 ] )
74+
75+
self.assertEqual( [ s.radius() for s in samples ], [ 1.0 ] )
76+
77+
def testObjectSamplesMatchingResult( self ) :
78+
79+
# If the input object has different hashes at different times, but still produces identical objects,
80+
# then we should still only output one sample.
81+
82+
frame = GafferTest.FrameNode()
83+
84+
# Quick hack to produce a value that doesn't vary, but has a hash that does: feed the frame
85+
# through an integer multiply node, which will truncate the value to an integer
86+
multiply = GafferTest.MultiplyNode()
87+
multiply["op1"].setValue( 1 )
88+
multiply["op2"].setInput( frame["output"] )
89+
90+
sphere = GafferScene.Sphere()
91+
sphere["type"].setValue( sphere.Type.Primitive )
92+
sphere["radius"].setInput( multiply["product"] )
93+
94+
with Gaffer.Context() as c :
95+
c["scene:path"] = IECore.InternedStringVectorData( [ "sphere" ] )
96+
samples = GafferScene.Private.RendererAlgo.objectSamples( sphere["out"]["object"], [ 1.25, 1.75 ] )
97+
98+
self.assertEqual( [ s.radius() for s in samples ], [ 1.0 ] )
99+
64100
def testNonInterpolableObjectSamples( self ) :
65101

66102
frame = GafferTest.FrameNode()

src/GafferScene/RendererAlgo.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,9 @@ bool objectSamples( const ObjectPlug *objectPlug, const std::vector<float> &samp
556556
const Context *frameContext = Context::current();
557557
Context::EditableScope timeContext( frameContext );
558558

559+
bool actualMovement = false;
560+
IECore::MurmurHash actualHash;
561+
559562
samples.reserve( sampleTimes.size() );
560563
for( size_t i = 0; i < sampleTimes.size(); i++ )
561564
{
@@ -568,6 +571,15 @@ bool objectSamples( const ObjectPlug *objectPlug, const std::vector<float> &samp
568571
runTimeCast<const Camera>( object.get() )
569572
)
570573
{
574+
if( i == 0 )
575+
{
576+
actualHash = object->hash();
577+
}
578+
else if( !actualMovement )
579+
{
580+
actualMovement = object->hash() != actualHash;
581+
}
582+
571583
samples.push_back( object.get() );
572584
}
573585
else if(
@@ -608,6 +620,11 @@ bool objectSamples( const ObjectPlug *objectPlug, const std::vector<float> &samp
608620
break;
609621
}
610622
}
623+
624+
if( !actualMovement && samples.size() > 1 )
625+
{
626+
samples.resize( 1 );
627+
}
611628
}
612629

613630
if( hash )

0 commit comments

Comments
 (0)