@@ -93,6 +93,17 @@ void HdArnoldInstancer::Sync(HdSceneDelegate* sceneDelegate, HdRenderParam* rend
9393 }
9494}
9595
96+ // Sample a primvar, check that the keys have the correct number of instances otherwise get only the sample at the keyframe
97+ // We have to do this because hydra SamplePrimvar
98+ template <typename VectorT>
99+ static void SamplePrimvar (
100+ HdSceneDelegate* delegate, const SdfPath& id, const TfToken& key, const GfVec2f& shutterRange, VectorT& out)
101+ {
102+ HdArnoldSampledPrimvarType sample;
103+ delegate->SamplePrimvar (id, key, &sample);
104+ HdArnoldUnboxResample (sample, shutterRange, out);
105+ }
106+
96107void HdArnoldInstancer::_SyncPrimvars (HdDirtyBits dirtyBits, HdArnoldRenderParam* renderParam)
97108{
98109 auto & changeTracker = GetDelegate ()->GetRenderIndex ().GetChangeTracker ();
@@ -120,21 +131,13 @@ void HdArnoldInstancer::_SyncPrimvars(HdDirtyBits dirtyBits, HdArnoldRenderParam
120131 continue ;
121132 }
122133 if (primvar.name == GetInstanceTransformsToken ()) {
123- HdArnoldSampledPrimvarType sample;
124- GetDelegate ()->SamplePrimvar (id, GetInstanceTransformsToken (), &sample);
125- HdArnoldUnboxResample (sample, renderParam->GetShutterRange (), _transforms);
134+ SamplePrimvar (GetDelegate (), id, primvar.name , renderParam->GetShutterRange (), _transforms);
126135 } else if (primvar.name == GetRotateToken ()) {
127- HdArnoldSampledPrimvarType sample;
128- GetDelegate ()->SamplePrimvar (id, GetRotateToken (), &sample);
129- HdArnoldUnboxResample (sample, renderParam->GetShutterRange (), _rotates);
136+ SamplePrimvar (GetDelegate (), id, primvar.name , renderParam->GetShutterRange (), _rotates);
130137 } else if (primvar.name == GetScaleToken ()) {
131- HdArnoldSampledPrimvarType sample;
132- GetDelegate ()->SamplePrimvar (id, GetScaleToken (), &sample);
133- HdArnoldUnboxResample (sample, renderParam->GetShutterRange (), _scales);
138+ SamplePrimvar (GetDelegate (), id, primvar.name , renderParam->GetShutterRange (), _scales);
134139 } else if (primvar.name == GetTranslateToken ()) {
135- HdArnoldSampledPrimvarType sample;
136- GetDelegate ()->SamplePrimvar (id, GetTranslateToken (), &sample);
137- HdArnoldUnboxResample (sample, renderParam->GetShutterRange (), _translates);
140+ SamplePrimvar (GetDelegate (), id, primvar.name , renderParam->GetShutterRange (), _translates);
138141 } else {
139142 HdArnoldInsertPrimvar (
140143 _primvars, primvar.name , primvar.role , primvar.interpolation , GetDelegate ()->Get (id, primvar.name ),
@@ -143,13 +146,39 @@ void HdArnoldInstancer::_SyncPrimvars(HdDirtyBits dirtyBits, HdArnoldRenderParam
143146 }
144147 }
145148
149+ // NOTE: it shouldn't be necessary to mark the instancer clean as it is done later on by hydra
146150 changeTracker.MarkInstancerClean (id);
147151}
148152
153+ void HdArnoldInstancer::ResampleInstancePrimvars ()
154+ {
155+ const auto & id = GetId ();
156+ std::lock_guard<std::mutex> lock (_mutex);
157+ // Recompute the sampled primvars only if they were previously sampled
158+ if (_transforms.count ) {
159+ SamplePrimvar (GetDelegate (), id, GetInstanceTransformsToken (), _samplingInterval, _transforms);
160+ }
161+ if (_rotates.count ) {
162+ SamplePrimvar (GetDelegate (), id, GetRotateToken (), _samplingInterval, _rotates);
163+ }
164+ if (_scales.count ) {
165+ SamplePrimvar (GetDelegate (), id, GetScaleToken (), _samplingInterval, _scales);
166+ }
167+ if (_translates.count ) {
168+ SamplePrimvar (GetDelegate (), id, GetTranslateToken (), _samplingInterval, _translates);
169+ }
170+ }
171+
149172void HdArnoldInstancer::CalculateInstanceMatrices (HdArnoldRenderDelegate* renderDelegate,
150173 const SdfPath& prototypeId, std::vector<AtNode *> &instancers)
151174{
152175 const SdfPath& instancerId = GetId ();
176+ HdArnoldRenderParam * renderParam = reinterpret_cast <HdArnoldRenderParam*>(renderDelegate->GetRenderParam ());
177+
178+ // If the sampling interval has changed we need to resample the translate, orientations and scales
179+ if (UpdateSamplingInterval (renderParam->GetShutterRange ())){
180+ ResampleInstancePrimvars ();
181+ }
153182
154183 const auto instanceIndices = GetDelegate ()->GetInstanceIndices (instancerId, prototypeId);
155184 if (instanceIndices.empty ()) {
@@ -166,10 +195,15 @@ void HdArnoldInstancer::CalculateInstanceMatrices(HdArnoldRenderDelegate* render
166195 // most samples and use its time range.
167196 // TODO(pal): Improve this further by using the widest time range and calculate sample count based on that.
168197 _AccumulateSampleTimes (instancerTransforms, sampleArray);
169- _AccumulateSampleTimes (_transforms, sampleArray);
170- _AccumulateSampleTimes (_translates, sampleArray);
171- _AccumulateSampleTimes (_rotates, sampleArray);
172- _AccumulateSampleTimes (_scales, sampleArray);
198+ {
199+ // Another mesh can be resampling the instances primvars, we need to lock
200+ std::lock_guard<std::mutex> lock (_mutex);
201+ _AccumulateSampleTimes (_transforms, sampleArray);
202+ _AccumulateSampleTimes (_translates, sampleArray);
203+ _AccumulateSampleTimes (_rotates, sampleArray);
204+ _AccumulateSampleTimes (_scales, sampleArray);
205+ }
206+
173207
174208 // By default _deformKeys will take over sample counts
175209 if (sampleArray.count <= 2 && _deformKeys < 2 && _deformKeys > -1 ) {
@@ -274,7 +308,7 @@ void HdArnoldInstancer::CalculateInstanceMatrices(HdArnoldRenderDelegate* render
274308 auto * nodeIdxsArray = AiArrayAllocate (instanceCount, sampleCount, AI_TYPE_UINT);
275309 auto * matrices = static_cast <AtMatrix*>(AiArrayMap (matrixArray));
276310 auto * nodeIdxs = static_cast <uint32_t *>(AiArrayMap (nodeIdxsArray));
277- std::fill (nodeIdxs, nodeIdxs + instanceCount, 0 );
311+ std::fill (nodeIdxs, nodeIdxs + instanceCount*sampleCount , 0 );
278312 AiArrayUnmap (nodeIdxsArray);
279313 auto convertMatrices = [&](size_t sample) {
280314 std::transform (
0 commit comments