refactor GJK again
							parent
							
								
									2151252d6e
								
							
						
					
					
						commit
						f787a00a91
					
				|  | @ -24,7 +24,7 @@ namespace MoonTools.Core.Bonk | |||
|         /// </summary> | ||||
|         /// <param name="simplex">A simplex returned by the GJK algorithm.</param> | ||||
|         /// <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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,73 +11,135 @@ namespace MoonTools.Core.Bonk | |||
|         /// </summary> | ||||
|         public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) | ||||
|         { | ||||
|             var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||
|             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)); | ||||
|             return FindCollisionSimplex(shapeA, transformA, shapeB, transformB).Item1; | ||||
|         } | ||||
| 
 | ||||
|         /// <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> | ||||
|         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 a = minkowskiDifference.Support(Vector2.UnitX); | ||||
|             var b = minkowskiDifference.Support(-a); | ||||
| 
 | ||||
|             return Vector2.Dot(a, b) > 0 ? (false, default(Simplex)) : Simplex(new Simplex(minkowskiDifference, a, b)); | ||||
|             var c = minkowskiDifference.Support(Vector2.UnitX); | ||||
|             var b = minkowskiDifference.Support(-Vector2.UnitX); | ||||
|             return Check(minkowskiDifference, c, b); | ||||
|         } | ||||
| 
 | ||||
|         private static (bool, Simplex) Simplex(Simplex simplex) | ||||
|         private static (bool, Simplex2D) Check(MinkowskiDifference minkowskiDifference, Vector2 c, Vector2 b) | ||||
|         { | ||||
|             var a = simplex.DirectionA; | ||||
|             var b = simplex.DirectionB; | ||||
|             var cb = c - b; | ||||
|             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) | ||||
|         { | ||||
|                 return (false, simplex.WithDirections(a, b)); | ||||
|             var a = minkowskiDifference.Support(direction); | ||||
|             var notPastOrigin = Vector2.Dot(a, direction) < 0; | ||||
|             var (intersects, newSimplex, newDirection) = EnclosesOrigin(a, simplex); | ||||
| 
 | ||||
|             if (notPastOrigin) | ||||
|             { | ||||
|                 return (false, default(Simplex2D)); | ||||
|             } | ||||
|             else if (intersects) | ||||
|             { | ||||
|                 return (true, new Simplex2D(simplex.A, simplex.B.Value, a)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 var c = simplex.Support((b - a).Perpendicular()); | ||||
|                 var axb = a.Cross(b); | ||||
|                 var bxc = b.Cross(c); | ||||
|                 return DoSimplex(minkowskiDifference, newSimplex, newDirection); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|                 if (axb.Y > 0 != bxc.Y > 0) | ||||
|         private static (bool, Simplex2D, Vector2) EnclosesOrigin(Vector2 a, Simplex2D simplex) | ||||
|         { | ||||
|                     return Simplex(simplex.WithDirections(b, c)); | ||||
|             if (simplex.ZeroSimplex) | ||||
|             { | ||||
|                 return HandleZeroSimplex(a, simplex.A); | ||||
|             } | ||||
|             else if (simplex.OneSimplex) | ||||
|             { | ||||
|                 return HandleOneSimplex(a, simplex.A, simplex.B.Value); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                     var axc = a.Cross(c); | ||||
|                     var cxb = -bxc; | ||||
|                 return (false, simplex, Vector2.Zero); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|                     if (axc.Y > 0 != cxb.Y > 0) | ||||
|         private static (bool, Simplex2D, Vector2) HandleZeroSimplex(Vector2 a, Vector2 b) | ||||
|         { | ||||
|                         return Simplex(simplex.WithDirections(a, 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 (false, new Simplex2D(a, b), abp); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                         return (true, simplex.WithDirections(a, b)); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|                     return (false, new Simplex2D(a), a0); | ||||
|                 } | ||||
|             } | ||||
|             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 Microsoft.Xna.Framework; | ||||
| using MoonTools.Core.Structs; | ||||
| using MoonTools.Core.Bonk.Extensions; | ||||
| using MoreLinq; | ||||
| 
 | ||||
| namespace MoonTools.Core.Bonk | ||||
| { | ||||
|     /// <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> | ||||
|     public struct Simplex : IShape2D | ||||
|     public struct Simplex2D : IShape2D | ||||
|     { | ||||
|         MinkowskiDifference minkowskiDifference; | ||||
|         Vector2 directionA; | ||||
|         Vector2 directionB; | ||||
|         Vector2 a; | ||||
|         Vector2? b; | ||||
|         Vector2? c; | ||||
| 
 | ||||
|         public Vector2 DirectionA { get { return directionA; } } | ||||
|         public Vector2 DirectionB { get { return directionB; } } | ||||
|         public Vector2 A => a; | ||||
|         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.directionA = directionA; | ||||
|             this.directionB = directionB; | ||||
|             this.a = a; | ||||
|             this.b = null; | ||||
|             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 | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 yield return (Position2D)Support(directionA); | ||||
|                 yield return (Position2D)Support(directionB); | ||||
|                 yield return (Position2D)Support(-(directionB - directionA).Perpendicular()); | ||||
|                 yield return (Position2D)a; | ||||
|                 if (b.HasValue) { yield return (Position2D)b; } | ||||
|                 if (c.HasValue) { yield return (Position2D)c; } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -46,7 +64,7 @@ namespace MoonTools.Core.Bonk | |||
| 
 | ||||
|         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) | ||||
|  | @ -66,11 +84,10 @@ namespace MoonTools.Core.Bonk | |||
| 
 | ||||
|         public bool Equals(IShape2D other) | ||||
|         { | ||||
|             if (other is Simplex otherSimplex) | ||||
|             if (other is Simplex2D otherSimplex) | ||||
|             { | ||||
|                 return minkowskiDifference == otherSimplex.minkowskiDifference && | ||||
|                     ((directionA == otherSimplex.directionA && directionB == otherSimplex.directionB) || | ||||
|                     (directionA == otherSimplex.directionB && directionB == otherSimplex.directionA)); | ||||
|                 if (Count != otherSimplex.Count) { return false; } | ||||
|                 return Vertices.Intersect(otherSimplex.Vertices).Count() == Count; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|  | @ -78,22 +95,23 @@ namespace MoonTools.Core.Bonk | |||
| 
 | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             var hashCode = 74270316; | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<MinkowskiDifference>.Default.GetHashCode(minkowskiDifference); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(directionA); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(directionB); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(DirectionA); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(DirectionB); | ||||
|             var hashCode = -495772172; | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2>.Default.GetHashCode(a); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2?>.Default.GetHashCode(b); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Vector2?>.Default.GetHashCode(c); | ||||
|             hashCode = hashCode * -1521134295 + ZeroSimplex.GetHashCode(); | ||||
|             hashCode = hashCode * -1521134295 + OneSimplex.GetHashCode(); | ||||
|             hashCode = hashCode * -1521134295 + TwoSimplex.GetHashCode(); | ||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); | ||||
|             return hashCode; | ||||
|         } | ||||
| 
 | ||||
|         public static bool operator ==(Simplex a, Simplex b) | ||||
|         public static bool operator ==(Simplex2D a, Simplex2D b) | ||||
|         { | ||||
|             return a.Equals(b); | ||||
|         } | ||||
| 
 | ||||
|         public static bool operator !=(Simplex a, Simplex b) | ||||
|         public static bool operator !=(Simplex2D a, Simplex2D b) | ||||
|         { | ||||
|             return !(a == b); | ||||
|         } | ||||
|  |  | |||
|  | @ -4,15 +4,15 @@ namespace MoonTools.Core.Bonk.Extensions | |||
| { | ||||
|     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 new Vector2(vec3.X, vec3.Y); | ||||
|             return Vector3.Cross(new Vector3(a.X, a.Y, 0), new Vector3(b.X, b.Y, 0)).Z; | ||||
|         } | ||||
| 
 | ||||
|         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.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] | ||||
|  | @ -47,6 +51,10 @@ namespace Tests | |||
| 
 | ||||
|             intersection.X.Should().BeApproximately(ix, 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] | ||||
|  | @ -63,8 +71,9 @@ namespace Tests | |||
| 
 | ||||
|             var intersection = EPA2D.Intersect(line, transformA, square, transformB, simplex); | ||||
| 
 | ||||
|             intersection.X.Should().Be(-1); | ||||
|             intersection.Y.Should().Be(1); | ||||
|             var movedTransform = new Transform2D(transformA.Position - intersection * 1.01f); // move a tiny bit past | ||||
| 
 | ||||
|             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 | ||||
|         { | ||||
|             [Test] | ||||
|             public void SimplexEquals() | ||||
|             public void ZeroSimplexEquals() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
| 
 | ||||
|                 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); | ||||
|                 var simplexA = new Simplex2D(Vector2.One); | ||||
|                 var simplexB = new Simplex2D(Vector2.One); | ||||
| 
 | ||||
|                 simplexA.Equals(simplexB).Should().BeTrue(); | ||||
|             } | ||||
| 
 | ||||
|             [Test] | ||||
|             public void SimplexEqualsOperator() | ||||
|             public void ZeroSimplexEqualsOperator() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
| 
 | ||||
|                 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); | ||||
|                 var simplexA = new Simplex2D(Vector2.One); | ||||
|                 var simplexB = new Simplex2D(Vector2.One); | ||||
| 
 | ||||
|                 (simplexA == simplexB).Should().BeTrue(); | ||||
|             } | ||||
| 
 | ||||
|             [Test] | ||||
|             public void SimplexDirectionOutOfOrderEqual() | ||||
|             public void ZeroSimplexNotEquals() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
|                 var simplexA = new Simplex2D(Vector2.Zero); | ||||
|                 var simplexB = new Simplex2D(Vector2.One); | ||||
| 
 | ||||
|                 var shapeB = new Circle(2); | ||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); | ||||
|                 simplexA.Equals(simplexB).Should().BeFalse(); | ||||
| 
 | ||||
|                 var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||
|                 var simplexC = new Simplex2D(Vector2.Zero, Vector2.One); | ||||
| 
 | ||||
|                 var directionA = Vector2.UnitX; | ||||
|                 var directionB = Vector2.UnitY; | ||||
|                 simplexA.Equals(simplexC).Should().BeFalse(); | ||||
|             } | ||||
| 
 | ||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); | ||||
|                 var simplexB = new Simplex(minkowskiDifference, directionB, directionA); | ||||
|             [Test] | ||||
|             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(); | ||||
| 
 | ||||
|                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
|                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.One); | ||||
| 
 | ||||
|                 simplexC.Equals(simplexD).Should().BeTrue(); | ||||
|             } | ||||
| 
 | ||||
|             [Test] | ||||
|             public void SimplexDirectionOutOfOrderEqualOperator() | ||||
|             public void OneSimplexEqualsOperator() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
| 
 | ||||
|                 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); | ||||
|                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
|                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
| 
 | ||||
|                 (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] | ||||
|             public void SimplexMinkowskiNotEqual() | ||||
|             public void OneSimplexNotEquals() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
| 
 | ||||
|                 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); | ||||
|                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
|                 var simplexB = new Simplex2D(Vector2.One, Vector2.UnitX); | ||||
| 
 | ||||
|                 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] | ||||
|             public void SimplexMinkowskiNotEqualOperator() | ||||
|             public void OneSimplexNotEqualsOperator() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
|                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
|                 var simplexB = new Simplex2D(Vector2.One, Vector2.UnitX); | ||||
| 
 | ||||
|                 var shapeB = new Circle(2); | ||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); | ||||
|                 (simplexA == simplexB).Should().BeFalse(); | ||||
| 
 | ||||
|                 var minkowskiDifferenceA = new MinkowskiDifference(shapeA, transformA, shapeB, transformB); | ||||
|                 var minkowskiDifferenceB = new MinkowskiDifference(shapeB, transformB, shapeA, transformA); | ||||
|                 var simplexC = new Simplex2D(Vector2.One, Vector2.Zero); | ||||
|                 var simplexD = new Simplex2D(Vector2.Zero, Vector2.UnitX); | ||||
| 
 | ||||
|                 var directionA = Vector2.UnitX; | ||||
|                 var directionB = Vector2.UnitY; | ||||
| 
 | ||||
|                 var simplexA = new Simplex(minkowskiDifferenceA, directionA, directionB); | ||||
|                 var simplexB = new Simplex(minkowskiDifferenceB, directionA, directionB); | ||||
| 
 | ||||
|                 (simplexA != simplexB).Should().BeTrue(); | ||||
|                 (simplexC == simplexD).Should().BeFalse(); | ||||
|             } | ||||
| 
 | ||||
|             [Test] | ||||
|             public void SimplexDirectionsNotEqual() | ||||
|             public void TwoSimplexEquals() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
|                 var simplexA = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||
|                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||
| 
 | ||||
|                 var shapeB = new Circle(2); | ||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); | ||||
|                 simplexA.Equals(simplexB).Should().BeTrue(); | ||||
| 
 | ||||
|                 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; | ||||
|                 var directionB = Vector2.UnitY; | ||||
|                 var directionC = -Vector2.UnitX; | ||||
|                 var directionD = -Vector2.UnitY; | ||||
|                 simplexC.Equals(simplexD).Should().BeTrue(); | ||||
|             } | ||||
| 
 | ||||
|                 var simplexA = new Simplex(minkowskiDifference, directionA, directionB); | ||||
|                 var simplexB = new Simplex(minkowskiDifference, directionC, directionD); | ||||
|             [Test] | ||||
|             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(); | ||||
| 
 | ||||
|                 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] | ||||
|             public void SimplexDirectionsNotEqualOperator() | ||||
|             public void TwoSimplexNotEqualsOperator() | ||||
|             { | ||||
|                 var shapeA = new Circle(3); | ||||
|                 var transformA = new Transform2D(new Position2D(1, 2)); | ||||
|                 var simplexA = new Simplex2D(Vector2.One, Vector2.UnitY, Vector2.UnitX); | ||||
|                 var simplexB = new Simplex2D(Vector2.One, Vector2.Zero, Vector2.UnitX); | ||||
| 
 | ||||
|                 var shapeB = new Circle(2); | ||||
|                 var transformB = new Transform2D(new Position2D(4, 5)); | ||||
|                 (simplexA == simplexB).Should().BeFalse(); | ||||
| 
 | ||||
|                 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; | ||||
|                 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(); | ||||
|                 (simplexC == simplexD).Should().BeFalse(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -259,6 +259,18 @@ namespace Tests | |||
|             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] | ||||
|         public void RotatedRectanglesOverlapping() | ||||
|         { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue