Пример #1
0
        /// <summary>
        /// Get the position so that the object does not collide with the object anymore.
        /// Important: this is used raycasting checks, as this needs some more corner-cases.
        /// </summary>
        /// <param name="collider">The collider which is the player</param>
        /// <param name="collisionPoint">Point of the collision in the scene</param>
        /// <param name="hitNormal">Collision-normal of the object with which the player collided</param>
        /// <returns>Position which is possible for the collider so there is no collision.</returns>
        private JVector GetPosition(Collider collider, JVector collisionPoint, JVector hitNormal)
        {
            JVector    bbSize     = collider.BoundingBoxSize;
            GameObject gameObject = collider.GameObject;

            // Calculate the size of the forward and right vector based on the bounding-box.
            JVector forward = 0.5f * bbSize.Z * Conversion.ToJitterVector(gameObject.transform.Forward);
            JVector right   = 0.5f * bbSize.X * Conversion.ToJitterVector(gameObject.transform.Right);
            JVector d       = Conversion.ToJitterVector(gameObject.transform.Forward);

            if (hitNormal.IsZero())
            {
                return(bbSize.Z * -0.5f * Conversion.ToJitterVector(gameObject.transform.Forward));
            }

            // Correct directions
            TurnIntoDirectionOf(ref forward, hitNormal);
            TurnIntoDirectionOf(ref right, hitNormal);
            TurnIntoDirectionOf(ref d, hitNormal);

            // Calculate the projected length (half-length) of the player on the hit-normal.
            JVector lengthOnNormal = ProjectOn(forward, hitNormal);
            JVector widthOnNormal  = ProjectOn(right, hitNormal);
            JVector projectedSize  = lengthOnNormal + widthOnNormal;

            JVector margin      = ProjectOn(projectedSize, d);
            JVector endPosition = collisionPoint + margin;

            // Check if it hit a corner and it could actually go closer
            JVector plane = new JVector(-hitNormal.Z, 0, hitNormal.X);

            TurnIntoDirectionOf(ref plane, -1 * forward);
            plane.Normalize();

            // Check if there is an intersection between the front-"plane" of the player and the collided object
            JVector intersection;

            JVector frontMiddle = endPosition + forward;
            JVector frontRight  = endPosition + forward - right;
            JVector planeEnd    = collisionPoint + MathHelper.Max(bbSize.X, bbSize.Z) * plane;

            if (DoIntersect(frontMiddle, frontRight, collisionPoint, planeEnd, out intersection))
            {
                intersection.Y = collider.Position.Y;
                JVector colToIntersection = intersection - collisionPoint;

                JVector margin2 = ProjectOn(colToIntersection, d);

                margin      = margin.LengthSquared() > margin2.LengthSquared() ? margin2 : margin;
                endPosition = collisionPoint + margin;
            }

            //// Todo: Visual debuggin might be removed in the end
            //PhysicsDrawer.Instance.ClearPointsToDraw();
            //PhysicsDrawer.Instance.AddPointToDraw(Conversion.ToXnaVector(collisionPoint));
            //PhysicsDrawer.Instance.AddPointToDraw(Conversion.ToXnaVector(endPosition));

            //return collider.Position;
            return(endPosition);
        }
Пример #2
0
        /// <summary>
        /// Get the position so that the object does not collide with the object anymore.
        /// Important: this is used for the normal collision-handling.
        /// </summary>
        /// <param name="collider">The collider which is the player</param>
        /// <param name="collisionPoint">Point of the collision in the scene</param>
        /// <param name="hitNormal">Collision-normal of the object with which the player collided</param>
        /// <returns>Position which is possible for the collider so there is no collision.</returns>
        private JVector ProjectToNonCollision(Collider collider, JVector collisionPoint, JVector hitNormal)
        {
            JVector    bbSize     = collider.BoundingBoxSize;
            GameObject gameObject = collider.GameObject;

            // This should actually not happen
            if (hitNormal.IsZero())
            {
                return(bbSize.Z * -0.5f * Conversion.ToJitterVector(gameObject.transform.Forward));
            }

            // Calculate the size of the forward and right vector based on the bounding-box.
            JVector forward = 0.5f * bbSize.Z * Conversion.ToJitterVector(gameObject.transform.Forward);
            JVector right   = 0.5f * bbSize.X * Conversion.ToJitterVector(gameObject.transform.Right);

            // Correct directions for calculations.
            TurnIntoDirectionOf(ref forward, hitNormal);
            TurnIntoDirectionOf(ref right, hitNormal);

            // Calculate the projected length (half-length) of the player on the hit-normal.
            JVector lengthOnNormal = ProjectOn(forward, hitNormal);
            JVector widthOnNormal  = ProjectOn(right, hitNormal);
            JVector projectedSize  = lengthOnNormal + widthOnNormal;

            // Get vector which gives the non-collided-part of the car projected on the hit-normal.
            JVector distColToPos = collisionPoint - collider.Position;

            // Correct directions for calculations.
            TurnIntoDirectionOf(ref projectedSize, hitNormal);
            TurnIntoDirectionOf(ref distColToPos, hitNormal);

            // Calculate the penetration-depth of the collision
            JVector nonCollidedSize = ProjectOn(distColToPos, hitNormal);
            JVector penetration     = nonCollidedSize - projectedSize;

            // Todo: Visual debuggin might be removed in the end
            PhysicsDrawer.Instance.AddPointToDraw(Conversion.ToXnaVector(collider.Position - (1 + Epsilon) * penetration));

            // Calcualte the position for the player so it doesn't collide anymore
            return(collider.Position - (1 + Epsilon) * penetration);
        }