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); |                 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; |             return FindCollisionSimplex(shapeA, transformA, shapeB, transformB).Item1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <summary> |         /// <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> |         /// </summary> | ||||||
|         /// <param name="rectangleA"></param> |         /// <param name="rectangleA"></param> | ||||||
|         /// <param name="transformA"></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; |             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> |         /// <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. |         /// 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> |         /// </summary> | ||||||
|  |  | ||||||
|  | @ -6,21 +6,9 @@ namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|     public struct Point : IShape2D, IEquatable<Point> |     public struct Point : IShape2D, IEquatable<Point> | ||||||
|     { |     { | ||||||
|         private Position2D _position; |         private Position2D Position { get; } | ||||||
|         public AABB AABB { 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) |         public AABB TransformedAABB(Transform2D transform) | ||||||
|         { |         { | ||||||
|             return AABB.Transformed(AABB, transform); |             return AABB.Transformed(AABB, transform); | ||||||
|  | @ -28,7 +16,7 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         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) |         public override bool Equals(object obj) | ||||||
|  | @ -43,22 +31,22 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public bool Equals(Point other) |         public bool Equals(Point other) | ||||||
|         { |         { | ||||||
|             return _position == other._position; |             return Position == other.Position; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override int GetHashCode() |         public override int GetHashCode() | ||||||
|         { |         { | ||||||
|             return HashCode.Combine(_position); |             return HashCode.Combine(Position); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool operator ==(Point a, Point b) |         public static bool operator ==(Point a, Point b) | ||||||
|         { |         { | ||||||
|             return a.Equals(b); |             return true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool operator !=(Point a, Point b) |         public static bool operator !=(Point a, Point b) | ||||||
|         { |         { | ||||||
|             return !(a == b); |             return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -15,36 +15,27 @@ namespace Tests | ||||||
|             [Test] |             [Test] | ||||||
|             public void PointEqual() |             public void PointEqual() | ||||||
|             { |             { | ||||||
|                 var a = new Point(1, 1); |                 var a = new Point(); | ||||||
|                 var b = new Point(1, 1); |                 var b = new Point(); | ||||||
| 
 | 
 | ||||||
|                 a.Equals(b).Should().BeTrue(); |                 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] |             [Test] | ||||||
|             public void PointEqualOperator() |             public void PointEqualOperator() | ||||||
|             { |             { | ||||||
|                 var a = new Point(1, 1); |                 var a = new Point(); | ||||||
|                 var b = new Point(1, 1); |                 var b = new Point(); | ||||||
|                 (a == b).Should().BeTrue(); |                 (a == b).Should().BeTrue(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void PointNotEqualOperator() |             public void PointNotEqualOperator() | ||||||
|             { |             { | ||||||
|                 var a = new Point(1, 1); |                 var a = new Point(); | ||||||
|                 var b = new Point(-1, 1); |                 var b = new Point(); | ||||||
| 
 | 
 | ||||||
|                 (a != b).Should().BeTrue(); |                 (a != b).Should().BeFalse(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,8 +12,8 @@ namespace Tests | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointLineOverlapping() |         public void PointLineOverlapping() | ||||||
|         { |         { | ||||||
|             var point = new Point(-3, -3); |             var point = new Point(); | ||||||
|             var pointTransform = new Transform2D(new Position2D(4, 4)); |             var pointTransform = new Transform2D(new Position2D(1, 1)); | ||||||
|             var line = new Line(new Position2D(-2, -2), new Position2D(2, 2)); |             var line = new Line(new Position2D(-2, -2), new Position2D(2, 2)); | ||||||
| 
 | 
 | ||||||
|             NarrowPhase.TestCollision(point, pointTransform, line, Transform2D.DefaultTransform).Should().BeTrue(); |             NarrowPhase.TestCollision(point, pointTransform, line, Transform2D.DefaultTransform).Should().BeTrue(); | ||||||
|  | @ -22,10 +22,11 @@ namespace Tests | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointLineNotOverlapping() |         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)); |             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] |         [Test] | ||||||
|  | @ -43,7 +44,7 @@ namespace Tests | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointCircleNotOverlapping() |         public void PointCircleNotOverlapping() | ||||||
|         { |         { | ||||||
|             var point = new Point(0, 0); |             var point = new Point(); | ||||||
|             var pointTransform = new Transform2D(new Position2D(3, 0)); |             var pointTransform = new Transform2D(new Position2D(3, 0)); | ||||||
|             var circle = new Circle(1); |             var circle = new Circle(1); | ||||||
| 
 | 
 | ||||||
|  | @ -53,7 +54,7 @@ namespace Tests | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointRectangleOverlapping() |         public void PointRectangleOverlapping() | ||||||
|         { |         { | ||||||
|             var point = new Point(1, 1); |             var point = new Point(); | ||||||
|             var rectangle = new Rectangle(-2, -2, 2, 2); |             var rectangle = new Rectangle(-2, -2, 2, 2); | ||||||
| 
 | 
 | ||||||
|             NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeTrue(); |             NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeTrue(); | ||||||
|  | @ -62,16 +63,18 @@ namespace Tests | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointRectangleNotOverlapping() |         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); |             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] |         [Test] | ||||||
|         public void PointPolygonOverlapping() |         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( |             var polygon = new Polygon(ImmutableArray.Create( | ||||||
|                 new Position2D(-2, -2), |                 new Position2D(-2, -2), | ||||||
|                 new Position2D(-3, 2), |                 new Position2D(-3, 2), | ||||||
|  | @ -79,13 +82,14 @@ namespace Tests | ||||||
|                 new Position2D(3, -2) |                 new Position2D(3, -2) | ||||||
|             )); |             )); | ||||||
| 
 | 
 | ||||||
|             NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeTrue(); |             NarrowPhase.TestCollision(point, pointTransform, polygon, Transform2D.DefaultTransform).Should().BeTrue(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|         public void PointPolygonNotOverlapping() |         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( |             var polygon = new Polygon(ImmutableArray.Create( | ||||||
|                 new Position2D(-2, -2), |                 new Position2D(-2, -2), | ||||||
|                 new Position2D(-3, 2), |                 new Position2D(-3, 2), | ||||||
|  | @ -93,7 +97,7 @@ namespace Tests | ||||||
|                 new Position2D(3, -2) |                 new Position2D(3, -2) | ||||||
|             )); |             )); | ||||||
| 
 | 
 | ||||||
|             NarrowPhase.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse(); |             NarrowPhase.TestCollision(point, pointTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| using FluentAssertions; | using FluentAssertions; | ||||||
| using NUnit.Framework; | using NUnit.Framework; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using MoonTools.Core.Bonk; | using MoonTools.Core.Bonk; | ||||||
|  | @ -34,8 +34,8 @@ namespace Tests | ||||||
|             var line = new Line(new Position2D(20, -4), new Position2D(22, -12)); |             var line = new Line(new Position2D(20, -4), new Position2D(22, -12)); | ||||||
|             var lineTransform = new Transform2D(new Vector2(0, 0)); |             var lineTransform = new Transform2D(new Vector2(0, 0)); | ||||||
| 
 | 
 | ||||||
|             var point = new Point(8, 8); |             var point = new Point(); | ||||||
|             var pointTransform = Transform2D.DefaultTransform; |             var pointTransform = new Transform2D(new Position2D(8, 8)); | ||||||
| 
 | 
 | ||||||
|             spatialHash.Insert(0, rectA, rectATransform); |             spatialHash.Insert(0, rectA, rectATransform); | ||||||
|             spatialHash.Insert(1, rectB, rectBTransform); |             spatialHash.Insert(1, rectB, rectBTransform); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue