reorganization + AABB test when retrieving from spatial hash

generics
Evan Hemsley 2020-01-01 19:24:42 -08:00
parent f62c855c37
commit 097790a41f
6 changed files with 89 additions and 52 deletions

View File

@ -10,7 +10,15 @@ namespace MoonTools.Core.Bonk
/// </summary> /// </summary>
public struct AABB : IEquatable<AABB> public struct AABB : IEquatable<AABB>
{ {
/// <summary>
/// The top-left position of the AABB.
/// </summary>
/// <value></value>
public Vector2 Min { get; private set; } public Vector2 Min { get; private set; }
/// <summary>
/// The bottom-right position of the AABB.
/// </summary>
/// <value></value>
public Vector2 Max { get; private set; } public Vector2 Max { get; private set; }
public float Width { get { return Max.X - Min.X; } } public float Width { get { return Max.X - Min.X; } }
@ -18,7 +26,15 @@ namespace MoonTools.Core.Bonk
public float Right { get { return Max.X; } } public float Right { get { return Max.X; } }
public float Left { get { return Min.X; } } public float Left { get { return Min.X; } }
public float Top { get { return Min.Y; } } /// <summary>
/// The top of the AABB. Assumes a downward-aligned Y axis, so this value will be smaller than Bottom.
/// </summary>
/// <value></value>
public float Top { get { return Min.Y; } }
/// <summary>
/// The bottom of the AABB. Assumes a downward-aligned Y axis, so this value will be larger than Top.
/// </summary>
/// <value></value>
public float Bottom { get { return Max.Y; } } public float Bottom { get { return Max.Y; } }
public AABB(float minX, float minY, float maxX, float maxY) public AABB(float minX, float minY, float maxX, float maxY)
@ -44,6 +60,12 @@ namespace MoonTools.Core.Bonk
); );
} }
/// <summary>
/// Efficiently transforms the AABB by a Transform2D.
/// </summary>
/// <param name="aabb"></param>
/// <param name="transform"></param>
/// <returns></returns>
public static AABB Transformed(AABB aabb, Transform2D transform) public static AABB Transformed(AABB aabb, Transform2D transform)
{ {
var center = (aabb.Min + aabb.Max) / 2f; var center = (aabb.Min + aabb.Max) / 2f;
@ -55,6 +77,12 @@ namespace MoonTools.Core.Bonk
return new AABB(newCenter - newExtent, newCenter + newExtent); return new AABB(newCenter - newExtent, newCenter + newExtent);
} }
/// <summary>
/// Creates an AABB for an arbitrary collection of positions.
/// This is less efficient than defining a custom AABB method for most shapes, so avoid using this if possible.
/// </summary>
/// <param name="vertices"></param>
/// <returns></returns>
public static AABB FromVertices(IEnumerable<Position2D> vertices) public static AABB FromVertices(IEnumerable<Position2D> vertices)
{ {
var minX = float.MaxValue; var minX = float.MaxValue;
@ -85,6 +113,11 @@ namespace MoonTools.Core.Bonk
return new AABB(minX, minY, maxX, maxY); return new AABB(minX, minY, maxX, maxY);
} }
public static bool TestOverlap(AABB a, AABB b)
{
return a.Left <= b.Right && a.Right >= b.Left && a.Top <= b.Bottom && a.Bottom >= b.Top;
}
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is AABB aabb && Equals(aabb); return obj is AABB aabb && Equals(aabb);

View File

@ -73,7 +73,10 @@ namespace MoonTools.Core.Bonk
foreach (var t in hashDictionary[key]) foreach (var t in hashDictionary[key])
{ {
var (otherShape, otherTransform) = IDLookup[t]; var (otherShape, otherTransform) = IDLookup[t];
if (!id.Equals(t)) { yield return (t, otherShape, otherTransform); } if (!id.Equals(t) && AABB.TestOverlap(shape.TransformedAABB(transform2D), otherShape.TransformedAABB(otherTransform)))
{
yield return (t, otherShape, otherTransform);
}
} }
} }
} }

View File

@ -1,53 +1,8 @@
using MoonTools.Core.Structs; using MoonTools.Core.Structs;
using System.Numerics; using System.Numerics;
using System.Collections.Generic;
namespace MoonTools.Core.Bonk namespace MoonTools.Core.Bonk
{ {
internal unsafe struct SimplexVertexBuffer
{
private const int Size = 35;
public int Length { get; private set; }
public SimplexVertexBuffer(IEnumerable<Position2D> positions)
{
var i = 0;
foreach (var position in positions)
{
if (i == Size) { break; }
var vertex = position.ToVector2();
_simplexXBuffer[i] = vertex.X;
_simplexYBuffer[i] = vertex.Y;
i++;
}
Length = i;
}
public Vector2 this[int key]
{
get => new Vector2(_simplexXBuffer[key], _simplexYBuffer[key]);
private set
{
_simplexXBuffer[key] = value.X;
_simplexYBuffer[key] = value.Y;
}
}
public void Insert(int index, Vector2 value)
{
for (var i = Length; i > index; i--)
{
this[i] = this[i - 1];
}
this[index] = value;
Length++;
}
private fixed float _simplexXBuffer[Size];
private fixed float _simplexYBuffer[Size];
}
public static class NarrowPhase public static class NarrowPhase
{ {
private enum PolygonWinding private enum PolygonWinding
@ -57,7 +12,7 @@ namespace MoonTools.Core.Bonk
} }
/// <summary> /// <summary>
/// Tests if the two shape-transform pairs are overlapping. /// Tests if two shape-transform pairs are overlapping. Automatically detects fast-path optimizations.
/// </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)
{ {

View File

@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Numerics;
using MoonTools.Core.Structs;
internal unsafe struct SimplexVertexBuffer
{
private const int Size = 35;
public int Length { get; private set; }
public SimplexVertexBuffer(IEnumerable<Position2D> positions)
{
var i = 0;
foreach (var position in positions)
{
if (i == Size) { break; }
var vertex = position.ToVector2();
_simplexXBuffer[i] = vertex.X;
_simplexYBuffer[i] = vertex.Y;
i++;
}
Length = i;
}
public Vector2 this[int key]
{
get => new Vector2(_simplexXBuffer[key], _simplexYBuffer[key]);
private set
{
_simplexXBuffer[key] = value.X;
_simplexYBuffer[key] = value.Y;
}
}
public void Insert(int index, Vector2 value)
{
for (var i = Length; i > index; i--)
{
this[i] = this[i - 1];
}
this[index] = value;
Length++;
}
private fixed float _simplexXBuffer[Size];
private fixed float _simplexYBuffer[Size];
}

View File

@ -6,7 +6,6 @@ namespace MoonTools.Core.Bonk
{ {
public struct Point : IShape2D, IEquatable<Point> public struct Point : IShape2D, IEquatable<Point>
{ {
private Position2D Position { get; }
public AABB AABB { get; } public AABB AABB { get; }
public AABB TransformedAABB(Transform2D transform) public AABB TransformedAABB(Transform2D transform)
@ -16,7 +15,7 @@ namespace MoonTools.Core.Bonk
public Vector2 Support(Vector2 direction, Transform2D transform) public Vector2 Support(Vector2 direction, Transform2D transform)
{ {
return Vector2.Transform(Position.ToVector2(), transform.TransformMatrix); return Vector2.Transform(Vector2.Zero, transform.TransformMatrix);
} }
public override bool Equals(object obj) public override bool Equals(object obj)
@ -31,12 +30,12 @@ namespace MoonTools.Core.Bonk
public bool Equals(Point other) public bool Equals(Point other)
{ {
return Position == other.Position; return true;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCode.Combine(Position); return 0;
} }
public static bool operator ==(Point a, Point b) public static bool operator ==(Point a, Point b)