refactor GJK again
							parent
							
								
									2151252d6e
								
							
						
					
					
						commit
						f787a00a91
					
				|  | @ -24,7 +24,7 @@ namespace MoonTools.Core.Bonk | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="simplex">A simplex returned by the GJK algorithm.</param> |         /// <param name="simplex">A simplex returned by the GJK algorithm.</param> | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex simplex) |         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex2D simplex) | ||||||
|         { |         { | ||||||
|             var simplexVertices = new PooledList<Vector2>(36, ClearMode.Always); |             var simplexVertices = new PooledList<Vector2>(36, ClearMode.Always); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,73 +11,135 @@ namespace MoonTools.Core.Bonk | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) |         public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||||
|         { |         { | ||||||
|             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |             return FindCollisionSimplex(shapeA, transformA, shapeB, transformB).Item1; | ||||||
|             var a = minkowskiDifference.Support(Vector2.UnitX); |  | ||||||
|             var b = minkowskiDifference.Support(-a); |  | ||||||
| 
 |  | ||||||
|             return Vector2.Dot(a, b) > 0 ? false : CheckSimplex(new Simplex(minkowskiDifference, a, b)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         private static bool CheckSimplex(Simplex simplex) |  | ||||||
|         { |  | ||||||
|             var a = simplex.DirectionA; |  | ||||||
|             var b = simplex.DirectionB; |  | ||||||
| 
 |  | ||||||
|             var axb = a.Cross(b); |  | ||||||
|             var c = simplex.Support((b - a).Perpendicular()); |  | ||||||
|             var axc = a.Cross(c); |  | ||||||
|             var bxc = b.Cross(c); |  | ||||||
|             var cxb = -bxc; |  | ||||||
| 
 |  | ||||||
|             return (b - a) == Vector2.Zero || (axb.Y > 0 != bxc.Y > 0 ? CheckSimplex(simplex.WithDirections(b, c)) : (axc.Y > 0 != cxb.Y > 0 ? CheckSimplex(simplex.WithDirections(a, c)) : true)); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         /// <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> | ||||||
|         public static (bool, Simplex) FindCollisionSimplex(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) |         public static (bool, Simplex2D) FindCollisionSimplex(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||||
|         { |         { | ||||||
|             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||||
|             var a = minkowskiDifference.Support(Vector2.UnitX); |             var c = minkowskiDifference.Support(Vector2.UnitX); | ||||||
|             var b = minkowskiDifference.Support(-a); |             var b = minkowskiDifference.Support(-Vector2.UnitX); | ||||||
| 
 |             return Check(minkowskiDifference, c, b); | ||||||
|             return Vector2.Dot(a, b) > 0 ? (false, default(Simplex)) : Simplex(new Simplex(minkowskiDifference, a, b)); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static (bool, Simplex) Simplex(Simplex simplex) |         private static (bool, Simplex2D) Check(MinkowskiDifference minkowskiDifference, Vector2 c, Vector2 b) | ||||||
|         { |         { | ||||||
|             var a = simplex.DirectionA; |             var cb = c - b; | ||||||
|             var b = simplex.DirectionB; |             var c0 = -c; | ||||||
|  |             var d = Direction(cb, c0); | ||||||
|  |             return DoSimplex(minkowskiDifference, new Simplex2D(b, c), d); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             if ((b - a) == Vector2.Zero) |         private static (bool, Simplex2D) DoSimplex(MinkowskiDifference minkowskiDifference, Simplex2D simplex, Vector2 direction) | ||||||
|  |         { | ||||||
|  |             var a = minkowskiDifference.Support(direction); | ||||||
|  |             var notPastOrigin = Vector2.Dot(a, direction) < 0; | ||||||
|  |             var (intersects, newSimplex, newDirection) = EnclosesOrigin(a, simplex); | ||||||
|  | 
 | ||||||
|  |             if (notPastOrigin) | ||||||
|             { |             { | ||||||
|                 return (false, simplex.WithDirections(a, b)); |                 return (false, default(Simplex2D)); | ||||||
|  |             } | ||||||
|  |             else if (intersects) | ||||||
|  |             { | ||||||
|  |                 return (true, new Simplex2D(simplex.A, simplex.B.Value, a)); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 var c = simplex.Support((b - a).Perpendicular()); |                 return DoSimplex(minkowskiDifference, newSimplex, newDirection); | ||||||
|                 var axb = a.Cross(b); |             } | ||||||
|                 var bxc = b.Cross(c); |         } | ||||||
| 
 | 
 | ||||||
|                 if (axb.Y > 0 != bxc.Y > 0) |         private static (bool, Simplex2D, Vector2) EnclosesOrigin(Vector2 a, Simplex2D simplex) | ||||||
|  |         { | ||||||
|  |             if (simplex.ZeroSimplex) | ||||||
|  |             { | ||||||
|  |                 return HandleZeroSimplex(a, simplex.A); | ||||||
|  |             } | ||||||
|  |             else if (simplex.OneSimplex) | ||||||
|  |             { | ||||||
|  |                 return HandleOneSimplex(a, simplex.A, simplex.B.Value); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 return (false, simplex, Vector2.Zero); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static (bool, Simplex2D, Vector2) HandleZeroSimplex(Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             var ab = b - a; | ||||||
|  |             var a0 = -a; | ||||||
|  |             var (newSimplex, newDirection) = SameDirection(ab, a0) ? (new Simplex2D(a, b), Perpendicular(ab, a0)) : (new Simplex2D(a), a0); | ||||||
|  |             return (false, newSimplex, newDirection); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static (bool, Simplex2D, Vector2) HandleOneSimplex(Vector2 a, Vector2 b, Vector2 c) | ||||||
|  |         { | ||||||
|  |             var a0 = -a; | ||||||
|  |             var ab = b - a; | ||||||
|  |             var ac = c - a; | ||||||
|  |             var abp = Perpendicular(ab, -ac); | ||||||
|  |             var acp = Perpendicular(ac, -ab); | ||||||
|  | 
 | ||||||
|  |             if (SameDirection(abp, a0)) | ||||||
|  |             { | ||||||
|  |                 if (SameDirection(ab, a0)) | ||||||
|                 { |                 { | ||||||
|                     return Simplex(simplex.WithDirections(b, c)); |                     return (false, new Simplex2D(a, b), abp); | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     var axc = a.Cross(c); |                     return (false, new Simplex2D(a), a0); | ||||||
|                     var cxb = -bxc; |  | ||||||
| 
 |  | ||||||
|                     if (axc.Y > 0 != cxb.Y > 0) |  | ||||||
|                     { |  | ||||||
|                         return Simplex(simplex.WithDirections(a, b)); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         return (true, simplex.WithDirections(a, b)); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             else if (SameDirection(acp, a0)) | ||||||
|  |             { | ||||||
|  |                 if (SameDirection(ac, a0)) | ||||||
|  |                 { | ||||||
|  |                     return (false, new Simplex2D(a, c), acp); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     return (false, new Simplex2D(a), a0); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 return (true, new Simplex2D(b, c), a0); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static Vector2 TripleProduct(Vector2 a, Vector2 b, Vector2 c) | ||||||
|  |         { | ||||||
|  |             var A = new Vector3(a.X, a.Y, 0); | ||||||
|  |             var B = new Vector3(b.X, b.Y, 0); | ||||||
|  |             var C = new Vector3(c.X, c.Y, 0); | ||||||
|  | 
 | ||||||
|  |             var first = Vector3.Cross(A, B); | ||||||
|  |             var second = Vector3.Cross(first, C); | ||||||
|  | 
 | ||||||
|  |             return new Vector2(second.X, second.Y); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static Vector2 Direction(Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             var d = TripleProduct(a, b, a); | ||||||
|  |             var collinear = d == Vector2.Zero; | ||||||
|  |             return collinear ? new Vector2(a.Y, -a.X) : d; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static bool SameDirection(Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             return Vector2.Dot(a, b) > 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static Vector2 Perpendicular(Vector2 a, Vector2 b) | ||||||
|  |         { | ||||||
|  |             return TripleProduct(a, b, a); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,41 +1,59 @@ | ||||||
|  | using System.Linq; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Microsoft.Xna.Framework; | using Microsoft.Xna.Framework; | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using MoonTools.Core.Bonk.Extensions; | using MoonTools.Core.Bonk.Extensions; | ||||||
|  | using MoreLinq; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// A simplex is a shape used to calculate overlap. It is defined by a Minkowski difference and two direction vectors. |     /// A simplex is a shape with up to n - 2 vertices in the nth dimension. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public struct Simplex : IShape2D |     public struct Simplex2D : IShape2D | ||||||
|     { |     { | ||||||
|         MinkowskiDifference minkowskiDifference; |         Vector2 a; | ||||||
|         Vector2 directionA; |         Vector2? b; | ||||||
|         Vector2 directionB; |         Vector2? c; | ||||||
| 
 | 
 | ||||||
|         public Vector2 DirectionA { get { return directionA; } } |         public Vector2 A => a; | ||||||
|         public Vector2 DirectionB { get { return directionB; } } |         public Vector2? B => b; | ||||||
|  |         public Vector2? C => c; | ||||||
| 
 | 
 | ||||||
|         public Simplex(MinkowskiDifference minkowskiDifference, Vector2 directionA, Vector2 directionB) |         public bool ZeroSimplex { get { return !b.HasValue && !c.HasValue; } } | ||||||
|  |         public bool OneSimplex { get { return b.HasValue && !c.HasValue; } } | ||||||
|  |         public bool TwoSimplex { get { return b.HasValue && c.HasValue; } } | ||||||
|  | 
 | ||||||
|  |         public int Count => TwoSimplex ? 3 : (OneSimplex ? 2 : 1); | ||||||
|  | 
 | ||||||
|  |         public Simplex2D(Vector2 a) | ||||||
|         { |         { | ||||||
|             this.minkowskiDifference = minkowskiDifference; |             this.a = a; | ||||||
|             this.directionA = directionA; |             this.b = null; | ||||||
|             this.directionB = directionB; |             this.c = null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Simplex WithDirections(Vector2 a, Vector2 b) |         public Simplex2D(Vector2 a, Vector2 b) | ||||||
|         { |         { | ||||||
|             return new Simplex(minkowskiDifference, a, b); |             this.a = a; | ||||||
|  |             this.b = b; | ||||||
|  |             this.c = null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Simplex2D(Vector2 a, Vector2 b, Vector2 c) | ||||||
|  |         { | ||||||
|  |             this.a = a; | ||||||
|  |             this.b = b; | ||||||
|  |             this.c = c; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public IEnumerable<Position2D> Vertices |         public IEnumerable<Position2D> Vertices | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|             { |             { | ||||||
|                 yield return (Position2D)Support(directionA); |                 yield return (Position2D)a; | ||||||
|                 yield return (Position2D)Support(directionB); |                 if (b.HasValue) { yield return (Position2D)b; } | ||||||
|                 yield return (Position2D)Support(-(directionB - directionA).Perpendicular()); |                 if (c.HasValue) { yield return (Position2D)c; } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -46,7 +64,7 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction) |         public Vector2 Support(Vector2 direction) | ||||||
|         { |         { | ||||||
|             return minkowskiDifference.Support(direction); |             return Vertices.MaxBy(vertex => Vector2.Dot(vertex, direction)).First(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|  | @ -66,11 +84,10 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public bool Equals(IShape2D other) |         public bool Equals(IShape2D other) | ||||||
|         { |         { | ||||||
|             if (other is Simplex otherSimplex) |             if (other is Simplex2D otherSimplex) | ||||||
|             { |             { | ||||||
|                 return minkowskiDifference == otherSimplex.minkowskiDifference && |                 if (Count != otherSimplex.Count) { return false; } | ||||||
|                     ((directionA == otherSimplex.directionA && directionB == otherSimplex.directionB) || |                 return Vertices.Intersect(otherSimplex.Vertices).Count() == Count; | ||||||
|                     (directionA == otherSimplex.directionB && directionB == otherSimplex.directionA)); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return false; |             return false; | ||||||
|  | @ -78,22 +95,23 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public override int GetHashCode() |         public override int GetHashCode() | ||||||
|         { |         { | ||||||
|             var hashCode = 74270316; |             var hashCode = -495772172; | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<MinkowskiDifference>.Default.GetHashCode(minkowskiDifference); |             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(a); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(directionA); |             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2?>.Default.GetHashCode(b); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(directionB); |             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2?>.Default.GetHashCode(c); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(DirectionA); |             hashCode = hashCode * -1521134295 + ZeroSimplex.GetHashCode(); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(DirectionB); |             hashCode = hashCode * -1521134295 + OneSimplex.GetHashCode(); | ||||||
|  |             hashCode = hashCode * -1521134295 + TwoSimplex.GetHashCode(); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); |             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); | ||||||
|             return hashCode; |             return hashCode; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool operator ==(Simplex a, Simplex b) |         public static bool operator ==(Simplex2D a, Simplex2D b) | ||||||
|         { |         { | ||||||
|             return a.Equals(b); |             return a.Equals(b); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool operator !=(Simplex a, Simplex b) |         public static bool operator !=(Simplex2D a, Simplex2D b) | ||||||
|         { |         { | ||||||
|             return !(a == b); |             return !(a == b); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -4,15 +4,15 @@ namespace MoonTools.Core.Bonk.Extensions | ||||||
| { | { | ||||||
|     internal static class Vector2Extensions |     internal static class Vector2Extensions | ||||||
|     { |     { | ||||||
|         internal static Vector2 Cross(this Vector2 a, Vector2 b) |         internal static float Cross(this Vector2 a, Vector2 b) | ||||||
|         { |         { | ||||||
|             var vec3 = Vector3.Cross(new Vector3(a.X, a.Y, 0), new Vector3(b.X, b.Y, 0)); |             return Vector3.Cross(new Vector3(a.X, a.Y, 0), new Vector3(b.X, b.Y, 0)).Z; | ||||||
|             return new Vector2(vec3.X, vec3.Y); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         internal static Vector2 Perpendicular(this Vector2 v) |         internal static Vector2 Perpendicular(this Vector2 a, Vector2 b) | ||||||
|         { |         { | ||||||
|             return new Vector2(v.Y, -v.X); |             var ab = b - a; | ||||||
|  |             return a.Cross(b) > 0 ? Vector2.Normalize(new Vector2(ab.Y, ab.X)) : Vector2.Normalize(new Vector2(ab.Y, -ab.X)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -26,6 +26,10 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             intersection.X.Should().Be(1f); |             intersection.X.Should().Be(1f); | ||||||
|             intersection.Y.Should().Be(0); |             intersection.Y.Should().Be(0); | ||||||
|  | 
 | ||||||
|  |             var movedTransform = new Transform2D(transformA.Position - intersection * 1.01f); // move a tiny bit past | ||||||
|  | 
 | ||||||
|  |             GJK2D.TestCollision(squareA, movedTransform, squareB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -47,6 +51,10 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             intersection.X.Should().BeApproximately(ix, 0.01f); |             intersection.X.Should().BeApproximately(ix, 0.01f); | ||||||
|             intersection.Y.Should().BeApproximately(iy, 0.01f); |             intersection.Y.Should().BeApproximately(iy, 0.01f); | ||||||
|  | 
 | ||||||
|  |             var movedTransform = new Transform2D(transformA.Position - intersection * 1.01f); // move a tiny bit past | ||||||
|  | 
 | ||||||
|  |             GJK2D.TestCollision(circleA, movedTransform, circleB, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         [Test] |         [Test] | ||||||
|  | @ -63,8 +71,9 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|             var intersection = EPA2D.Intersect(line, transformA, square, transformB, simplex); |             var intersection = EPA2D.Intersect(line, transformA, square, transformB, simplex); | ||||||
| 
 | 
 | ||||||
|             intersection.X.Should().Be(-1); |             var movedTransform = new Transform2D(transformA.Position - intersection * 1.01f); // move a tiny bit past | ||||||
|             intersection.Y.Should().Be(1); | 
 | ||||||
|  |             GJK2D.TestCollision(line, movedTransform, square, transformB).Should().BeFalse(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										210
									
								
								Test/Equality.cs
								
								
								
								
							
							
						
						
									
										210
									
								
								Test/Equality.cs
								
								
								
								
							|  | @ -258,169 +258,163 @@ namespace Tests | ||||||
|         public class SimplexTests |         public class SimplexTests | ||||||
|         { |         { | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexEquals() |             public void ZeroSimplexEquals() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One); | ||||||
| 
 |  | ||||||
|                 var shapeB = new Circle(2); |  | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 |  | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |  | ||||||
| 
 |  | ||||||
|                 var directionA = Vector2.UnitX; |  | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
| 
 | 
 | ||||||
|                 simplexA.Equals(simplexB).Should().BeTrue(); |                 simplexA.Equals(simplexB).Should().BeTrue(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexEqualsOperator() |             public void ZeroSimplexEqualsOperator() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One); | ||||||
| 
 |  | ||||||
|                 var shapeB = new Circle(2); |  | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 |  | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |  | ||||||
| 
 |  | ||||||
|                 var directionA = Vector2.UnitX; |  | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
| 
 | 
 | ||||||
|                 (simplexA == simplexB).Should().BeTrue(); |                 (simplexA == simplexB).Should().BeTrue(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexDirectionOutOfOrderEqual() |             public void ZeroSimplexNotEquals() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.Zero); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One); | ||||||
| 
 | 
 | ||||||
|                 var shapeB = new Circle(2); |                 simplexA.Equals(simplexB).Should().BeFalse(); | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 | 
 | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |                 var simplexC = new Simplex2D(Vector2.Zero, Vector2.One); | ||||||
| 
 | 
 | ||||||
|                 var directionA = Vector2.UnitX; |                 simplexA.Equals(simplexC).Should().BeFalse(); | ||||||
|                 var directionB = Vector2.UnitY; |             } | ||||||
| 
 | 
 | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |             [Test] | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionB, directionA); |             public void ZeroSimplexNotEqualsOperator() | ||||||
|  |             { | ||||||
|  |                 var simplexA = new Simplex2D(Vector2.Zero); | ||||||
|  |                 var simplexB = new Simplex2D(Vector2.One); | ||||||
|  | 
 | ||||||
|  |                 (simplexA != simplexB).Should().BeTrue(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void OneSimplexEquals() | ||||||
|  |             { | ||||||
|  |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|  |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
| 
 | 
 | ||||||
|                 simplexA.Equals(simplexB).Should().BeTrue(); |                 simplexA.Equals(simplexB).Should().BeTrue(); | ||||||
|  | 
 | ||||||
|  |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.One); | ||||||
|  | 
 | ||||||
|  |                 simplexC.Equals(simplexD).Should().BeTrue(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexDirectionOutOfOrderEqualOperator() |             public void OneSimplexEqualsOperator() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
| 
 |  | ||||||
|                 var shapeB = new Circle(2); |  | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 |  | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |  | ||||||
| 
 |  | ||||||
|                 var directionA = Vector2.UnitX; |  | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionB, directionA); |  | ||||||
| 
 | 
 | ||||||
|                 (simplexA == simplexB).Should().BeTrue(); |                 (simplexA == simplexB).Should().BeTrue(); | ||||||
|  | 
 | ||||||
|  |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.One); | ||||||
|  | 
 | ||||||
|  |                 (simplexC == simplexD).Should().BeTrue(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexMinkowskiNotEqual() |             public void OneSimplexNotEquals() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One, Vector2.UnitX); | ||||||
| 
 |  | ||||||
|                 var shapeB = new Circle(2); |  | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 |  | ||||||
|                 var minkowskiDifferenceA = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |  | ||||||
|                 var minkowskiDifferenceB = new MinkowskiDifference(shapeB, transformB, shapeA, transformA); |  | ||||||
| 
 |  | ||||||
|                 var directionA = Vector2.UnitX; |  | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifferenceA, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifferenceB, directionA, directionB); |  | ||||||
| 
 | 
 | ||||||
|                 simplexA.Equals(simplexB).Should().BeFalse(); |                 simplexA.Equals(simplexB).Should().BeFalse(); | ||||||
|  | 
 | ||||||
|  |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.UnitX); | ||||||
|  | 
 | ||||||
|  |                 simplexC.Equals(simplexD).Should().BeFalse(); | ||||||
|  | 
 | ||||||
|  |                 var simplexE = new Simplex2D(Vector2.Zero); | ||||||
|  | 
 | ||||||
|  |                 simplexA.Equals(simplexE).Should().BeFalse(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexMinkowskiNotEqualOperator() |             public void OneSimplexNotEqualsOperator() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var shapeB = new Circle(2); |                 (simplexA == simplexB).Should().BeFalse(); | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 | 
 | ||||||
|                 var minkowskiDifferenceA = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||||
|                 var minkowskiDifferenceB = new MinkowskiDifference(shapeB, transformB, shapeA, transformA); |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var directionA = Vector2.UnitX; |                 (simplexC == simplexD).Should().BeFalse(); | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifferenceA, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifferenceB, directionA, directionB); |  | ||||||
| 
 |  | ||||||
|                 (simplexA != simplexB).Should().BeTrue(); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexDirectionsNotEqual() |             public void TwoSimplexEquals() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var shapeB = new Circle(2); |                 simplexA.Equals(simplexB).Should().BeTrue(); | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 | 
 | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.One, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var directionA = Vector2.UnitX; |                 simplexC.Equals(simplexD).Should().BeTrue(); | ||||||
|                 var directionB = Vector2.UnitY; |             } | ||||||
|                 var directionC = -Vector2.UnitX; |  | ||||||
|                 var directionD = -Vector2.UnitY; |  | ||||||
| 
 | 
 | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |             [Test] | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionC, directionD); |             public void TwoSimplexEqualsOperator() | ||||||
|  |             { | ||||||
|  |                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  | 
 | ||||||
|  |                 (simplexA == simplexB).Should().BeTrue(); | ||||||
|  | 
 | ||||||
|  |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.One, Vector2.UnitX); | ||||||
|  | 
 | ||||||
|  |                 (simplexC == simplexD).Should().BeTrue(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void TwoSimplexNotEquals() | ||||||
|  |             { | ||||||
|  |                 var simplexA = new Simplex2D(Vector2.One, Vector2.UnitY, Vector2.UnitX); | ||||||
|  |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 simplexA.Equals(simplexB).Should().BeFalse(); |                 simplexA.Equals(simplexB).Should().BeFalse(); | ||||||
|  | 
 | ||||||
|  |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.UnitY, Vector2.UnitX); | ||||||
|  | 
 | ||||||
|  |                 simplexC.Equals(simplexD).Should().BeFalse(); | ||||||
|  | 
 | ||||||
|  |                 var simplexE = new Simplex2D(Vector2.Zero); | ||||||
|  | 
 | ||||||
|  |                 simplexA.Equals(simplexE).Should().BeFalse(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Test] |             [Test] | ||||||
|             public void SimplexDirectionsNotEqualOperator() |             public void TwoSimplexNotEqualsOperator() | ||||||
|             { |             { | ||||||
|                 var shapeA = new Circle(3); |                 var simplexA = new Simplex2D(Vector2.One, Vector2.UnitY, Vector2.UnitX); | ||||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); |                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var shapeB = new Circle(2); |                 (simplexA == simplexB).Should().BeFalse(); | ||||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); |  | ||||||
| 
 | 
 | ||||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); |                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||||
|  |                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.UnitY, Vector2.UnitX); | ||||||
| 
 | 
 | ||||||
|                 var directionA = Vector2.UnitX; |                 (simplexC == simplexD).Should().BeFalse(); | ||||||
|                 var directionB = Vector2.UnitY; |  | ||||||
|                 var directionC = -Vector2.UnitX; |  | ||||||
|                 var directionD = -Vector2.UnitY; |  | ||||||
| 
 |  | ||||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); |  | ||||||
|                 var simplexB = new Simplex(minkowskiDifference, directionC, directionD); |  | ||||||
| 
 |  | ||||||
|                 (simplexA != simplexB).Should().BeTrue(); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -259,6 +259,18 @@ namespace Tests | ||||||
|             GJK2D.TestCollision(circle, circleTransform, square, squareTransform).Should().BeFalse(); |             GJK2D.TestCollision(circle, circleTransform, square, squareTransform).Should().BeFalse(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         [Test] | ||||||
|  |         public void RectanglesNotOverlapping() | ||||||
|  |         { | ||||||
|  |             var rectangleA = new MoonTools.Core.Bonk.Rectangle(-6, -6, 6, 6); | ||||||
|  |             var transformA = new Transform2D(new Position2D(39, 249)); | ||||||
|  | 
 | ||||||
|  |             var rectangleB = new MoonTools.Core.Bonk.Rectangle(0, 0, 16, 16); | ||||||
|  |             var transformB = new Transform2D(new Position2D(16, 240)); | ||||||
|  | 
 | ||||||
|  |             GJK2D.TestCollision(rectangleA, transformA, rectangleB, transformB).Should().BeFalse(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         [Test] |         [Test] | ||||||
|         public void RotatedRectanglesOverlapping() |         public void RotatedRectanglesOverlapping() | ||||||
|         { |         { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue