Example #1
0
        // Calculate the projection of a polygon on an axis and returns it as a [min, max] interval
        private static void ProjectPolygon(FixVec2 axis, FixPolygon polygon, out Fix min, out Fix max)
        {
            // To project a point on an axis use the dot product
            var d = axis.Dot(polygon.Points[0]);

            min = d;
            max = d;
            for (var i = 0; i < polygon.Points.Length; i++)
            {
                d = polygon.Points[i].Dot(axis);
                if (d < min)
                {
                    min = d;
                }
                else if (d > max)
                {
                    max = d;
                }
            }
        }
Example #2
0
        // Check if polygon A is going to collide with polygon B for the given velocity
        public static PolygonCollisionResult CheckCollision(FixPolygon polygonA, FixPolygon polygonB, FixVec2 velocity)
        {
            var result = new PolygonCollisionResult {
                Intersect = true, WillIntersect = true
            };

            var edgeCountA          = polygonA.Edges.Length;
            var edgeCountB          = polygonB.Edges.Length;
            var minIntervalDistance = Fix.MaxValue;
            var translationAxis     = new FixVec2();

            // Loop through all the edges of both polygons
            for (var edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
            {
                var edge = edgeIndex < edgeCountA ? polygonA.Edges[edgeIndex] : polygonB.Edges[edgeIndex - edgeCountA];

                // ===== 1. Find if the polygons are currently intersecting =====

                // Find the axis perpendicular to the current edge
                var axis = new FixVec2(-edge.Y, edge.X).Normalize();

                // Find the projection of the polygon on the current axis
                Fix minA;
                Fix maxA;
                Fix minB;
                Fix maxB;
                ProjectPolygon(axis, polygonA, out minA, out maxA);
                ProjectPolygon(axis, polygonB, out minB, out maxB);

                // Check if the polygon projections are currently intersecting
                if (IntervalDistance(minA, maxA, minB, maxB) > 0)
                {
                    result.Intersect = false;
                }

                // ===== 2. Now find if the polygons *will* intersect =====

                // Project the velocity on the current axis
                var velocityProjection = axis.Dot(velocity);

                // Get the projection of polygon A during the movement
                if (velocityProjection < 0)
                {
                    minA += velocityProjection;
                }
                else
                {
                    maxA += velocityProjection;
                }

                // Do the same test as above for the new projection
                var intervalDistance = IntervalDistance(minA, maxA, minB, maxB);
                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 FixVec2
                intervalDistance = FixMath.Abs(intervalDistance);
                if (intervalDistance < minIntervalDistance)
                {
                    minIntervalDistance = intervalDistance;
                    translationAxis     = axis;

                    var d = polygonA.Center - polygonB.Center;
                    if (d.Dot(translationAxis) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }
            }

            // The minimum translation FixVec2 can be used to push the polygons apart.
            // First moves the polygons by their velocity
            // then move polygonA by MinimumTranslationVector.
            if (result.WillIntersect)
            {
                result.MinimumTranslationVector = translationAxis * minIntervalDistance;
            }

            return(result);
        }