示例#1
0
 public RigidBodyState(Guid id, float time, RigidBodyTransform transform, bool hasUpdate, MotionType mType)
 {
     Id         = id;
     LocalTime  = time;
     Transform  = transform;
     HasUpdate  = hasUpdate;
     motionType = mType;
 }
            public void Update(ref RigidBodyData entry)
            {
                while (_nextIndex < _next.Transforms.Count &&
                       _next.Transforms[_nextIndex].RigidBodyId.CompareTo(entry.RigidBodyId) < 0)
                {
                    _nextIndex++;
                }

                while (_prevIndex < _prev.Transforms.Count &&
                       _prev.Transforms[_prevIndex].RigidBodyId.CompareTo(entry.RigidBodyId) < 0)
                {
                    _prevIndex++;
                }

                if (_nextIndex >= _next.Transforms.Count ||
                    _next.Transforms[_nextIndex].RigidBodyId != entry.RigidBodyId)
                {
                    // velocity is zero
                    entry.SetZeroVelocities();

                    if (entry.MotionType == MotionType.Sleeping)
                    {
                        entry.Time    = _timestamp;
                        entry.Updated = true;
                    }
                    else
                    {
                        entry.Updated = false;
                    }
                    return;
                }

                if (_prevIndex < _prev.Transforms.Count &&
                    _prev.Transforms[_prevIndex].RigidBodyId == _next.Transforms[_nextIndex].RigidBodyId)
                {
                    RigidBodyTransform t = new RigidBodyTransform();
                    {
                        t.Lerp(_prev.Transforms[_prevIndex].Transform, _next.Transforms[_nextIndex].Transform, _frac);
                    }
                    entry.Transform = t;
                    entry.SetZeroVelocities();
                    // estimate velocity
                    float DT       = _next.Time - _prev.Time;
                    var   prevT    = _prev.Transforms[_prevIndex].Transform;
                    var   currentT = _next.Transforms[_nextIndex].Transform;
                    entry.SetVelocitiesFromTransformsDiff(DT, currentT, prevT);
                }
                else
                {
                    entry.Transform = _next.Transforms[_nextIndex].Transform;
                    entry.SetZeroVelocities();
                }

                entry.Time       = _timestamp;
                entry.MotionType = _next.Transforms[_nextIndex].MotionType;
                entry.Updated    = true;
            }
 public RigidBodyState(Guid id, float time, RigidBodyTransform transform,
                       Vector3 linearVelocity, Vector3 angularVelocity,
                       bool hasUpdate, MotionType mType)
 {
     Id              = id;
     LocalTime       = time;
     Transform       = transform;
     LinearVelocity  = linearVelocity;
     AngularVelocity = angularVelocity;
     HasUpdate       = hasUpdate;
     motionType      = mType;
 }
 public void SetVelocitiesFromTransformsDiff(float DT, RigidBodyTransform current,
                                             RigidBodyTransform prev)
 {
     if (Math.Abs(DT) > 0.0005f)
     {
         float invUpdateDT = 1.0f / (DT);                     // DT has to be different from zero
         UnityEngine.Vector3 eulerAngles  = (UnityEngine.Quaternion.Inverse(prev.Rotation) * current.Rotation).eulerAngles;
         UnityEngine.Vector3 radianAngles = UtilMethods.TransformEulerAnglesToRadians(eulerAngles);
         //if (radianAngles.sqrMagnitude < 0.02F)
         //{
         //	Debug.Log("NULL DT=" + DT + " prevRot=" + prev.Rotation.ToString() + " next=" + current.Rotation.ToString());
         //}
         AngularVelocity = radianAngles * invUpdateDT;
         LinearVelocity  = (current.Position - prev.Position) * invUpdateDT;
     }
 }
 public TransformInfo(Guid rigidBodyId, RigidBodyTransform transform, MotionType motionType)
 {
     RigidBodyId = rigidBodyId;
     Transform   = transform;
     MotionType  = motionType;
 }
 public void Lerp(RigidBodyTransform t0, RigidBodyTransform t1, float f)
 {
     Position = Vector3.Lerp(t0.Position, t1.Position, f);
     Rotation = Quaternion.Lerp(t0.Rotation, t1.Rotation, f);
 }
示例#7
0
        public void AddAndProcessRemoteBodyForPrediction(RigidBodyPhysicsBridgeInfo rb,
                                                         RigidBodyTransform transform, UnityEngine.Vector3 keyFramedPos,
                                                         UnityEngine.Quaternion keyFramedOrientation, float timeOfSnapshot,
                                                         PredictionTimeParameters timeInfo)
        {
            var collisionInfo = new CollisionSwitchInfo();

            collisionInfo.startPosition    = rb.RigidBody.transform.position;
            collisionInfo.startOrientation = rb.RigidBody.transform.rotation;
            collisionInfo.rigidBodyId      = rb.Id;
            collisionInfo.isKeyframed      = rb.IsKeyframed;
            // test is this remote body is in the monitor stream or if this is grabbed & key framed then this should not be dynamic
            if (_monitorCollisionInfo.ContainsKey(rb.Id) && !rb.IsKeyframed)
            {
                // dynamic
                rb.RigidBody.isKinematic  = false;
                collisionInfo.monitorInfo = _monitorCollisionInfo[rb.Id];
                collisionInfo.monitorInfo.timeFromStartCollision += timeInfo.DT;
                collisionInfo.linearVelocity  = rb.RigidBody.velocity;
                collisionInfo.angularVelocity = rb.RigidBody.angularVelocity;
#if MRE_PHYSICS_DEBUG
                Debug.Log(" Remote body: " + rb.Id.ToString() + " is dynamic since:"
                          + collisionInfo.monitorInfo.timeFromStartCollision + " relative distance:" + collisionInfo.monitorInfo.relativeDistance
                          + " interpolation:" + collisionInfo.monitorInfo.keyframedInterpolationRatio);
#endif
                // if time passes by then make a transformation between key framed and dynamic
                // but only change the positions not the velocity
                if (collisionInfo.monitorInfo.keyframedInterpolationRatio > 0.05f)
                {
                    // interpolate between key framed and dynamic transforms
                    float t = collisionInfo.monitorInfo.keyframedInterpolationRatio;
                    UnityEngine.Vector3    interpolatedPos;
                    UnityEngine.Quaternion interpolatedQuad;
                    interpolatedPos  = t * keyFramedPos + (1.0f - t) * rb.RigidBody.transform.position;
                    interpolatedQuad = UnityEngine.Quaternion.Slerp(keyFramedOrientation, rb.RigidBody.transform.rotation, t);
#if MRE_PHYSICS_DEBUG
                    Debug.Log(" Interpolate body " + rb.Id.ToString() + " t=" + t
                              + " time=" + UnityEngine.Time.time
                              + " pos KF:" + keyFramedPos
                              + " dyn:" + rb.RigidBody.transform.position
                              + " interp pos:" + interpolatedPos
                              + " rb vel:" + rb.RigidBody.velocity
                              + " KF vel:" + rb.lastValidLinerVelocity);
#endif
                    // apply these changes only if they are significant in order to not to bother the physics engine
                    // for settled objects
                    UnityEngine.Vector3 posdiff = rb.RigidBody.transform.position - interpolatedPos;
                    if (posdiff.magnitude > interpolationPosEpsilon)
                    {
                        rb.RigidBody.transform.position = interpolatedPos;
                    }
                    float angleDiff = Math.Abs(
                        UnityEngine.Quaternion.Angle(rb.RigidBody.transform.rotation, interpolatedQuad));
                    if (angleDiff > interpolationAngularEps)
                    {
                        rb.RigidBody.transform.rotation = interpolatedQuad;
                    }

                    // apply velocity damping if we are in the interpolation phase
                    if (collisionInfo.monitorInfo.keyframedInterpolationRatio >= velocityDampingInterpolationValueStart)
                    {
                        rb.RigidBody.velocity        *= velocityDampingForInterpolation;
                        rb.RigidBody.angularVelocity *= velocityDampingForInterpolation;
                    }
                }
            }
            else
            {
                // 100% key framing
                rb.RigidBody.isKinematic        = true;
                rb.RigidBody.transform.position = keyFramedPos;
                rb.RigidBody.transform.rotation = keyFramedOrientation;
                rb.RigidBody.velocity.Set(0.0f, 0.0f, 0.0f);
                rb.RigidBody.angularVelocity.Set(0.0f, 0.0f, 0.0f);
                collisionInfo.linearVelocity  = rb.lastValidLinerVelocity;
                collisionInfo.angularVelocity = rb.lastValidAngularVelocity;
                collisionInfo.monitorInfo     = new CollisionMonitorInfo();
#if MRE_PHYSICS_DEBUG
                if (rb.IsKeyframed)
                {
                    Debug.Log(" Remote body: " + rb.Id.ToString() + " is key framed:"
                              + " linvel:" + collisionInfo.linearVelocity
                              + " angvel:" + collisionInfo.angularVelocity);
                }
#endif
            }
            // <todo> add more filtering here to cancel out unnecessary items,
            // but for small number of bodies should be OK
            _switchCollisionInfos.Add(collisionInfo);
        }
示例#8
0
 public TransformInfo(Guid id, RigidBodyTransform transform, MotionType mType)
 {
     Id         = id;
     Transform  = transform;
     motionType = mType;
 }
示例#9
0
            public void step(float timestep)
            {
                if (_mode == Mode.Init)
                {
                    // todo: do we need this warm up?
                    if (SnapshotBuffer.Snapshots.Count >= 4)
                    {
                        _mode = Mode.Play;

                        CurrentSnapshot  = SnapshotBuffer.Snapshots.First().Value;
                        CurrentLocalTime = CurrentSnapshot.Time;
                    }
                }
                else if (_mode != Mode.Init)
                {
                    // todo: consider exposing as a parameter or calculating based on local and remote timesteps.
                    const float bufferTimeBiasTimeUnit = 1.0f / 60;

                    float targetBufferTime       = _stats.mean() - _stats.deviation();
                    float biasedTargetBufferTime = targetBufferTime / bufferTimeBiasTimeUnit;

                    biasedTargetBufferTime = biasedTargetBufferTime > 0 ?
                                             ((int)biasedTargetBufferTime) * bufferTimeBiasTimeUnit : ((int)biasedTargetBufferTime - 1) * bufferTimeBiasTimeUnit;

                    float nextTimestamp = CurrentLocalTime + timestep;
                    float bufferedTime  = SnapshotBuffer.Snapshots.Last().Value.Time - nextTimestamp;

                    _stats.addSample(bufferedTime);

                    // check if time shift is required
                    float timeShift;
                    if (Math.Abs(biasedTargetBufferTime) > 0.001)
                    {
                        // todo: limit slow-down, don't allow time to move to the past
                        timeShift = biasedTargetBufferTime > 0 ?
                                    _speedUpCoef * biasedTargetBufferTime : _speedDownCoef * biasedTargetBufferTime;

                        nextTimestamp += timeShift;
                        _stats.shiftTime(-timeShift);
                    }
                    else
                    {
                        timeShift = 0;
                    }

#if DEBUG_JITTER_BUFFER
                    _debugStats.add(bufferedTime, _stats.mean(), targetBufferTime, biasedTargetBufferTime, timeShift, nextTimestamp);
#endif

                    if (nextTimestamp <= SnapshotBuffer.Snapshots.Last().Value.Time)
                    {
                        // Snapshot can be interpolated from the buffers
                        HasUpdate = true;

                        Snapshot prev, next;
                        SnapshotBuffer.step(nextTimestamp, out prev, out next);

                        if (Math.Abs(next.Time - nextTimestamp) < 0.001)
                        {
                            // if offset is less than a millisecond, just use 'next' snapshot time
                            CurrentLocalTime = next.Time;
                            CurrentSnapshot  = next;
                        }
                        else if (prev != null)
                        {
                            if (Math.Abs(prev.Time - nextTimestamp) < 0.001)
                            {
                                // if offset is less than a millisecond, just use 'prev' snapshot time
                                CurrentLocalTime = prev.Time;
                                CurrentSnapshot  = prev;
                            }
                            else
                            {
                                float frac = (nextTimestamp - prev.Time) / (next.Time - prev.Time);

                                List <Snapshot.TransformInfo> transforms = new List <Snapshot.TransformInfo>(next.Transforms.Count);

                                int prevIndex = 0;
                                int nextIndex = 0;

                                for (; nextIndex < next.Transforms.Count; nextIndex++)
                                {
                                    // find corresponding transform in prev snapshot
                                    while (prevIndex < prev.Transforms.Count && prev.Transforms[prevIndex].Id.CompareTo(next.Transforms[nextIndex].Id) < 0)
                                    {
                                        prevIndex++;
                                    }

                                    if (prevIndex < prev.Transforms.Count &&
                                        prev.Transforms[prevIndex].Id == next.Transforms[nextIndex].Id)
                                    {
                                        RigidBodyTransform t = new RigidBodyTransform();
                                        {
                                            t.Lerp(prev.Transforms[prevIndex].Transform, next.Transforms[nextIndex].Transform, frac);
                                        }

                                        transforms.Add(new Snapshot.TransformInfo(next.Transforms[nextIndex].Id, t,
                                                                                  next.Transforms[nextIndex].motionType));
                                    }
                                    else
                                    {
                                        transforms.Add(new Snapshot.TransformInfo(next.Transforms[nextIndex].Id,
                                                                                  next.Transforms[nextIndex].Transform, next.Transforms[nextIndex].motionType));
                                    }
                                }

                                // interpolated snapshot
                                CurrentLocalTime = nextTimestamp;
                                CurrentSnapshot  = new Snapshot(nextTimestamp, transforms);
                            }
                        }
                        else
                        {
                            // if prev snapshot is missing, just use current transforms with past timestamp
                            CurrentLocalTime = nextTimestamp;
                            CurrentSnapshot  = next;
                        }
                    }
                    else
                    {
                        // Snapshot can not be interpolated from the buffers
                        HasUpdate = false;

                        CurrentLocalTime = nextTimestamp;
                        CurrentSnapshot  = new Snapshot(CurrentLocalTime, CurrentSnapshot.Transforms);
                    }
                }
            }
示例#10
0
        public void AddAndProcessRemoteBodyForPrediction(RigidBodyPhysicsBridgeInfo rb,
                                                         RigidBodyTransform transform, Godot.Vector3 keyFramedPos,
                                                         Godot.Quat keyFramedOrientation, float timeOfSnapshot,
                                                         PredictionTimeParameters timeInfo)
        {
            var collisionInfo = new CollisionSwitchInfo();

            collisionInfo.startPosition    = rb.RigidBody.GlobalTransform.origin;
            collisionInfo.startOrientation = rb.RigidBody.GlobalTransform.basis.RotationQuat();
            collisionInfo.rigidBodyId      = rb.Id;
            collisionInfo.isKeyframed      = rb.IsKeyframed;
            // test is this remote body is in the monitor stream or if this is grabbed & key framed then this should not be dynamic
            if (_monitorCollisionInfo.ContainsKey(rb.Id) && !rb.IsKeyframed)
            {
                // dynamic
                if (rb.RigidBody.Mode != Godot.RigidBody.ModeEnum.Rigid)
                {
                    rb.RigidBody.Mode = Godot.RigidBody.ModeEnum.Rigid;
                }
                collisionInfo.monitorInfo = _monitorCollisionInfo[rb.Id];
                collisionInfo.monitorInfo.timeFromStartCollision += timeInfo.DT;
                collisionInfo.linearVelocity  = rb.RigidBody.LinearVelocity;
                collisionInfo.angularVelocity = rb.RigidBody.AngularVelocity;
#if MRE_PHYSICS_DEBUG
                GD.Print(" Remote body: " + rb.Id.ToString() + " is dynamic since:"
                         + collisionInfo.monitorInfo.timeFromStartCollision + " relative distance:" + collisionInfo.monitorInfo.relativeDistance
                         + " interpolation:" + collisionInfo.monitorInfo.keyframedInterpolationRatio);
#endif
                // if time passes by then make a transformation between key framed and dynamic
                // but only change the positions not the velocity
                if (collisionInfo.monitorInfo.keyframedInterpolationRatio > 0.05f)
                {
                    // interpolate between key framed and dynamic transforms
                    float         t = collisionInfo.monitorInfo.keyframedInterpolationRatio;
                    Godot.Vector3 interpolatedPos;
                    Godot.Quat    interpolatedQuad;
                    interpolatedPos  = t * keyFramedPos + (1.0f - t) * rb.RigidBody.GlobalTransform.origin;
                    interpolatedQuad = keyFramedOrientation.Slerp(rb.RigidBody.GlobalTransform.basis.RotationQuat(), t);
#if MRE_PHYSICS_DEBUG
                    GD.Print(" Interpolate body " + rb.Id.ToString() + " t=" + t
                             + " time=" + OS.GetTicksMsec() * 0.001
                             + " pos KF:" + keyFramedPos
                             + " dyn:" + rb.RigidBody.Transform.origin
                             + " interp pos:" + interpolatedPos
                             + " rb vel:" + rb.RigidBody.LinearVelocity
                             + " KF vel:" + rb.lastValidLinerVelocityOrPos);
#endif
                    // apply these changes only if they are significant in order to not to bother the physics engine
                    // for settled objects
                    Godot.Vector3 posdiff         = rb.RigidBody.GlobalTransform.origin - interpolatedPos;
                    Vector3       rigidBodyOrigin = rb.RigidBody.GlobalTransform.origin;
                    Basis         rigidBodyBasis  = rb.RigidBody.GlobalTransform.basis;
                    if (posdiff.Length() > interpolationPosEpsilon)
                    {
                        rigidBodyOrigin = interpolatedPos;
                    }
                    float angleDiff = Math.Abs(Mathf.Rad2Deg(rigidBodyBasis.GetEuler().AngleTo(interpolatedQuad.GetEuler())));
                    if (angleDiff > interpolationAngularEps)
                    {
                        rigidBodyBasis = new Basis(interpolatedQuad);
                    }
                    rb.RigidBody.GlobalTransform = new Transform(rigidBodyBasis, rigidBodyOrigin);

                    // apply velocity damping if we are in the interpolation phase
                    if (collisionInfo.monitorInfo.keyframedInterpolationRatio >= velocityDampingInterpolationValueStart)
                    {
                        rb.RigidBody.LinearVelocity  *= velocityDampingForInterpolation;
                        rb.RigidBody.AngularVelocity *= velocityDampingForInterpolation;
                    }
                }
            }
            else
            {
                // 100% key framing
                if (rb.RigidBody.Mode != Godot.RigidBody.ModeEnum.Kinematic)
                {
                    rb.RigidBody.Mode = Godot.RigidBody.ModeEnum.Kinematic;
                }
                rb.RigidBody.GlobalTransform  = new Transform(new Basis(keyFramedOrientation), keyFramedPos);
                rb.RigidBody.LinearVelocity   = new Vector3(0.0f, 0.0f, 0.0f);
                rb.RigidBody.AngularVelocity  = new Vector3(0.0f, 0.0f, 0.0f);
                collisionInfo.linearVelocity  = rb.lastValidLinerVelocityOrPos;
                collisionInfo.angularVelocity = rb.lastValidAngularVelocityorAng;
                collisionInfo.monitorInfo     = new CollisionMonitorInfo();
#if MRE_PHYSICS_DEBUG
                if (rb.IsKeyframed)
                {
                    GD.Print(" Remote body: " + rb.Id.ToString() + " is key framed:"
                             + " linvel:" + collisionInfo.linearVelocity
                             + " angvel:" + collisionInfo.angularVelocity);
                }
#endif
            }
            // <todo> add more filtering here to cancel out unnecessary items,
            // but for small number of bodies should be OK
            _switchCollisionInfos.Add(collisionInfo);
        }
示例#11
0
 public void Lerp(RigidBodyTransform t0, RigidBodyTransform t1, float f)
 {
     Position = t0.Position.LinearInterpolate(t1.Position, f);
     // FIXEM: There is no Quat.Lerp.
     Rotation = t0.Rotation.Slerp(t1.Rotation, f);
 }