public bool TryGetInterpolatedSnapshot(DateTime when, out TSnapshot result)
        {
            SnapshotEntry <TSnapshot> firstSnapshot  = null;
            SnapshotEntry <TSnapshot> secondSnapshot = null;

            foreach (var snapshot in storage)
            {
                if (snapshot.Timestamp < when)
                {
                    firstSnapshot = snapshot;
                }
                else
                {
                    secondSnapshot = snapshot;
                    break;
                }
            }

            if (firstSnapshot == null || secondSnapshot == null)
            {
                result = default(TSnapshot);
                return(false);
            }

            result = InterpolateSnapshots(firstSnapshot, secondSnapshot, when);
            return(true);
        }
        protected override MotionSnapshot InterpolateSnapshots(SnapshotEntry <MotionSnapshot> first, SnapshotEntry <MotionSnapshot> second, DateTime when)
        {
            var firstWeight  = (second.Timestamp - when).TotalMilliseconds / (second.Timestamp - first.Timestamp).TotalMilliseconds;
            var secondWeight = 1.0 - firstWeight;

            return(new MotionSnapshot {
                Position = first.Snapshot.Position.ScaleBy(firstWeight) + second.Snapshot.Position.ScaleBy(secondWeight),
                Yaw = (float)(first.Snapshot.Yaw * firstWeight + second.Snapshot.Yaw * secondWeight)
            });
        }
        public void Update()
        {
            var now = DateTime.Now;

            // add new snapshot entry
            var snapshot = TakeSnapshot();
            var entry    = new SnapshotEntry <TSnapshot> {
                Snapshot  = snapshot,
                Timestamp = now,
                Expires   = now + snapshotCullingExpiration
            };

            storage.Enqueue(entry);

            // cull old snapshot entries
            SnapshotEntry <TSnapshot> peekedEntry;

            while (storage.TryPeek(out peekedEntry) && peekedEntry.Expires < now)
            {
                SnapshotEntry <TSnapshot> throwaway;
                storage.TryDequeue(out throwaway);
            }
        }
 protected abstract TSnapshot InterpolateSnapshots(SnapshotEntry <TSnapshot> first, SnapshotEntry <TSnapshot> second, DateTime when);