diff --git a/Bonk/Bonk.csproj b/Bonk/Bonk.csproj
index ee8b234..66762f5 100644
--- a/Bonk/Bonk.csproj
+++ b/Bonk/Bonk.csproj
@@ -17,6 +17,6 @@
-
+
\ No newline at end of file
diff --git a/Bonk/NarrowPhase/EPA2D.cs b/Bonk/NarrowPhase/EPA2D.cs
index 791c9a9..d14ca1b 100644
--- a/Bonk/NarrowPhase/EPA2D.cs
+++ b/Bonk/NarrowPhase/EPA2D.cs
@@ -4,9 +4,10 @@
* https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/
*/
-using Collections.Pooled;
using MoonTools.Core.Structs;
using System;
+using System.Collections.Immutable;
+using System.Linq;
using System.Numerics;
namespace MoonTools.Core.Bonk
@@ -26,12 +27,7 @@ namespace MoonTools.Core.Bonk
///
public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex2D simplex)
{
- var simplexVertices = new PooledList(36, ClearMode.Always);
-
- foreach (var vertex in simplex.Vertices)
- {
- simplexVertices.Add(vertex);
- }
+ var simplexVertices = simplex.Vertices.Select(vertex => vertex.ToVector2()).ToImmutableArray();
var e0 = (simplexVertices[1].X - simplexVertices[0].X) * (simplexVertices[1].Y + simplexVertices[0].Y);
var e1 = (simplexVertices[2].X - simplexVertices[1].X) * (simplexVertices[2].Y + simplexVertices[1].Y);
@@ -55,25 +51,23 @@ namespace MoonTools.Core.Bonk
}
else
{
- simplexVertices.Insert(edge.index, support);
+ simplexVertices = simplexVertices.Insert(edge.index, support);
}
}
- simplexVertices.Dispose();
-
return intersection;
}
- private static Edge FindClosestEdge(PolygonWinding winding, PooledList simplexVertices)
+ private static Edge FindClosestEdge(PolygonWinding winding, ImmutableArray simplexVertices)
{
var closestDistance = float.PositiveInfinity;
var closestNormal = Vector2.Zero;
var closestIndex = 0;
- for (int i = 0; i < simplexVertices.Count; i++)
+ for (int i = 0; i < simplexVertices.Length; i++)
{
var j = i + 1;
- if (j >= simplexVertices.Count) { j = 0; }
+ if (j >= simplexVertices.Length) { j = 0; }
Vector2 edge = simplexVertices[j] - simplexVertices[i];
Vector2 norm;
diff --git a/Bonk/Shapes/Line.cs b/Bonk/Shapes/Line.cs
index 72f1362..10dd4a1 100644
--- a/Bonk/Shapes/Line.cs
+++ b/Bonk/Shapes/Line.cs
@@ -13,7 +13,7 @@ namespace MoonTools.Core.Bonk
private Position2D v0;
private Position2D v1;
- private IEnumerable vertices
+ private IEnumerable Vertices
{
get
{
@@ -39,7 +39,7 @@ namespace MoonTools.Core.Bonk
public AABB AABB(Transform2D Transform2D)
{
- return Bonk.AABB.FromTransformedVertices(vertices, Transform2D);
+ return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D);
}
public override bool Equals(object obj)
@@ -67,7 +67,7 @@ namespace MoonTools.Core.Bonk
var hashCode = -851829407;
hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(v0);
hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(v1);
- hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(vertices);
+ hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(Vertices);
return hashCode;
}
diff --git a/Bonk/Shapes/Polygon.cs b/Bonk/Shapes/Polygon.cs
index 44ecf93..0e10f48 100644
--- a/Bonk/Shapes/Polygon.cs
+++ b/Bonk/Shapes/Polygon.cs
@@ -1,26 +1,32 @@
using System.Linq;
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Numerics;
-using Collections.Pooled;
using MoonTools.Core.Structs;
using MoreLinq;
namespace MoonTools.Core.Bonk
{
///
- /// A Shape defined by an arbitrary collection of vertices. WARNING: Polygon must use an Array internally and therefore will create GC pressure.
+ /// A Shape defined by an arbitrary collection of vertices.
+ /// NOTE: A Polygon must have more than 2 vertices and should not have duplicate vertices.
///
public struct Polygon : IShape2D, IEquatable
{
- private PooledSet vertices;
+ private ImmutableArray vertices;
public IEnumerable Vertices { get { return vertices == null ? Enumerable.Empty() : vertices; } }
// vertices are local to the origin
public Polygon(params Position2D[] vertices)
{
- this.vertices = new PooledSet(vertices, ClearMode.Always);
+ this.vertices = ImmutableArray.Create(vertices);
+ }
+
+ public Polygon(ImmutableArray vertices)
+ {
+ this.vertices = vertices;
}
public Vector2 Support(Vector2 direction, Transform2D transform)
@@ -47,7 +53,19 @@ namespace MoonTools.Core.Bonk
{
if (other is Polygon otherPolygon)
{
- return vertices.SetEquals(otherPolygon.vertices);
+ var q = from a in vertices
+ join b in otherPolygon.vertices on a equals b
+ select a;
+
+ return vertices.Length == otherPolygon.vertices.Length && q.Count() == vertices.Length;
+ }
+ else if (other is Rectangle rectangle)
+ {
+ var q = from a in vertices
+ join b in rectangle.Vertices on a equals b
+ select a;
+
+ return vertices.Length == 4 && q.Count() == vertices.Length;
}
return false;
@@ -55,10 +73,7 @@ namespace MoonTools.Core.Bonk
public override int GetHashCode()
{
- var hashCode = -1404792980;
- hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(vertices);
- hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(Vertices);
- return hashCode;
+ return HashCode.Combine(vertices, Vertices);
}
public static bool operator ==(Polygon a, Polygon b)
@@ -70,5 +85,15 @@ namespace MoonTools.Core.Bonk
{
return !(a == b);
}
+
+ public static bool operator ==(Polygon a, Rectangle b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Polygon a, Rectangle b)
+ {
+ return !(a == b);
+ }
}
}
diff --git a/Bonk/Shapes/Rectangle.cs b/Bonk/Shapes/Rectangle.cs
index c1b46c6..9e5a001 100644
--- a/Bonk/Shapes/Rectangle.cs
+++ b/Bonk/Shapes/Rectangle.cs
@@ -17,7 +17,7 @@ namespace MoonTools.Core.Bonk
public int MaxX { get; }
public int MaxY { get; }
- private IEnumerable vertices
+ public IEnumerable Vertices
{
get
{
@@ -38,12 +38,12 @@ namespace MoonTools.Core.Bonk
public Vector2 Support(Vector2 direction, Transform2D transform)
{
- return vertices.Select(vertex => Vector2.Transform(vertex, transform.TransformMatrix)).MaxBy(transformed => Vector2.Dot(transformed, direction)).First();
+ return Vertices.Select(vertex => Vector2.Transform(vertex, transform.TransformMatrix)).MaxBy(transformed => Vector2.Dot(transformed, direction)).First();
}
public AABB AABB(Transform2D Transform2D)
{
- return Bonk.AABB.FromTransformedVertices(vertices, Transform2D);
+ return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D);
}
public override bool Equals(object obj)
@@ -76,7 +76,7 @@ namespace MoonTools.Core.Bonk
hashCode = hashCode * -1521134295 + MinY.GetHashCode();
hashCode = hashCode * -1521134295 + MaxX.GetHashCode();
hashCode = hashCode * -1521134295 + MaxY.GetHashCode();
- hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(vertices);
+ hashCode = hashCode * -1521134295 + EqualityComparer>.Default.GetHashCode(Vertices);
return hashCode;
}
diff --git a/Test/Equality.cs b/Test/Equality.cs
index fc6b6ef..e5921fd 100644
--- a/Test/Equality.cs
+++ b/Test/Equality.cs
@@ -253,6 +253,66 @@ namespace Tests
(a != b).Should().BeTrue();
}
+
+ [Test]
+ public void PolygonRectangleEqual()
+ {
+ var a = new Polygon(
+ new Position2D(1, 1),
+ new Position2D(1, -1),
+ new Position2D(-1, -1),
+ new Position2D(-1, 1)
+ );
+
+ var b = new Rectangle(-1, -1, 1, 1);
+
+ a.Should().BeEquivalentTo(b);
+ }
+
+ [Test]
+ public void PolygonRectangleNotEqual()
+ {
+ var a = new Polygon(
+ new Position2D(2, 1),
+ new Position2D(1, -1),
+ new Position2D(-1, -1),
+ new Position2D(-2, 1)
+ );
+
+ var b = new Rectangle(-1, -1, 1, 1);
+
+ a.Should().NotBeEquivalentTo(b);
+ }
+
+ [Test]
+ public void PolygonRectangleEqualOperator()
+ {
+ var a = new Polygon(
+ new Position2D(1, 1),
+ new Position2D(1, -1),
+ new Position2D(-1, -1),
+ new Position2D(-1, 1)
+ );
+
+ var b = new Rectangle(-1, -1, 1, 1);
+
+ (a == b).Should().BeTrue();
+ }
+
+ [Test]
+ public void PolygonRectangleNotEqualOperator()
+ {
+ var a = new Polygon(
+ new Position2D(2, 1),
+ new Position2D(1, -1),
+ new Position2D(-1, -1),
+ new Position2D(-2, 1)
+ );
+
+ var b = new Rectangle(-1, -1, 1, 1);
+
+ (a != b).Should().BeTrue();
+ }
}
public class SimplexTests