void IBeforeSolverUpdateable.Update(float dt)
        {
            //We can't let multiple characters manage the same pairs simultaneously.  Lock it up!
            this.LockCharacterPairs();
            try
            {
                bool hadSupport = this.SupportFinder.HasSupport;

                this.CollectSupportData();

                //Compute the initial velocities relative to the support.
                var relativeVelocity = this.Body.LinearVelocity;
                var verticalVelocity = Vector3.Dot(this.supportData.Normal, relativeVelocity);

                //Don't attempt to use an object as support if we are flying away from it (and we were never standing on it to begin with).
                if (this.SupportFinder.HasSupport && !hadSupport && verticalVelocity < 0)
                {
                    this.SupportFinder.ClearSupportData();
                    this.supportData = new SupportData();
                }

                //Attempt to jump.
                if (this.tryToJump)                 //Jumping while crouching would be a bit silly.
                {
                    //In the following, note that the jumping velocity changes are computed such that the separating velocity is specifically achieved,
                    //rather than just adding some speed along an arbitrary direction.  This avoids some cases where the character could otherwise increase
                    //the jump speed, which may not be desired.
                    if (this.SupportFinder.HasTraction)
                    {
                        //The character has traction, so jump straight up.
                        float currentDownVelocity;
                        Vector3.Dot(ref this.down, ref relativeVelocity, out currentDownVelocity);
                        //Target velocity is JumpSpeed.
                        float velocityChange = Math.Max(this.jumpSpeed + currentDownVelocity, 0);
                        this.ApplyJumpVelocity(this.down * -velocityChange, ref relativeVelocity);

                        //Prevent any old contacts from hanging around and coming back with a negative depth.
                        foreach (var pair in this.Body.CollisionInformation.Pairs)
                        {
                            pair.ClearContacts();
                        }
                        this.SupportFinder.ClearSupportData();
                        this.supportData = new SupportData();
                    }
                    else
                    {
                        Utilities.Logger.Error("Support Does not have traction");
                    }
                }
                this.tryToJump = false;
            }
            finally
            {
                this.UnlockCharacterPairs();
            }

            //Vertical support data is different because it has the capacity to stop the character from moving unless
            //contacts are pruned appropriately.
            Vector3 movement3D;

            this.HorizontalMotionConstraint.GetMovementDirectionIn3D(out movement3D);
            this.HorizontalMotionConstraint.SupportData = this.supportData;

            SupportData verticalSupportData;

            this.SupportFinder.GetTractionInDirection(ref movement3D, out verticalSupportData);
            this.VerticalMotionConstraint.SupportData = verticalSupportData;
        }
Esempio n. 2
0
        public bool GetTractionInDirection(ref Vector3 movementDirection, out SupportData supportData)
        {
            if (this.HasTraction)
            {
                int   greatestIndex = -1;
                float greatestDot   = -float.MaxValue;
                for (int i = 0; i < this.supports.Count; i++)
                {
                    if (this.supports.Elements[i].HasTraction)
                    {
                        float dot;
                        Vector3.Dot(ref movementDirection, ref this.supports.Elements[i].Contact.Normal, out dot);
                        if (dot > greatestDot)
                        {
                            greatestDot   = dot;
                            greatestIndex = i;
                        }
                    }
                }
                if (greatestIndex != -1)
                {
                    supportData.Position      = this.supports.Elements[greatestIndex].Contact.Position;
                    supportData.Normal        = this.supports.Elements[greatestIndex].Contact.Normal;
                    supportData.SupportObject = this.supports.Elements[greatestIndex].Support;
                    supportData.HasTraction   = true;

                    float depth = -float.MaxValue;
                    for (int i = 0; i < this.supports.Count; i++)
                    {
                        if (this.supports.Elements[i].HasTraction)
                        {
                            float dot;
                            Vector3.Dot(ref this.supports.Elements[i].Contact.Normal, ref supportData.Normal, out dot);
                            dot = dot * this.supports.Elements[i].Contact.PenetrationDepth;
                            if (dot > depth)
                            {
                                depth = dot;
                            }
                        }
                    }
                    supportData.Depth = depth;

                    return(true);
                }
                //Okay, try the ray cast result then.
                if (this.SupportRayData != null && this.SupportRayData.Value.HasTraction)
                {
                    supportData.Position      = this.SupportRayData.Value.HitData.Location;
                    supportData.Normal        = this.SupportRayData.Value.HitData.Normal;
                    supportData.Depth         = Vector3.Dot(this.character.Down, this.SupportRayData.Value.HitData.Normal) * (this.bottomHeight - this.SupportRayData.Value.HitData.T);
                    supportData.SupportObject = this.SupportRayData.Value.HitObject;
                    supportData.HasTraction   = true;
                    return(true);
                }
                //Well that's strange!
                supportData = new SupportData();
                return(false);
            }
            else
            {
                supportData = new SupportData();
                return(false);
            }
        }