예제 #1
0
 public void Add(MySnapshot value)
 {
     Active           = value.Active;
     Position        += value.Position;
     Rotation         = Rotation * Quaternion.Inverse(value.Rotation); Rotation.Normalize();
     LinearVelocity  += value.LinearVelocity;
     AngularVelocity += value.AngularVelocity;
 }
예제 #2
0
 public MySnapshot Diff(MySnapshot value0)
 {
     return(new MySnapshot()
     {
         Active = this.Active,
         Position = this.Position - value0.Position,
         Rotation = Quaternion.Inverse(this.Rotation) * value0.Rotation,
         LinearVelocity = this.LinearVelocity - value0.LinearVelocity,
         AngularVelocity = this.AngularVelocity - value0.AngularVelocity
     });
 }
예제 #3
0
 public MySnapshot Lerp(MySnapshot value2, float factor)
 {
     return(new MySnapshot()
     {
         Active = this.Active || value2.Active,
         Position = Vector3D.Lerp(this.Position, value2.Position, factor),
         Rotation = Quaternion.Slerp(this.Rotation, value2.Rotation, factor),
         LinearVelocity = Vector3.Lerp(this.LinearVelocity, value2.LinearVelocity, factor),
         AngularVelocity = Vector3.Lerp(this.AngularVelocity, value2.AngularVelocity, factor)
     });
 }
예제 #4
0
        public void ApplyDelta(MyTimeSpan timestamp, MySnapshot delta)
        {
            int i = 0;

            while (i < m_history.Count)
            {
                if (timestamp <= m_history[i].Timestamp)
                {
                    var item = m_history[i];
                    item.Snapshot.Add(delta);
                    m_history[i] = item;
                }
                i++;
            }
        }
예제 #5
0
        public void Read(BitStream stream, MyTimeSpan timeStamp)
        {
            var snapshot = new MySnapshot(stream);

            if (m_entity.Parent == null && m_entity.Physics != null)
            {
                if (m_entity.Physics.IsInWorld && m_entity.Physics.RigidBody != null && !m_entity.Physics.RigidBody.IsActive && snapshot.Active)
                {
                    m_entity.Physics.RigidBody.Activate();
                }
                if (m_entity.Physics.RigidBody == null || m_entity.Physics.RigidBody.IsActive)
                {
                    m_receivedQueue.Add(snapshot, timeStamp);
                }
            }
        }
예제 #6
0
        public void Add(MySnapshot snapshot, MyTimeSpan timestamp)
        {
            int exact = FindExact(timestamp);

            //  System.Diagnostics.Debug.Assert(exact == -1, "Timestamp " + timestamp + " already exist in history.");
            if (exact != -1)
            {
                return;
            }

            var item = new MyItem()
            {
                Valid     = true,
                Type      = SnapshotType.Exact,
                Timestamp = timestamp,
                Snapshot  = snapshot
            };
            int idx = FindIndex(timestamp);

            m_history.Insert(idx, item);
        }
예제 #7
0
        private MySnapshotHistory.MyItem UpdateFromServerQueue(MyTimeSpan clientTimestamp, MyPredictedSnapshotSyncSetup setup)
        {
            bool recalc     = false;
            var  serverItem = m_receivedQueue.GetItem(clientTimestamp);

            if (serverItem.Valid)
            {
                if (serverItem.Timestamp != m_lastServerTimestamp)
                {
                    var item = m_clientHistory.Get(serverItem.Timestamp, MyTimeSpan.Zero);
                    if (item.Valid && (item.Type == MySnapshotHistory.SnapshotType.Exact || item.Type == MySnapshotHistory.SnapshotType.Interpolation))
                    {
                        m_lastServerTimestamp = serverItem.Timestamp;
                        m_receivedQueue.Prune(clientTimestamp, MyTimeSpan.Zero, 3);
                        m_clientHistory.Prune(serverItem.Timestamp, MyTimeSpan.Zero, 10);

                        MySnapshot delta;
                        if (!serverItem.Snapshot.Active && !setup.IsControlled)
                        {
                            var currentSnapshot = new MySnapshot(m_entity);
                            delta = serverItem.Snapshot.Diff(currentSnapshot);
                            Reset();
                        }
                        else
                        {
                            delta = serverItem.Snapshot.Diff(item.Snapshot);
                        }
                        if (m_lastServerVelocity.IsValid())
                        {
                            var deltaVelocity = serverItem.Snapshot.LinearVelocity - m_lastServerVelocity;
                            m_lastServerVelocity = serverItem.Snapshot.LinearVelocity;

                            var deltaVelocityLengthSqr = deltaVelocity.LengthSquared();
                            if (m_stopSuspected > 0)
                            {
                                var currentSnapshot     = new MySnapshot(m_entity);
                                var maxVelocityDeltaSqr = (MinVelocityChangeToReset / 2) * (MinVelocityChangeToReset / 2);
                                if ((serverItem.Snapshot.LinearVelocity - currentSnapshot.LinearVelocity).LengthSquared() > maxVelocityDeltaSqr)
                                {
                                    Reset();
                                    delta           = serverItem.Snapshot.Diff(currentSnapshot);
                                    m_stopSuspected = 0;
                                }
                            }
                            if (deltaVelocityLengthSqr > (MinVelocityChangeToReset * MinVelocityChangeToReset))
                            {
                                m_stopSuspected = 10;
                                if (MyCompilationSymbols.EnableNetworkPositionTracking)
                                {
                                    VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.MPositions3, "!!!!!!!!!!!!!!!!!!! sudden server velocity change (" + m_entity.DisplayName + "): " + Math.Sqrt(deltaVelocityLengthSqr));
                                }
                            }
                            else if (m_stopSuspected > 0)
                            {
                                m_stopSuspected--;
                            }
                        }
                        else
                        {
                            m_lastServerVelocity = serverItem.Snapshot.LinearVelocity;
                        }
                        if (m_wasReset)
                        {
                            delta.Position     += serverItem.Snapshot.LinearVelocity * (float)(clientTimestamp - serverItem.Timestamp).Seconds;
                            m_wasReset          = false;
                            serverItem.Snapshot = delta;
                            serverItem.Type     = MySnapshotHistory.SnapshotType.Reset;
                            return(serverItem);
                        }

                        /*{
                         *  var lvsqr = delta.LinearVelocity.LengthSquared();
                         *  var maxLinearFactorSqr = setup.MaxLinearFactor * setup.MaxLinearFactor;
                         *  var maxLinVel = MaxLinearVelocityDelta * MaxLinearVelocityDelta * maxLinearFactorSqr;
                         *  if (lvsqr > maxLinVel)
                         *  {
                         *      var similarItem = m_clientHistory.GetSimilar(serverItem.Timestamp, serverItem.Snapshot.LinearVelocity);
                         *      if (similarItem.Valid)
                         *      {
                         *          var newDelta = serverItem.Snapshot.LinearVelocity - similarItem.Snapshot.LinearVelocity;
                         *          if (newDelta.LengthSquared() < maxLinVel)
                         *          {
                         *              if (MyCompilationSymbols.EnableNetworkClientControlledTracking)
                         *                  if (m_entity.DisplayName.Contains(m_trackName))
                         *                      VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.MPositions3,
                         *                          m_entity.DisplayName + ": old " + newDelta + " new " + delta.LinearVelocity +
                         *                          " ------------------------------------------" +
                         *                          serverItem.Snapshot + " >> " + item.Snapshot + " >> " + similarItem.Snapshot);
                         *              delta.LinearVelocity = Vector3.Zero;
                         *          }
                         *      }
                         *  }
                         * }*/
                        var  serverAngVelSqr         = serverItem.Snapshot.AngularVelocity.LengthSquared();
                        bool anyAngVel               = serverAngVelSqr > 0.001f;
                        var  minLinearVelocityFactor = Math.Max(Math.Min(serverItem.Snapshot.LinearVelocity.LengthSquared() /
                                                                         (ReferenceLinearVelocity * ReferenceLinearVelocity), 1.0f), 0.01f);
                        var minAngularVelocityFactor = Math.Max(Math.Min(serverAngVelSqr /
                                                                         (ReferenceAngularVelocity * ReferenceAngularVelocity), 1.0f), 0.01f);
                        int iterations   = (int)(SmoothTimesteps * setup.IterationsFactor);
                        var maxFactorSqr = setup.MaxPositionFactor * setup.MaxPositionFactor;

                        var anyDelta = setup.ApplyPhysics && setup.ApplyRotation && delta.AngularVelocity.LengthSquared() > 0.00001f;
                        // position
                        {
                            var psqr = delta.Position.LengthSquared();
                            if (psqr > MaxPositionDelta * MaxPositionDelta * maxFactorSqr)
                            {
                                var dir       = delta.Position;
                                var length    = dir.Normalize();
                                var newLength = length - MaxPositionDelta * (1.0f - DeltaFactor);
                                delta.Position = dir * newLength;
                                anyDelta       = true;
                                m_animDeltaPositionIterations = 0;
                            }
                            else if (!SmoothPositionCorrection)
                            {
                                delta.Position *= DeltaFactor;
                                anyDelta        = true;
                                m_animDeltaPositionIterations = 0;
                            }
                            else
                            {
                                if (psqr > MinPositionDelta * MinPositionDelta * minLinearVelocityFactor)
                                {
                                    m_animDeltaPositionIterations = iterations;
                                }
                                if (m_animDeltaPositionIterations > 0)
                                {
                                    m_animDeltaPosition          = delta.Position / m_animDeltaPositionIterations;
                                    m_animDeltaPositionTimestamp = serverItem.Timestamp;
                                }
                                delta.Position = Vector3D.Zero;
                            }
                        }
                        // rotation
                        if (setup.ApplyRotation)
                        {
                            Vector3 axis;
                            float   angle;
                            delta.Rotation.GetAxisAngle(out axis, out angle);

                            if (angle > MathHelper.Pi)
                            {
                                axis  = -axis;
                                angle = 2 * MathHelper.Pi - angle;
                            }
                            if (angle > MaxRotationAngle * setup.MaxRotationFactor)
                            {
                                delta.Rotation = Quaternion.CreateFromAxisAngle(axis, angle - MaxRotationAngle * (1.0f - DeltaFactor));
                                anyDelta       = true;
                                m_animDeltaRotationIterations = 0;
                            }
                            else if (!SmoothRotationCorrection)
                            {
                                delta.Rotation = Quaternion.CreateFromAxisAngle(axis, angle * DeltaFactor);
                                anyDelta       = true;
                                m_animDeltaRotationIterations = 0;
                            }
                            else
                            {
                                if (angle > MinRotationAngle * minAngularVelocityFactor)
                                {
                                    m_animDeltaRotationIterations = iterations;
                                }
                                if (m_animDeltaRotationIterations > 0)
                                {
                                    m_animDeltaRotation          = Quaternion.CreateFromAxisAngle(axis, angle / m_animDeltaRotationIterations);
                                    m_animDeltaRotationTimestamp = serverItem.Timestamp;
                                }
                                delta.Rotation = Quaternion.Identity;
                            }
                        }
                        if (setup.ApplyPhysics)
                        {
                            // linear velocity
                            {
                                var lvsqr = delta.LinearVelocity.LengthSquared();
                                if (!SmoothLinearVelocityCorrection)
                                {
                                    delta.LinearVelocity *= DeltaFactor;
                                    anyDelta              = true;
                                    m_animDeltaLinearVelocityIterations = 0;
                                }
                                else
                                {
                                    if (lvsqr > MinLinearVelocityDelta * MinLinearVelocityDelta)
                                    {
                                        m_animDeltaLinearVelocityIterations = iterations;
                                    }
                                    if (m_animDeltaLinearVelocityIterations > 0)
                                    {
                                        m_animDeltaLinearVelocity          = delta.LinearVelocity * DeltaFactor / m_animDeltaLinearVelocityIterations;
                                        m_animDeltaLinearVelocityTimestamp = serverItem.Timestamp;
                                    }
                                    delta.LinearVelocity = Vector3.Zero;
                                }
                            }
                            // angular velocity
                            {
                                var lvsqr = delta.AngularVelocity.LengthSquared();
                                if (!SmoothAngularVelocityCorrection)
                                {
                                    delta.AngularVelocity *= DeltaFactor;
                                    anyDelta = true;
                                    m_animDeltaAngularVelocityIterations = 0;
                                }
                                else
                                {
                                    if (lvsqr > MinAngularVelocityDelta * MinAngularVelocityDelta)
                                    {
                                        m_animDeltaAngularVelocityIterations = iterations;
                                    }
                                    if (m_animDeltaAngularVelocityIterations > 0)
                                    {
                                        m_animDeltaAngularVelocity          = delta.AngularVelocity * DeltaFactor / m_animDeltaAngularVelocityIterations;
                                        m_animDeltaAngularVelocityTimestamp = serverItem.Timestamp;
                                    }
                                    delta.AngularVelocity = Vector3.Zero;
                                }
                            }
                        }

                        if (!SetTransformCorrections)
                        {
                            delta.Position = Vector3D.Zero;
                            delta.Rotation = Quaternion.Identity;
                            m_animDeltaPositionIterations = m_animDeltaRotationIterations = 0;
                        }
                        if (!SetPhysicsCorrections)
                        {
                            delta.LinearVelocity  = Vector3.Zero;
                            delta.AngularVelocity = Vector3.Zero;
                            m_animDeltaLinearVelocityIterations = m_animDeltaAngularVelocityIterations = 0;
                        }

                        if (anyDelta)
                        {
                            if (MyCompilationSymbols.EnableNetworkPositionTracking)
                            {
                                if (m_entity.DisplayName.Contains(m_trackName))
                                {
                                    VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.MPositions3,
                                                             m_entity.DisplayName + ": " + serverItem.Snapshot + " >> " + item.Snapshot + " >> " + delta);
                                }
                            }
                        }
                        serverItem.Snapshot = delta;
                        serverItem.Valid    = anyDelta;
                    }
                    else
                    {
                        serverItem.Valid = false;
                        recalc           = m_wasReset;
                        if (!m_wasReset && MyCompilationSymbols.EnableNetworkPositionTracking)
                        {
                            MyTrace.Send(TraceWindow.MPositions3,
                                         "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + m_entity.DisplayName + ": " + item.Type);
                        }
                    }
                }
                else
                {
                    serverItem.Valid = false;
                    recalc           = m_wasReset;
                }
            }
            else
            {
                if (!m_receivedQueue.Empty())
                {
                    recalc = true;
                }
                m_clientHistory.Prune(clientTimestamp, MyTimeSpan.FromMilliseconds(1500));
            }
            if (recalc)
            {
                serverItem = m_receivedQueue.Get(clientTimestamp, MyTimeSpan.Zero);
                if (serverItem.Valid && serverItem.Type == MySnapshotHistory.SnapshotType.Exact ||
                    serverItem.Type == MySnapshotHistory.SnapshotType.Interpolation ||
                    serverItem.Type == MySnapshotHistory.SnapshotType.Extrapolation)
                {
                    var currentSnapshot = new MySnapshot(m_entity);
                    var delta           = serverItem.Snapshot.Diff(currentSnapshot);
                    serverItem.Valid    = true;
                    serverItem.Snapshot = delta;
                    serverItem.Type     = MySnapshotHistory.SnapshotType.Reset;
                    return(serverItem);
                }
                else
                {
                    serverItem.Valid = false;
                    if (MyCompilationSymbols.EnableNetworkPositionTracking)
                    {
                        MyTrace.Send(TraceWindow.MPositions3,
                                     "------------------------------------------- " + m_entity.DisplayName + ": " +
                                     m_receivedQueue.ToStringTimestamps() + " / " + serverItem.Type);
                    }
                }
            }
            return(serverItem);
        }
예제 #8
0
        public void Write(BitStream stream)
        {
            var snapshot = new MySnapshot(m_entity);

            snapshot.Write(stream);
        }
예제 #9
0
        public void UpdatePrediction(MyTimeSpan clientTimestamp, MySnapshotSyncSetup setup)
        {
            var currentSnapshot = new MySnapshot(m_entity);
            var tmpSnapshot     = currentSnapshot;

            m_clientHistory.Add(currentSnapshot, clientTimestamp);

            var  serverTmpSnapshot = m_receivedQueue.GetItem(clientTimestamp);
            var  timeDelta         = (float)(m_lastServerTimestamp - serverTmpSnapshot.Timestamp).Seconds;
            var  predictedSetup    = setup as MyPredictedSnapshotSyncSetup;
            var  serverDeltaItem   = UpdateFromServerQueue(clientTimestamp, predictedSetup);
            bool animated          = m_animDeltaPositionIterations > 0 || m_animDeltaLinearVelocityIterations > 0 || m_animDeltaRotationIterations > 0 ||
                                     m_animDeltaAngularVelocityIterations > 0;
            bool applySnapshot = false;

            if (serverDeltaItem.Valid)
            {
                currentSnapshot.Add(serverDeltaItem.Snapshot);
                m_clientHistory.ApplyDelta(serverDeltaItem.Timestamp, serverDeltaItem.Snapshot);
                applySnapshot = true;
            }

            if (animated)
            {
                if (m_animDeltaPositionIterations > 0)
                {
                    m_clientHistory.ApplyDeltaPosition(m_animDeltaPositionTimestamp, m_animDeltaPosition);
                    currentSnapshot.Position += m_animDeltaPosition;
                    m_animDeltaPositionIterations--;
                }
                if (m_animDeltaLinearVelocityIterations > 0)
                {
                    m_clientHistory.ApplyDeltaLinearVelocity(m_animDeltaLinearVelocityTimestamp, m_animDeltaLinearVelocity);
                    currentSnapshot.LinearVelocity += m_animDeltaLinearVelocity;
                    m_animDeltaLinearVelocityIterations--;
                }
                if (m_animDeltaAngularVelocityIterations > 0)
                {
                    m_clientHistory.ApplyDeltaAngularVelocity(m_animDeltaAngularVelocityTimestamp, m_animDeltaAngularVelocity);
                    currentSnapshot.AngularVelocity += m_animDeltaAngularVelocity;
                    m_animDeltaAngularVelocityIterations--;
                }
                if (m_animDeltaRotationIterations > 0)
                {
                    m_clientHistory.ApplyDeltaRotation(m_animDeltaRotationTimestamp, m_animDeltaRotation);
                    currentSnapshot.Rotation = currentSnapshot.Rotation * Quaternion.Inverse(m_animDeltaRotation);
                    currentSnapshot.Rotation.Normalize();
                    m_animDeltaRotationIterations--;
                }

                applySnapshot = true;
            }
            if (applySnapshot)
            {
                currentSnapshot.Apply(m_entity, setup.ApplyRotation, setup.ApplyPhysics, serverDeltaItem.Type == MySnapshotHistory.SnapshotType.Reset);
            }

            //if (MyCompilationSymbols.EnableNetworkClientUpdateTracking)
            {
                if (m_entity.DisplayName.Contains("dicykal") && (serverDeltaItem.Valid || animated))
                {
                    var velocity = (serverTmpSnapshot.Snapshot.Position - m_lastServerSnapshot.Position) / timeDelta;
                    m_lastServerSnapshot = serverTmpSnapshot.Snapshot;

                    var clientTimeDelta = (float)(m_lastClientTimestamp - clientTimestamp).Seconds;
                    var clientVelocity  = (currentSnapshot.Position - m_lastClientSnapshot.Position) / clientTimeDelta;
                    m_lastClientSnapshot  = currentSnapshot;
                    m_lastClientTimestamp = clientTimestamp;

                    VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.MPositions3, m_entity.DisplayName + ": " +
                                             tmpSnapshot + " / " + currentSnapshot + " / " + serverTmpSnapshot.Snapshot + "; cvel " + velocity + " / " + clientVelocity + "; " +
                                             serverDeltaItem.Valid + ", " + animated + "; " + m_animDeltaPosition * 60);

                    /*var delta = tmpSnapshot.Diff(currentSnapshot);
                     * var posLen = delta.Position.Length();
                     * var lenLV = delta.LinearVelocity.Length();
                     * var sdPosLen = serverDeltaItem.Snapshot.Position.Length();
                     * var aPosLen = m_animDeltaPosition.Length();
                     *
                     * VRage.Trace.MyTrace.Send(VRage.Trace.TraceWindow.MPositions3, m_entity.DisplayName +
                     *  ": pos " + delta.Position + " / " + posLen + " lv " + tmpSnapshot.LinearVelocity + " / " + lenLV +
                     *  "; sdelta " + serverDeltaItem.Valid + " pos " + serverDeltaItem.Snapshot.Position + " / " + sdPosLen +
                     *  " anim " + m_animDeltaPositionIterations + " pos " + m_animDeltaPosition + " / " + aPosLen);*/
                }
            }
        }
        void IMySnapshotSync.Read(BitStream stream, MyTimeSpan timeStamp)
        {
            var item = new MySnapshot(stream);

            m_history.Add(item, timeStamp);
        }
        void IMySnapshotSync.Write(BitStream stream)
        {
            var item = new MySnapshot(m_entity);

            item.Write(stream);
        }