Пример #1
0
            public OneActorUpdate(Guid id, Godot.Vector3 localPos, Godot.Quat localQuat,
                                  Godot.Vector3 appPos, Godot.Quat appQuat)
            {
                localTransform = new TransformPatch();
                appTransform   = new TransformPatch();

                localTransform.Position = new Vector3Patch(localPos);
                localTransform.Rotation = new QuaternionPatch(localQuat);

                appTransform.Position = new Vector3Patch(appPos);
                appTransform.Rotation = new QuaternionPatch(appQuat);

                actorGuid = id;
            }
Пример #2
0
 public Transform(Quat quat, Vector3 origin)
 {
     basis       = new Basis(quat);
     this.origin = origin;
 }
Пример #3
0
 private void Rotate(Quat quat)
 {
     this *= new Basis(quat);
 }
Пример #4
0
 internal void SetQuantScale(Quat quat, Vector3 scale)
 {
     SetDiagonal(scale);
     Rotate(quat);
 }
Пример #5
0
        public void FixedUpdate(Spatial root)
        {
            // - physics rigid body management
            // -set transforms/velocities for key framed bodies

            // get all the prediction time infos in this struct
            PredictionTimeParameters timeInfo = new PredictionTimeParameters(1f / Engine.IterationsPerSecond);

            // start the predictor
            _predictor.StartBodyPredicitonForNextFrame();

            int index = 0;
            MultiSourceCombinedSnapshot snapshot;

            _snapshotManager.Step(timeInfo.DT, out snapshot);
            _snapshotManager.UpdateDebugDisplay(root);             // guarded by ifdef internally

            foreach (var rb in _rigidBodies.Values)
            {
                // if the body is owned then we only set the kinematic flag for the physics
                if (rb.Ownership)
                {
                    if (rb.IsKeyframed)
                    {
                        if (rb.RigidBody.Mode != Godot.RigidBody.ModeEnum.Kinematic)
                        {
                            rb.RigidBody.Mode = Godot.RigidBody.ModeEnum.Kinematic;
                        }
                    }
                    else
                    {
                        if (rb.RigidBody.Mode != Godot.RigidBody.ModeEnum.Rigid)
                        {
                            rb.RigidBody.Mode = Godot.RigidBody.ModeEnum.Rigid;
                        }
                    }
                    continue;
                }

                // Find corresponding rigid body info.
                // since both are sorted list this should hit without index=0 at the beginning
                while (index < snapshot.RigidBodies.Count && rb.Id.CompareTo(snapshot.RigidBodies.Values[index].Id) > 0)
                {
                    index++;
                }

                if (index < snapshot.RigidBodies.Count && rb.Id == snapshot.RigidBodies.Values[index].Id)
                {
                    // todo: kick-in prediction if we are missing an update for this rigid body
                    //if (!snapshot.RigidBodies.Values[index].HasUpdate)
                    //{
                    //	rb.RigidBody.isKinematic = false;
                    //	continue;
                    //}

                    RigidBodyTransform transform = snapshot.RigidBodies.Values[index].Transform;
                    float timeOfSnapshot         = snapshot.RigidBodies.Values[index].LocalTime;

                    // get the key framed stream, and compute implicit velocities
                    Godot.Vector3 keyFramedPos         = root.ToGlobal(transform.Position);
                    Godot.Quat    keyFramedOrientation = root.GlobalTransform.basis.RotationQuat() * transform.Rotation;
                    Godot.Vector3 JBLinearVelocity     =
                        root.GlobalTransform.basis.GetEuler() * snapshot.RigidBodies.Values[index].LinearVelocity;
                    Godot.Vector3 JBAngularVelocity =
                        root.GlobalTransform.basis.GetEuler() * snapshot.RigidBodies.Values[index].AngularVelocity;
                    // if there is a really new update then also store the implicit velocity
                    if (rb.lastTimeKeyFramedUpdate < timeOfSnapshot)
                    {
                        // we moved the velocity estimation into the jitter buffer
                        rb.lastValidLinerVelocityOrPos   = JBLinearVelocity;
                        rb.lastValidAngularVelocityorAng = JBAngularVelocity;

#if MRE_PHYSICS_DEBUG
                        // test the source of large velocities
                        if (rb.lastValidLinerVelocityOrPos.LengthSquared() > _maxEstimatedLinearVelocity * _maxEstimatedLinearVelocity)
                        {
                            // limited debug version
                            GD.Print(" ACTIVE SPEED LIMIT TRAP RB: "                             //+ rb.Id.ToString() + " got update lin vel:"
                                     + rb.lastValidLinerVelocityOrPos + " ang vel:" + rb.lastValidAngularVelocityorAng
                                     + " time:" + timeOfSnapshot
                                     + " newR:" + rb.lastTimeKeyFramedUpdate
                                     + " hasupdate:" + snapshot.RigidBodies.Values[index].HasUpdate);
                            //+  " DangE:" + eulerAngles + " DangR:" + radianAngles );
                        }
#endif

                        // cap the velocities
                        rb.lastValidLinerVelocityOrPos = ClampLength(
                            rb.lastValidLinerVelocityOrPos, _maxEstimatedLinearVelocity);
                        rb.lastValidAngularVelocityorAng = ClampLength(
                            rb.lastValidAngularVelocityorAng, _maxEstimatedAngularVelocity);
                        // if body is sleeping then all velocities are zero
                        if (snapshot.RigidBodies.Values[index].motionType == Patching.Types.MotionType.Sleeping)
                        {
                            rb.lastValidLinerVelocityOrPos   = new Vector3(0.0F, 0.0F, 0.0F);
                            rb.lastValidAngularVelocityorAng = new Vector3(0.0F, 0.0F, 0.0F);
                        }
#if MRE_PHYSICS_DEBUG
                        if (true)
                        {
                            // limited debug version
                            GD.Print(" Remote body: " + rb.Id.ToString() + " got update lin vel:"
                                     + rb.lastValidLinerVelocityOrPos + " ang vel:" + rb.lastValidAngularVelocityorAng
                                     + " time:" + timeOfSnapshot + " newR:" + rb.lastTimeKeyFramedUpdate);
                        }
                        else
                        {
                            GD.Print(" Remote body: " + rb.Id.ToString() + " got update lin vel:"
                                     + rb.lastValidLinerVelocityOrPos + " ang vel:" + rb.lastValidAngularVelocityorAng
                                     //+ " DangE:" + eulerAngles + " DangR:" + radianAngles
                                     + " time:" + timeOfSnapshot + " newp:" + keyFramedPos
                                     + " newR:" + keyFramedOrientation
                                     + " oldP:" + rb.RigidBody.GlobalTransform.origin
                                     + " oldR:" + rb.RigidBody.GlobalTransform.basis.RotationQuat()
                                     + " OriginalRot:" + transform.Rotation
                                     //+ " keyF:" + rb.RigidBody.isKinematic
                                     + " KF:" + rb.IsKeyframed);
                        }
#endif
                        // cap the velocities
                        rb.lastValidLinerVelocityOrPos = ClampLength(
                            rb.lastValidLinerVelocityOrPos, _maxEstimatedLinearVelocity);
                        rb.lastValidAngularVelocityorAng = ClampLength(
                            rb.lastValidAngularVelocityorAng, _maxEstimatedAngularVelocity);
                        // if body is sleeping then all velocities are zero
                        if (snapshot.RigidBodies.Values[index].motionType == Patching.Types.MotionType.Sleeping)
                        {
                            rb.lastValidLinerVelocityOrPos   = new Vector3(0.0F, 0.0F, 0.0F);
                            rb.lastValidAngularVelocityorAng = new Vector3(0.0F, 0.0F, 0.0F);
                        }
#if MRE_PHYSICS_DEBUG
                        GD.Print(" Remote body: " + rb.Id.ToString() + " got update lin vel:"
                                 + rb.lastValidLinerVelocityOrPos + " ang vel:" + rb.lastValidAngularVelocityorAng
                                 //+ " DangE:" + eulerAngles + " DangR:" + radianAngles
                                 + " time:" + timeOfSnapshot + " newp:" + keyFramedPos
                                 + " newR:" + keyFramedOrientation
                                 + " incUpdateDt:" + timeInfo.DT
                                 + " oldP:" + rb.RigidBody.GlobalTransform.origin
                                 + " oldR:" + rb.RigidBody.GlobalTransform.basis.RotationQuat()
                                 + " OriginalRot:" + transform.Rotation
                                 //+ " keyF:" + rb.RigidBody.isKinematic
                                 + " KF:" + rb.IsKeyframed);
#endif
                    }

                    rb.lastTimeKeyFramedUpdate = timeOfSnapshot;
                    rb.IsKeyframed             = (snapshot.RigidBodies.Values[index].motionType == Patching.Types.MotionType.Keyframed);

                    // code to disable prediction and to use just key framing (and comment out the prediction)
                    //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);

                    // call the predictor with this remotely owned body
                    _predictor.AddAndProcessRemoteBodyForPrediction(rb, transform,
                                                                    keyFramedPos, keyFramedOrientation, timeOfSnapshot, timeInfo);
                }
            }

            // call the predictor
            _predictor.PredictAllRemoteBodiesWithOwnedBodies(ref _rigidBodies, timeInfo);
        }
Пример #6
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);
        }