Skip to content

Commit f8d50d4

Browse files
wschnepphybridherbst
authored andcommitted
GLTFRecorder: fix issue where resulting animation would have linear interpolation for cases where a jump was expected
1 parent cde6ca3 commit f8d50d4

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

Runtime/Scripts/Timeline/GLTFRecorder.cs

+29-5
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ internal class Track
230230
private AnimationData tr;
231231
private ExportPlan plan;
232232
private Dictionary<double, object> samples;
233-
private object lastSample;
233+
private Tuple<double, object> lastSample = null;
234+
private Tuple<double, object> secondToLastSample = null;
234235

235236
public Track(AnimationData tr, ExportPlan plan, double time)
236237
{
@@ -245,11 +246,34 @@ public void SampleIfChanged(double time)
245246
var value = plan.Sample(tr);
246247
if (value == null || (value is Object o && !o))
247248
return;
248-
if (!value.Equals(lastSample))
249-
{
250-
samples[time] = value;
251-
lastSample = value;
249+
// As a memory optimization we want to be able to skip identical samples.
250+
// But, we cannot always skip samples when they are identical to the previous one - otherwise cases like this break:
251+
// - First assume an object is invisible at first (by having a scale of (0,0,0))
252+
// - At some point in time, it is instantaneously set "visible" by updating its scale from (0,0,0) to (1,1,1)
253+
// If we simply skip identical samples on insert, instead of a instantaneous
254+
// visibility/scale changes we get a linearly interpolated scale change because only two samples will be recorded:
255+
// - one (0,0,0) at the start of time
256+
// - (1,1,1) at the time of the visibility change
257+
// What we want to get is
258+
// - one sample with (0,0,0) at the start,
259+
// - one with the same value right before the instantaneous change,
260+
// - and then at the time of the change, we need a sample with (1,1,1)
261+
// With this setup, now the linear interpolation only has an effect in the very short duration between the last two samples and we get the animation we want.
262+
263+
// How do we achieve both?
264+
// Always sample & record and then on adding the next sample(s) we check
265+
// if the *last two* samples were identical to the current sample.
266+
// If that is the case we can remove/overwrite the middle sample with the new value.
267+
if (lastSample != null
268+
&& secondToLastSample != null
269+
&& lastSample.Item2.Equals(secondToLastSample.Item2)
270+
&& lastSample.Item2.Equals(value)) {
271+
272+
samples.Remove(lastSample.Item1);
252273
}
274+
samples[time] = value;
275+
secondToLastSample = lastSample;
276+
lastSample = new Tuple<double, object>(time, value);
253277
}
254278

255279
}

0 commit comments

Comments
 (0)