forked from MoonsideGames/MoonTools.Bonk
				
			optimization for circle overlap + remove position data from point
							parent
							
								
									22d99e6b8d
								
							
						
					
					
						commit
						f62c855c37
					
				| 
						 | 
				
			
			@ -65,11 +65,23 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
            {
 | 
			
		||||
                return TestRectangleOverlap(rectangleA, transformA, rectangleB, transformB);
 | 
			
		||||
            }
 | 
			
		||||
            else if (shapeA is Point && shapeB is Rectangle && transformB.Rotation == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return TestPointRectangleOverlap((Point)shapeA, transformA, (Rectangle)shapeB, transformB);
 | 
			
		||||
            }
 | 
			
		||||
            else if (shapeA is Rectangle && shapeB is Point && transformA.Rotation == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return TestPointRectangleOverlap((Point)shapeB, transformB, (Rectangle)shapeA, transformA);
 | 
			
		||||
            }
 | 
			
		||||
            else if (shapeA is Circle circleA && shapeB is Circle circleB && transformA.Scale.X == transformA.Scale.Y && transformB.Scale.X == transformB.Scale.Y)
 | 
			
		||||
            {
 | 
			
		||||
                return TestCircleOverlap(circleA, transformA, circleB, transformB);
 | 
			
		||||
            }
 | 
			
		||||
            return FindCollisionSimplex(shapeA, transformA, shapeB, transformB).Item1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fast path for overlapping rectangles. If the transforms have non-zero rotation this will be inaccurate.
 | 
			
		||||
        /// Fast path for axis-aligned rectangles. If the transforms have non-zero rotation this will be inaccurate.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="rectangleA"></param>
 | 
			
		||||
        /// <param name="transformA"></param>
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +96,44 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
            return firstAABB.Left <= secondAABB.Right && firstAABB.Right >= secondAABB.Left && firstAABB.Top <= secondAABB.Bottom && firstAABB.Bottom >= secondAABB.Top;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fast path for overlapping point and axis-aligned rectangle. The rectangle transform must have non-zero rotation.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="point"></param>
 | 
			
		||||
        /// <param name="pointTransform"></param>
 | 
			
		||||
        /// <param name="rectangle"></param>
 | 
			
		||||
        /// <param name="rectangleTransform"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static bool TestPointRectangleOverlap(Point point, Transform2D pointTransform, Rectangle rectangle, Transform2D rectangleTransform)
 | 
			
		||||
        {
 | 
			
		||||
            var transformedPoint = pointTransform.Position;
 | 
			
		||||
            var AABB = rectangle.TransformedAABB(rectangleTransform);
 | 
			
		||||
 | 
			
		||||
            return transformedPoint.X >= AABB.Left && transformedPoint.X <= AABB.Right && transformedPoint.Y <= AABB.Bottom && transformedPoint.Y >= AABB.Top;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fast path for overlapping circles. The circles must have uniform scaling.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="circleA"></param>
 | 
			
		||||
        /// <param name="transformA"></param>
 | 
			
		||||
        /// <param name="circleB"></param>
 | 
			
		||||
        /// <param name="transformB"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static bool TestCircleOverlap(Circle circleA, Transform2D transformA, Circle circleB, Transform2D transformB)
 | 
			
		||||
        {
 | 
			
		||||
            var radiusA = circleA.Radius * transformA.Scale.X;
 | 
			
		||||
            var radiusB = circleB.Radius * transformB.Scale.Y;
 | 
			
		||||
 | 
			
		||||
            var centerA = transformA.Position;
 | 
			
		||||
            var centerB = transformB.Position;
 | 
			
		||||
 | 
			
		||||
            var distanceSquared = (centerA - centerB).LengthSquared();
 | 
			
		||||
            var radiusSumSquared = (radiusA + radiusB) * (radiusA + radiusB);
 | 
			
		||||
 | 
			
		||||
            return distanceSquared <= radiusSumSquared;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Tests if the two shape-transform pairs are overlapping, and returns a simplex that can be used by the EPA algorithm to determine a miminum separating vector.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,21 +6,9 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
{
 | 
			
		||||
    public struct Point : IShape2D, IEquatable<Point>
 | 
			
		||||
    {
 | 
			
		||||
        private Position2D _position;
 | 
			
		||||
        private Position2D Position { get; }
 | 
			
		||||
        public AABB AABB { get; }
 | 
			
		||||
 | 
			
		||||
        public Point(Position2D position)
 | 
			
		||||
        {
 | 
			
		||||
            _position = position;
 | 
			
		||||
            AABB = new AABB(position, position);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Point(int x, int y)
 | 
			
		||||
        {
 | 
			
		||||
            _position = new Position2D(x, y);
 | 
			
		||||
            AABB = new AABB(x, y, x, y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public AABB TransformedAABB(Transform2D transform)
 | 
			
		||||
        {
 | 
			
		||||
            return AABB.Transformed(AABB, transform);
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +16,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
 | 
			
		||||
        public Vector2 Support(Vector2 direction, Transform2D transform)
 | 
			
		||||
        {
 | 
			
		||||
            return Vector2.Transform(_position.ToVector2(), transform.TransformMatrix);
 | 
			
		||||
            return Vector2.Transform(Position.ToVector2(), transform.TransformMatrix);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool Equals(object obj)
 | 
			
		||||
| 
						 | 
				
			
			@ -43,22 +31,22 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
 | 
			
		||||
        public bool Equals(Point other)
 | 
			
		||||
        {
 | 
			
		||||
            return _position == other._position;
 | 
			
		||||
            return Position == other.Position;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override int GetHashCode()
 | 
			
		||||
        {
 | 
			
		||||
            return HashCode.Combine(_position);
 | 
			
		||||
            return HashCode.Combine(Position);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator ==(Point a, Point b)
 | 
			
		||||
        {
 | 
			
		||||
            return a.Equals(b);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator !=(Point a, Point b)
 | 
			
		||||
        {
 | 
			
		||||
            return !(a == b);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,36 +15,27 @@ namespace Tests
 | 
			
		|||
            [Test]
 | 
			
		||||
            public void PointEqual()
 | 
			
		||||
            {
 | 
			
		||||
                var a = new Point(1, 1);
 | 
			
		||||
                var b = new Point(1, 1);
 | 
			
		||||
                var a = new Point();
 | 
			
		||||
                var b = new Point();
 | 
			
		||||
 | 
			
		||||
                a.Equals(b).Should().BeTrue();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Test]
 | 
			
		||||
            public void PointNotEqual()
 | 
			
		||||
            {
 | 
			
		||||
                var a = new Point(1, 1);
 | 
			
		||||
                var b = new Point(-1, 1);
 | 
			
		||||
 | 
			
		||||
                a.Equals(b).Should().BeFalse();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Test]
 | 
			
		||||
            public void PointEqualOperator()
 | 
			
		||||
            {
 | 
			
		||||
                var a = new Point(1, 1);
 | 
			
		||||
                var b = new Point(1, 1);
 | 
			
		||||
                var a = new Point();
 | 
			
		||||
                var b = new Point();
 | 
			
		||||
                (a == b).Should().BeTrue();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [Test]
 | 
			
		||||
            public void PointNotEqualOperator()
 | 
			
		||||
            {
 | 
			
		||||
                var a = new Point(1, 1);
 | 
			
		||||
                var b = new Point(-1, 1);
 | 
			
		||||
                var a = new Point();
 | 
			
		||||
                var b = new Point();
 | 
			
		||||
 | 
			
		||||
                (a != b).Should().BeTrue();
 | 
			
		||||
                (a != b).Should().BeFalse();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,8 @@ namespace Tests
 | 
			
		|||
        [Test]
 | 
			
		||||
        public void PointLineOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(-3, -3);
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(4, 4));
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(1, 1));
 | 
			
		||||
            var line = new Line(new Position2D(-2, -2), new Position2D(2, 2));
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, pointTransform, line, Transform2D.DefaultTransform).Should().BeTrue();
 | 
			
		||||
| 
						 | 
				
			
			@ -22,10 +22,11 @@ namespace Tests
 | 
			
		|||
        [Test]
 | 
			
		||||
        public void PointLineNotOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(1, 1);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(1, 1));
 | 
			
		||||
            var line = new Line(new Position2D(-3, -2), new Position2D(-9, -5));
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, line, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
            NarrowPhase.TestCollision(point, pointTransform, line, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Test]
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +44,7 @@ namespace Tests
 | 
			
		|||
        [Test]
 | 
			
		||||
        public void PointCircleNotOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(0, 0);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(3, 0));
 | 
			
		||||
            var circle = new Circle(1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +54,7 @@ namespace Tests
 | 
			
		|||
        [Test]
 | 
			
		||||
        public void PointRectangleOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(1, 1);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var rectangle = new Rectangle(-2, -2, 2, 2);
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeTrue();
 | 
			
		||||
| 
						 | 
				
			
			@ -62,16 +63,18 @@ namespace Tests
 | 
			
		|||
        [Test]
 | 
			
		||||
        public void PointRectangleNotOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(5, 5);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(5, 5));
 | 
			
		||||
            var rectangle = new Rectangle(-2, -2, 2, 2);
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
            NarrowPhase.TestCollision(point, pointTransform, rectangle, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Test]
 | 
			
		||||
        public void PointPolygonOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(1, 1);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(1, 1));
 | 
			
		||||
            var polygon = new Polygon(ImmutableArray.Create(
 | 
			
		||||
                new Position2D(-2, -2),
 | 
			
		||||
                new Position2D(-3, 2),
 | 
			
		||||
| 
						 | 
				
			
			@ -79,13 +82,14 @@ namespace Tests
 | 
			
		|||
                new Position2D(3, -2)
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeTrue();
 | 
			
		||||
            NarrowPhase.TestCollision(point, pointTransform, polygon, Transform2D.DefaultTransform).Should().BeTrue();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Test]
 | 
			
		||||
        public void PointPolygonNotOverlapping()
 | 
			
		||||
        {
 | 
			
		||||
            var point = new Point(5, 5);
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(5, 5));
 | 
			
		||||
            var polygon = new Polygon(ImmutableArray.Create(
 | 
			
		||||
                new Position2D(-2, -2),
 | 
			
		||||
                new Position2D(-3, 2),
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +97,7 @@ namespace Tests
 | 
			
		|||
                new Position2D(3, -2)
 | 
			
		||||
            ));
 | 
			
		||||
 | 
			
		||||
            NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
            NarrowPhase.TestCollision(point, pointTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Test]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
using FluentAssertions;
 | 
			
		||||
using FluentAssertions;
 | 
			
		||||
using NUnit.Framework;
 | 
			
		||||
using MoonTools.Core.Structs;
 | 
			
		||||
using MoonTools.Core.Bonk;
 | 
			
		||||
| 
						 | 
				
			
			@ -34,8 +34,8 @@ namespace Tests
 | 
			
		|||
            var line = new Line(new Position2D(20, -4), new Position2D(22, -12));
 | 
			
		||||
            var lineTransform = new Transform2D(new Vector2(0, 0));
 | 
			
		||||
 | 
			
		||||
            var point = new Point(8, 8);
 | 
			
		||||
            var pointTransform = Transform2D.DefaultTransform;
 | 
			
		||||
            var point = new Point();
 | 
			
		||||
            var pointTransform = new Transform2D(new Position2D(8, 8));
 | 
			
		||||
 | 
			
		||||
            spatialHash.Insert(0, rectA, rectATransform);
 | 
			
		||||
            spatialHash.Insert(1, rectB, rectBTransform);
 | 
			
		||||
| 
						 | 
				
			
			@ -98,4 +98,4 @@ namespace Tests
 | 
			
		|||
            spatialHash.Retrieve(0, rectA, rectATransform).Should().HaveCount(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue