From 36fcef738c0a2ab651b539475acb1cd6abfe0ed9 Mon Sep 17 00:00:00 2001 From: vis2k Date: Fri, 10 Mar 2023 17:51:53 +0800 Subject: [PATCH] timeline reset --- .../Core/NetworkClient_TimeInterpolation.cs | 9 ++ .../Mirror/Core/NetworkConnectionToClient.cs | 2 + .../SnapshotInterpolation.cs | 64 ++++++++++++- .../Snapshot Interpolation/ClientCube.cs | 9 ++ .../SnapshotInterpolation.unity | 2 + .../Editor/SnapshotInterpolationTests.cs | 90 ++++++++++++------- 6 files changed, 139 insertions(+), 37 deletions(-) diff --git a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs index 060dae5c1..11b9deb2f 100644 --- a/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs +++ b/Assets/Mirror/Core/NetworkClient_TimeInterpolation.cs @@ -50,6 +50,13 @@ public static partial class NetworkClient [Range(0, 1)] public static double slowdownSpeed = 0.01f; // 1% + [Header("Snapshot Interpolation: Clamping")] + [Tooltip("If the local timeline is so far behind remote time that catchup would take too long, then we do a hard reset so it won't catch up for a minute or more.")] + public static float resetNegativeThreshold = catchupNegativeThreshold * 5; // needs to be larger than catchup threshold + + [Tooltip("If the local timeline is so far ahead remote time that slowdown would take too long, then we do a hard reset so it won't slow down for a minute or more.")] + public static float resetPositiveThreshold = catchupPositiveThreshold * 5; // needs to be larger than catchup threshold + [Tooltip("Catchup/Slowdown is adjusted over n-second exponential moving average.")] public static int driftEmaDuration = 1; // shouldn't need to modify this, but expose it anyway @@ -155,6 +162,8 @@ public static void OnTimeSnapshot(TimeSnapshot snap) ref driftEma, catchupNegativeThreshold, catchupPositiveThreshold, + resetNegativeThreshold, + resetPositiveThreshold, ref deliveryTimeEma); // Debug.Log($"inserted TimeSnapshot remote={snap.remoteTime:F2} local={snap.localTime:F2} total={snapshots.Count}"); diff --git a/Assets/Mirror/Core/NetworkConnectionToClient.cs b/Assets/Mirror/Core/NetworkConnectionToClient.cs index 317074ec8..babd2afb9 100644 --- a/Assets/Mirror/Core/NetworkConnectionToClient.cs +++ b/Assets/Mirror/Core/NetworkConnectionToClient.cs @@ -90,6 +90,8 @@ public void OnTimeSnapshot(TimeSnapshot snapshot) ref driftEma, NetworkClient.catchupNegativeThreshold, NetworkClient.catchupPositiveThreshold, + NetworkClient.resetNegativeThreshold, + NetworkClient.resetPositiveThreshold, ref deliveryTimeEma ); } diff --git a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs index d0c08cfeb..793cdd10e 100644 --- a/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs +++ b/Assets/Mirror/Core/SnapshotInterpolation/SnapshotInterpolation.cs @@ -61,6 +61,40 @@ public static double Timescale( return 1; } + // catchup/slowdown attempts to bring timeline back in sync smoothly. + // however, if timeline is too far behind then we should clamp hard. + // otherwise catchup/slowdown may take 20s or more, minutes, or more. + // at some point, it'll just be way too far behind. + // + // to reproduce, try snapshot interpolation demo and press the button to + // simulate the client timeline at multiple seconds behind. it'll take + // a long time to catch up if the timeline is a long time behind. + // + // returns true if time needs to be clamped. + // drift EMA should also be reset so that catchup/slowdown doesn't + // compute based on old values before the reset. + public static bool TimelineReset( + double drift, // how far we are off from bufferTime + double absoluteResetNegativeThreshold, // in seconds. needs to be larger than catchup thresholds. + double absoluteResetPositiveThreshold // in seconds. needs to be larger than catchup thresholds. + ) + { + // if the drift time is too large, it means we are behind more time. + if (drift > absoluteResetPositiveThreshold) + { + return true; + } + + // if the drift time is too small, it means we are ahead of time. + if (drift < absoluteResetNegativeThreshold) + { + return true; + } + + // don't clamp, all is within acceptable ranges. + return false; + } + // calculate dynamic buffer time adjustment public static double DynamicAdjustment( double sendInterval, @@ -120,6 +154,8 @@ public static void InsertAndAdjust( ref ExponentialMovingAverage driftEma, // for catchup / slowdown float catchupNegativeThreshold, // in % of sendInteral (careful, we may run out of snapshots) float catchupPositiveThreshold, // in % of sendInterval + float resetNegativeThreshold, // in % of sendInterval (careful, we may run out of snapshots) + float resetPositiveThreshold, // in % of sendInterval ref ExponentialMovingAverage deliveryTimeEma) // for dynamic buffer time adjustment where T : Snapshot { @@ -205,15 +241,37 @@ public static void InsertAndAdjust( double drift = driftEma.Value - bufferTime; // convert relative thresholds to absolute values based on sendInterval - double absoluteNegativeThreshold = sendInterval * catchupNegativeThreshold; - double absolutePositiveThreshold = sendInterval * catchupPositiveThreshold; + double absoluteCatchupNegativeThreshold = sendInterval * catchupNegativeThreshold; + double absoluteCatchupPositiveThreshold = sendInterval * catchupPositiveThreshold; + double absoluteResetNegativeThreshold = sendInterval * resetNegativeThreshold; + double absoluteResetPositiveThreshold = sendInterval * resetPositiveThreshold; + + // catchup/slowdown smoothly keeps the timeline in sync. + // however, if we get way too far behind/ahead, then catchup/ + // slowdown could take 10s, 30s, minutes, to catch up. + // beyond a certain point, it's better to to reset the timeline. + // it'll cause a noticable visual jump, but it's necessary. + if (TimelineReset(drift, absoluteResetNegativeThreshold, absoluteResetPositiveThreshold)) + { + // reset timeline to be behind by 'bufferTime' + localTimeline = latestRemoteTime - bufferTime; + + // reset average drift. we just reset, so there is no drift. + driftEma.Reset(); + + // TODO reset snapshots too? old ones are of no value? + } + + // timeline reset could have reset drift. + // recalculate it before adjusting timescale. + drift = driftEma.Value - bufferTime; // next, set localTimescale to catchup consistently in Update(). // we quantize between default/catchup/slowdown, // this way we have 'default' speed most of the time(!). // and only catch up / slow down for a little bit occasionally. // a consistent multiplier would never be exactly 1.0. - localTimescale = Timescale(drift, catchupSpeed, slowdownSpeed, absoluteNegativeThreshold, absolutePositiveThreshold); + localTimescale = Timescale(drift, catchupSpeed, slowdownSpeed, absoluteCatchupNegativeThreshold, absoluteCatchupPositiveThreshold); // debug logging // UnityEngine.Debug.Log($"sendInterval={sendInterval:F3} bufferTime={bufferTime:F3} drift={drift:F3} driftEma={driftEma.Value:F3} timescale={localTimescale:F3} deliveryIntervalEma={deliveryTimeEma.Value:F3}"); diff --git a/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs b/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs index 14635f804..a4ec7e3e6 100644 --- a/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs +++ b/Assets/Mirror/Examples/Snapshot Interpolation/ClientCube.cs @@ -51,6 +51,13 @@ public class ClientCube : MonoBehaviour [Range(0, 1)] public double slowdownSpeed = 0.01f; // 1% + [Header("Snapshot Interpolation: Clamping")] + [Tooltip("If the local timeline is so far behind remote time that catchup would take too long, then we do a hard reset so it won't catch up for a minute or more.")] + public float resetNegativeThreshold = -5; // needs to be larger than catchup threshold + + [Tooltip("If the local timeline is so far ahead remote time that slowdown would take too long, then we do a hard reset so it won't slow down for a minute or more.")] + public float resetPositiveThreshold = 5; // needs to be larger than catchup threshold + [Tooltip("Catchup/Slowdown is adjusted over n-second exponential moving average.")] public int driftEmaDuration = 1; // shouldn't need to modify this, but expose it anyway @@ -144,6 +151,8 @@ public void OnMessage(Snapshot3D snap) ref driftEma, catchupNegativeThreshold, catchupPositiveThreshold, + resetNegativeThreshold, + resetPositiveThreshold, ref deliveryTimeEma); } diff --git a/Assets/Mirror/Examples/Snapshot Interpolation/SnapshotInterpolation.unity b/Assets/Mirror/Examples/Snapshot Interpolation/SnapshotInterpolation.unity index 2a218cab3..e9e1ad92c 100644 --- a/Assets/Mirror/Examples/Snapshot Interpolation/SnapshotInterpolation.unity +++ b/Assets/Mirror/Examples/Snapshot Interpolation/SnapshotInterpolation.unity @@ -176,6 +176,8 @@ MonoBehaviour: catchupPositiveThreshold: 1 catchupSpeed: 0.009999999776482582 slowdownSpeed: 0.009999999776482582 + resetNegativeThreshold: -5 + resetPositiveThreshold: 5 driftEmaDuration: 1 dynamicAdjustment: 1 dynamicAdjustmentTolerance: 1 diff --git a/Assets/Mirror/Tests/Editor/SnapshotInterpolationTests.cs b/Assets/Mirror/Tests/Editor/SnapshotInterpolationTests.cs index 4e1780147..23b75faeb 100644 --- a/Assets/Mirror/Tests/Editor/SnapshotInterpolationTests.cs +++ b/Assets/Mirror/Tests/Editor/SnapshotInterpolationTests.cs @@ -34,8 +34,10 @@ public class SnapshotInterpolationTests // some defaults const double catchupSpeed = 0.02; const double slowdownSpeed = 0.04; - const double negativeThresh = -0.10; // in seconds - const double positiveThresh = 0.10; // in seconds + const double catchupNegativeThresh = -0.10; // in seconds + const double catchupPositiveThresh = 0.10; // in seconds + const double resetNegativeThresh = -1.00; // in seconds + const double resetPositiveThresh = 1.00; // in seconds [SetUp] public void SetUp() @@ -72,19 +74,39 @@ public void RemoveRange() public void Timescale() { // no drift: linear time - Assert.That(SnapshotInterpolation.Timescale(0, catchupSpeed, slowdownSpeed, negativeThresh, positiveThresh), Is.EqualTo(1.0)); + Assert.That(SnapshotInterpolation.Timescale(0, catchupSpeed, slowdownSpeed, catchupNegativeThresh, catchupPositiveThresh), Is.EqualTo(1.0)); // near negative thresh but not under it: linear time - Assert.That(SnapshotInterpolation.Timescale(-0.09, catchupSpeed, slowdownSpeed, negativeThresh, positiveThresh), Is.EqualTo(1.0)); + Assert.That(SnapshotInterpolation.Timescale(-0.09, catchupSpeed, slowdownSpeed, catchupNegativeThresh, catchupPositiveThresh), Is.EqualTo(1.0)); // near positive thresh but not above it: linear time - Assert.That(SnapshotInterpolation.Timescale(0.09, catchupSpeed, slowdownSpeed, negativeThresh, positiveThresh), Is.EqualTo(1.0)); + Assert.That(SnapshotInterpolation.Timescale(0.09, catchupSpeed, slowdownSpeed, catchupNegativeThresh, catchupPositiveThresh), Is.EqualTo(1.0)); // below negative thresh: catchup - Assert.That(SnapshotInterpolation.Timescale(-0.11, catchupSpeed, slowdownSpeed, negativeThresh, positiveThresh), Is.EqualTo(0.96)); + Assert.That(SnapshotInterpolation.Timescale(-0.11, catchupSpeed, slowdownSpeed, catchupNegativeThresh, catchupPositiveThresh), Is.EqualTo(0.96)); // above positive thresh: slowdown - Assert.That(SnapshotInterpolation.Timescale(0.11, catchupSpeed, slowdownSpeed, negativeThresh, positiveThresh), Is.EqualTo(1.02)); + Assert.That(SnapshotInterpolation.Timescale(0.11, catchupSpeed, slowdownSpeed, catchupNegativeThresh, catchupPositiveThresh), Is.EqualTo(1.02)); + } + + [Test] + public void TimelineReset() + { + // no drift. no reset. + Assert.That(SnapshotInterpolation.TimelineReset(0, resetNegativeThresh, resetPositiveThresh), Is.False); + + // near negative thresh but not under it. no reset. + Assert.That(SnapshotInterpolation.TimelineReset(-0.99, resetNegativeThresh, resetPositiveThresh), Is.False); + + // near positive thresh but not above it. no reset. + Assert.That(SnapshotInterpolation.TimelineReset(0.99, resetNegativeThresh, resetPositiveThresh), Is.False); + + // below negative thresh. reset. + Assert.That(SnapshotInterpolation.TimelineReset(-1.01, resetNegativeThresh, resetPositiveThresh), Is.True); + + // above positive thresh. reset. + Assert.That(SnapshotInterpolation.TimelineReset(1.01, resetNegativeThresh, resetPositiveThresh), Is.True); + } [Test] @@ -149,8 +171,8 @@ public void InsertTwice() double localTimescale = 0; // insert twice - SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, snap, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // should only be inserted once Assert.That(buffer.Count, Is.EqualTo(1)); @@ -171,8 +193,8 @@ public void Insert_Sorts() SimpleSnapshot b = new SimpleSnapshot(3, 0, 43); // insert in reverse order - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // should be in sorted order Assert.That(buffer.Count, Is.EqualTo(2)); @@ -195,11 +217,11 @@ public void Insert_InitializesLocalTimeline() SimpleSnapshot b = new SimpleSnapshot(3, 0, 43); // first insertion should initialize the local timeline to remote time - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2)); // second insertion should not modify the timeline again - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); Assert.That(localTimeline, Is.EqualTo(2)); } @@ -219,9 +241,9 @@ public void Insert_ComputesAverageDrift() SimpleSnapshot c = new SimpleSnapshot(5, 0, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // first insertion initializes localTime to '2'. // so the timediffs to '2' are: 0, 1, 3. @@ -245,9 +267,9 @@ public void Insert_ComputesAverageDrift_Scrambled() SimpleSnapshot c = new SimpleSnapshot(5, 0, 43); // insert scrambled (not in order) - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // first insertion initializes localTime to '2'. // so the timediffs to '2' are: 0, 3, 1. @@ -276,9 +298,9 @@ public void Insert_ComputesAverageDeliveryInterval() SimpleSnapshot c = new SimpleSnapshot(5, 6, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // first insertion doesn't compute delivery interval because we need 2 snaps. // second insertion computes 4-3 = 1 @@ -307,9 +329,9 @@ public void Insert_ComputesAverageDeliveryInterval_Scrambled() SimpleSnapshot c = new SimpleSnapshot(5, 6, 43); // insert in order - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // first insertion doesn't compute delivery interval because we need 2 snaps. // second insertion computes 4-3 = 1 @@ -334,9 +356,9 @@ public void Sample() SimpleSnapshot a = new SimpleSnapshot(10, 0, 42); SimpleSnapshot b = new SimpleSnapshot(20, 0, 43); SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 1, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // sample at a time before the first snapshot SnapshotInterpolation.Sample(buffer, 9, out int from, out int to, out double t); @@ -372,9 +394,9 @@ public void Step() SimpleSnapshot b = new SimpleSnapshot(20, 0, 43); SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // step half way to the next snapshot SnapshotInterpolation.Step(buffer, 5, ref localTimeline, localTimescale, out SimpleSnapshot fromSnapshot, out SimpleSnapshot toSnapshot, out double t); @@ -397,9 +419,9 @@ public void Step_RemovesOld() SimpleSnapshot b = new SimpleSnapshot(20, 0, 43); SimpleSnapshot c = new SimpleSnapshot(30, 0, 44); - SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); - SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, a, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, b, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); + SnapshotInterpolation.InsertAndAdjust(buffer, c, ref localTimeline, ref localTimescale, 0, 0, 0.01, 0.01, ref driftEma, 0, 0, -100, 100, ref deliveryIntervalEma); // step 1.5 snapshots worth, so way past the first one SnapshotInterpolation.Step(buffer, 15, ref localTimeline, localTimescale, out SimpleSnapshot fromSnapshot, out SimpleSnapshot toSnapshot, out double t);