/// <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); }
/// <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); }