refactor GJK again

generics
Evan Hemsley 2019-10-25 22:00:34 -07:00
parent 2151252d6e
commit f787a00a91
7 changed files with 285 additions and 190 deletions

View File

@ -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);

View File

@ -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)
{ {
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 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)
{ {
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 else
{ {
var axc = a.Cross(c); return (false, simplex, Vector2.Zero);
var cxb = -bxc; }
}
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 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);
} }
} }
} }

View File

@ -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);
} }

View File

@ -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));
} }
} }
} }

View File

@ -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();
} }
} }
} }

View File

@ -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();
} }
} }
} }

View File

@ -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()
{ {