public override CollidableResults CheckForCollision(Collidable collidable, Vector3 velocity) { CollidableResults rayCastCollisionResult = new CollidableResults() { Intersect = false, HitPoint = Vector3.Zero, CollisionNormal = Vector3.Zero }; //is the vector perpendicular to the edge of the polygon where the intersection occured for (var i = 0; i < collidable.Points.Count; i++) { var p1 = collidable.Points[i]; var p2 = i + 1 >= collidable.Points.Count ? collidable.Points[0] : collidable.Points[i + 1]; rayCastCollisionResult.HitPoint = new Vector3(FindLineIntersection(Points[0], Points[1], p1, p2), 0f); if (!rayCastCollisionResult.HitPoint.Equals(Vector3.Zero)) { rayCastCollisionResult.Intersect = true; rayCastCollisionResult.CollisionNormal = new Vector3(collidable.Edges[i].Y, -collidable.Edges[i].X, 0f); rayCastCollisionResult.CollisionNormal.Normalize(); break; } } return(rayCastCollisionResult); }
// Check if polygon A is going to collide with polygon B for the given velocity public override CollidableResults CheckForCollision(Collidable polygon, Vector3 velocity) { var result = new CollidableResults { Intersect = true, WillIntersect = true }; var edgeCountA = Edges.Count; var edgeCountB = polygon.Edges.Count; var minIntervalDistance = float.PositiveInfinity; var translationAxis = new Vector2(); Vector2 edge; // Loop through all the edges of both polygons for (var edgeIndex = 0; edgeIndex < edgeCountB + edgeCountA; edgeIndex++) { if (edgeIndex < edgeCountB) { edge = polygon.Edges[edgeIndex]; } else { edge = Edges[edgeIndex - edgeCountB]; } // ===== 1. Find if the polygons are currently intersecting ===== // Find the axis perpendicular to the current edge var axis = new Vector2(-edge.Y, edge.X); axis.Normalize(); // Find the projection of the polygon on the current axis float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; ProjectPolygon(axis, this, ref minA, ref maxA); ProjectPolygon(axis, (Polygon)polygon, ref minB, ref maxB); // Check if the polygon projections are currentlty intersecting if (IntervalDistance(minB, maxB, minA, maxA) > 0) { result.Intersect = false; } // ===== 2. Now find if the polygons *will* intersect ===== // Project the velocity on the current axis var velocityProjection = Vector2.Dot(axis, new Vector2(velocity.X, velocity.Y)); // Get the projection of polygon A during the movement if (velocityProjection < 0) { minB += velocityProjection; } else { maxB += velocityProjection; } // Do the same test as above for the new projection var intervalDistance = IntervalDistance(minB, maxB, minA, maxA); if (intervalDistance > 0) { result.WillIntersect = false; } // If the polygons are not intersecting and won't intersect, exit the loop if (!result.Intersect && !result.WillIntersect) { break; } // Check if the current interval distance is the minimum one. If so store // the interval distance and the current distance. // This will be used to calculate the minimum translation vector intervalDistance = Math.Abs(intervalDistance); if (intervalDistance < minIntervalDistance) { minIntervalDistance = intervalDistance; translationAxis = axis; var d = polygon.Center - Center; if (Vector2.Dot(d, translationAxis) < 0) { translationAxis = -translationAxis; } } } // The minimum translation vector can be used to push the polygons appart. // First moves the polygons by their velocity // then move polygonA by MinimumTranslationVector. if (result.WillIntersect) { result.MinimumTranslationVector = new Vector3(translationAxis * minIntervalDistance, 0f); } return(result); }