forked from MoonsideGames/MoonTools.Bonk
even better gc optimization
parent
2a715e71db
commit
20872021fc
|
@ -22,15 +22,14 @@ namespace MoonTools.Core.Bonk
|
||||||
public static class EPA2D
|
public static class EPA2D
|
||||||
{
|
{
|
||||||
// vector returned gives direction from A to B
|
// vector returned gives direction from A to B
|
||||||
public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, (Func<Vector2, Vector2>, Vector2, Vector2) givenSimplexVertices)
|
public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex givenSimplex)
|
||||||
{
|
{
|
||||||
var simplexVertices = new SimplexVertices(new Vector2?[36]);
|
var simplexVertices = new SimplexVertices(new Vector2?[36]);
|
||||||
|
|
||||||
var (simplexSupport, a, b) = givenSimplexVertices;
|
foreach (var vertex in givenSimplex.Vertices)
|
||||||
simplexVertices.Add(simplexSupport(a));
|
{
|
||||||
simplexVertices.Add(simplexSupport(b));
|
simplexVertices.Add(vertex);
|
||||||
simplexVertices.Add(simplexSupport(-a));
|
}
|
||||||
simplexVertices.Add(simplexSupport(-b));
|
|
||||||
|
|
||||||
var e0 = (simplexVertices[1].X - simplexVertices[0].X) * (simplexVertices[1].Y + simplexVertices[0].Y);
|
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);
|
var e1 = (simplexVertices[2].X - simplexVertices[1].X) * (simplexVertices[2].Y + simplexVertices[1].Y);
|
||||||
|
|
115
Bonk/GJK2D.cs
115
Bonk/GJK2D.cs
|
@ -2,43 +2,126 @@
|
||||||
using MoonTools.Core.Structs;
|
using MoonTools.Core.Structs;
|
||||||
using System;
|
using System;
|
||||||
using MoonTools.Core.Bonk.Extensions;
|
using MoonTools.Core.Bonk.Extensions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MoonTools.Core.Bonk
|
namespace MoonTools.Core.Bonk
|
||||||
{
|
{
|
||||||
// TODO: get rid of minkowski closure for GC purposes
|
public struct MinkowskiDifference : IEquatable<MinkowskiDifference>
|
||||||
|
{
|
||||||
|
private IShape2D shapeA;
|
||||||
|
private Transform2D transformA;
|
||||||
|
private IShape2D shapeB;
|
||||||
|
private Transform2D transformB;
|
||||||
|
|
||||||
|
public MinkowskiDifference(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
||||||
|
{
|
||||||
|
this.shapeA = shapeA;
|
||||||
|
this.transformA = transformA;
|
||||||
|
this.shapeB = shapeB;
|
||||||
|
this.transformB = transformB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(MinkowskiDifference other)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
shapeA == other.shapeA &&
|
||||||
|
transformA.Equals(other.transformA) &&
|
||||||
|
shapeB == other.shapeB &&
|
||||||
|
transformB.Equals(other.transformB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Support(Vector2 direction)
|
||||||
|
{
|
||||||
|
return shapeA.Support(direction, transformA) - shapeB.Support(-direction, transformB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Simplex : IShape2D
|
||||||
|
{
|
||||||
|
MinkowskiDifference minkowskiDifference;
|
||||||
|
Vector2 directionA;
|
||||||
|
Vector2 directionB;
|
||||||
|
|
||||||
|
public Simplex(MinkowskiDifference minkowskiDifference, Vector2 directionA, Vector2 directionB)
|
||||||
|
{
|
||||||
|
this.minkowskiDifference = minkowskiDifference;
|
||||||
|
this.directionA = directionA;
|
||||||
|
this.directionB = directionB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Position2D> Vertices
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return (Position2D)Support(directionA);
|
||||||
|
yield return (Position2D)Support(directionB);
|
||||||
|
yield return (Position2D)Support(-(directionB - directionA).Perpendicular());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AABB AABB(Transform2D transform)
|
||||||
|
{
|
||||||
|
return Bonk.AABB.FromTransformedVertices(Vertices, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(IShape2D other)
|
||||||
|
{
|
||||||
|
if (other is Simplex polytope)
|
||||||
|
{
|
||||||
|
return minkowskiDifference.Equals(polytope.minkowskiDifference) &&
|
||||||
|
directionA == polytope.directionA &&
|
||||||
|
directionB == polytope.directionB;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Support(Vector2 direction)
|
||||||
|
{
|
||||||
|
return minkowskiDifference.Support(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Support(Vector2 direction, Transform2D transform)
|
||||||
|
{
|
||||||
|
return Vector2.Transform(Support(direction), transform.TransformMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class GJK2D
|
public static class GJK2D
|
||||||
{
|
{
|
||||||
public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
||||||
{
|
{
|
||||||
return OriginInside(MinkowskiDifference(shapeA, transformA, shapeB, transformB));
|
var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB);
|
||||||
|
return OriginInside(minkowskiDifference);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (bool, (Func<Vector2, Vector2>, Vector2, Vector2)) CollisionAndSimplex(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
public static (bool, Simplex) CollisionAndSimplex(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
||||||
{
|
{
|
||||||
var support = MinkowskiDifference(shapeA, transformA, shapeB, transformB);
|
var minkowskiDifference = new MinkowskiDifference(shapeA, transformA, shapeB, transformB);
|
||||||
var result = OriginInsideWithSimplex(support);
|
var (collision, a, b) = OriginInsideWithSimplex(minkowskiDifference);
|
||||||
return (result.Item1, (support, result.Item2, result.Item3));
|
var polytope = new Simplex(minkowskiDifference, a, b);
|
||||||
|
return (collision, polytope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Func<Vector2, Vector2> MinkowskiDifference(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
private static Vector2 MinkowskiDifference(Vector2 direction, IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
|
||||||
{
|
{
|
||||||
return direction => shapeA.Support(direction, transformA) - shapeB.Support(-direction, transformB);
|
return shapeA.Support(direction, transformA) - shapeB.Support(-direction, transformB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool OriginInside(Func<Vector2, Vector2> support)
|
private static bool OriginInside(MinkowskiDifference minkowskiDifference)
|
||||||
{
|
{
|
||||||
var a = support(Vector2.UnitX);
|
var a = minkowskiDifference.Support(Vector2.UnitX);
|
||||||
var b = support(-a);
|
var b = minkowskiDifference.Support(-a);
|
||||||
|
|
||||||
return Vector2.Dot(a, b) > 0 ? false : CheckSimplex(support, a, b);
|
return Vector2.Dot(a, b) > 0 ? false : CheckSimplex(minkowskiDifference.Support, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (bool, Vector2, Vector2) OriginInsideWithSimplex(Func<Vector2, Vector2> support)
|
private static (bool, Vector2, Vector2) OriginInsideWithSimplex(MinkowskiDifference minkowskiDifference)
|
||||||
{
|
{
|
||||||
var a = support(Vector2.UnitX);
|
var a = minkowskiDifference.Support(Vector2.UnitX);
|
||||||
var b = support(-a);
|
var b = minkowskiDifference.Support(-a);
|
||||||
|
|
||||||
return Vector2.Dot(a, b) > 0 ? (false, a, b) : Simplex(support, a, b);
|
return Vector2.Dot(a, b) > 0 ? (false, a, b) : Simplex(minkowskiDifference.Support, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CheckSimplex(Func<Vector2, Vector2> support, Vector2 a, Vector2 b)
|
private static bool CheckSimplex(Func<Vector2, Vector2> support, Vector2 a, Vector2 b)
|
||||||
|
|
Loading…
Reference in New Issue