コード例 #1
0
        public static bool PointToCircle(Vector2 point, Circle circle, out CollisionResult result)
        {
            result = new CollisionResult();

            // avoid the square root until we actually need it
            var distanceSquared = Vector2.DistanceSquared(point, circle.Position);
            var sumOfRadii      = 1 + circle.Radius;
            var collided        = distanceSquared < sumOfRadii * sumOfRadii;

            if (collided)
            {
                result.Normal = Vector2.Normalize(point - circle.Position);
                var depth = sumOfRadii - MathF.Sqrt(distanceSquared);
                result.MinimumTranslationVector = -depth * result.Normal;
                result.Point = circle.Position + result.Normal * circle.Radius;

                return(true);
            }

            return(false);
        }
コード例 #2
0
        public static bool CircleToCircle(Circle first, Circle second, out CollisionResult result)
        {
            result = new CollisionResult();

            // avoid the square root until we actually need it
            var distanceSquared = Vector2.DistanceSquared(first.Position, second.Position);
            var sumOfRadii      = first.Radius + second.Radius;
            var collided        = distanceSquared < sumOfRadii * sumOfRadii;

            if (collided)
            {
                result.Normal = Vector2.Normalize(first.Position - second.Position);
                var depth = sumOfRadii - MathF.Sqrt(distanceSquared);
                result.MinimumTranslationVector = -depth * result.Normal;
                result.Point = second.Position + result.Normal * second.Radius;

                return(true);
            }

            return(false);
        }
コード例 #3
0
        public static bool CircleToBox(Circle circle, Box box, out CollisionResult result)
        {
            result = new CollisionResult();

            var closestPointOnBounds = box.BoundingBox.GetClosestPointOnBorderToPoint(circle.Position, out result.Normal);

            // deal with circles whos center is in the box first since its cheaper to see if we are contained
            if (box.ContainsPoint(circle.Position))
            {
                result.Point = closestPointOnBounds;

                // calculate mtv. Find the safe, non-collided position and get the mtv from that.
                var safePlace = closestPointOnBounds + result.Normal * circle.Radius;
                result.MinimumTranslationVector = circle.Position - safePlace;

                return(true);
            }

            float sqrDistance = Vector2.DistanceSquared(closestPointOnBounds, circle.Position);

            // see if the point on the box is less than radius from the circle
            if (sqrDistance == 0)
            {
                result.MinimumTranslationVector = result.Normal * circle.Radius;
            }
            else if (sqrDistance <= circle.Radius * circle.Radius)
            {
                result.Normal = circle.Position - closestPointOnBounds;
                var depth = result.Normal.Length() - circle.Radius;

                result.Point = closestPointOnBounds;
                Vector2Ext.Normalize(ref result.Normal);
                result.MinimumTranslationVector = depth * result.Normal;

                return(true);
            }

            return(false);
        }
コード例 #4
0
        public static bool BoxToBox(Box first, Box second, out CollisionResult result)
        {
            result = new CollisionResult();

            var diff = MinkowskiDifference(first, second);

            if (diff.Contains(0f, 0f))
            {
                result.MinimumTranslationVector = diff.GetClosestPointOnBoundsToOrigin();

                if (result.MinimumTranslationVector == Vector2.Zero)
                {
                    return(false);
                }

                result.Normal = -result.MinimumTranslationVector;
                result.Normal.Normalize();

                return(true);
            }

            return(false);
        }
コード例 #5
0
        public static bool PolygonToPolygon(Polygon first, Polygon second, out CollisionResult result)
        {
            result = new CollisionResult();
            var isIntersecting = true;

            var     firstEdges          = first.EdgeNormals;
            var     secondEdges         = second.EdgeNormals;
            var     minIntervalDistance = float.PositiveInfinity;
            var     translationAxis     = new Vector2();
            var     polygonOffset       = first.Position - second.Position;
            Vector2 axis;

            // Loop through all the edges of both polygons
            for (var edgeIndex = 0; edgeIndex < firstEdges.Length + secondEdges.Length; edgeIndex++)
            {
                // 1. Find if the polygons are currently intersecting
                // Polygons have the normalized axis perpendicular to the current edge cached for us
                if (edgeIndex < firstEdges.Length)
                {
                    axis = firstEdges[edgeIndex];
                }
                else
                {
                    axis = secondEdges[edgeIndex - firstEdges.Length];
                }

                // Find the projection of the polygon on the current axis
                float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
                var   intervalDist = 0f;
                GetInterval(axis, first, ref minA, ref maxA);
                GetInterval(axis, second, ref minB, ref maxB);

                // get our interval to be space of the second Polygon. Offset by the difference in Position projected on the axis.
                Vector2.Dot(ref polygonOffset, ref axis, out float relativeIntervalOffset);
                minA += relativeIntervalOffset;
                maxA += relativeIntervalOffset;

                // check if the polygon projections are currentlty intersecting
                intervalDist = IntervalDistance(minA, maxA, minB, maxB);
                if (intervalDist > 0)
                {
                    isIntersecting = false;
                }


                // If the polygons are not intersecting and won't intersect, exit the loop
                if (!isIntersecting)
                {
                    return(false);
                }

                // 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
                intervalDist = System.Math.Abs(intervalDist);
                if (intervalDist < minIntervalDistance)
                {
                    // If the intervalDist == 0, the two objects are just touching each other, not colliding.
                    //Todo: Fully test.

                    if (intervalDist == 0)
                    {
                        return(false);
                    }

                    minIntervalDistance = intervalDist;
                    translationAxis     = axis;

                    if (Vector2.Dot(translationAxis, polygonOffset) < 0)
                    {
                        translationAxis = -translationAxis;
                    }
                }
            }

            // The minimum translation vector can be used to push the polygons appart.
            result.Normal = translationAxis;
            result.MinimumTranslationVector = -translationAxis * minIntervalDistance;

            return(true);
        }
コード例 #6
0
 public override bool CollidesWithShape(Shape other, out CollisionResult result)
 {
     result = default(CollisionResult);
     return(false);
 }
コード例 #7
0
 public override bool CollidesWithPoint(Vector2 point, out CollisionResult result)
 {
     result = default(CollisionResult);
     return(false);
 }