forked from MoonsideGames/MoonTools.Bonk
				
			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)
 | 
			
		||||
        {
 | 
			
		||||
            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
 | 
			
		||||
            {
 | 
			
		||||
                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)
 | 
			
		||||
        {
 | 
			
		||||
            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
 | 
			
		||||
                {
 | 
			
		||||
                    var axc = a.Cross(c);
 | 
			
		||||
                    var cxb = -bxc;
 | 
			
		||||
 | 
			
		||||
                    if (axc.Y > 0 != cxb.Y > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        return Simplex(simplex.WithDirections(a, b));
 | 
			
		||||
                    }
 | 
			
		||||
                    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