From 097790a41f7671adaf8e43614d310793b4af3248 Mon Sep 17 00:00:00 2001 From: Evan Hemsley Date: Wed, 1 Jan 2020 19:24:42 -0800 Subject: [PATCH] reorganization + AABB test when retrieving from spatial hash --- Bonk/AABB.cs | 35 +++++++++++++++++- Bonk/BroadPhase/SpatialHash.cs | 5 ++- Bonk/NarrowPhase/NarrowPhase.cs | 47 +------------------------ Bonk/NarrowPhase/SimplexVertexBuffer.cs | 47 +++++++++++++++++++++++++ Bonk/Shapes/Point.cs | 7 ++-- Bonk/{Shapes => }/Simplex.cs | 0 6 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 Bonk/NarrowPhase/SimplexVertexBuffer.cs rename Bonk/{Shapes => }/Simplex.cs (100%) diff --git a/Bonk/AABB.cs b/Bonk/AABB.cs index c3ca0f9..5a9473d 100644 --- a/Bonk/AABB.cs +++ b/Bonk/AABB.cs @@ -10,7 +10,15 @@ namespace MoonTools.Core.Bonk /// public struct AABB : IEquatable { + /// + /// The top-left position of the AABB. + /// + /// public Vector2 Min { get; private set; } + /// + /// The bottom-right position of the AABB. + /// + /// public Vector2 Max { get; private set; } 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 Left { get { return Min.X; } } - public float Top { get { return Min.Y; } } + /// + /// The top of the AABB. Assumes a downward-aligned Y axis, so this value will be smaller than Bottom. + /// + /// + public float Top { get { return Min.Y; } } + /// + /// The bottom of the AABB. Assumes a downward-aligned Y axis, so this value will be larger than Top. + /// + /// public float Bottom { get { return Max.Y; } } public AABB(float minX, float minY, float maxX, float maxY) @@ -44,6 +60,12 @@ namespace MoonTools.Core.Bonk ); } + /// + /// Efficiently transforms the AABB by a Transform2D. + /// + /// + /// + /// public static AABB Transformed(AABB aabb, Transform2D transform) { var center = (aabb.Min + aabb.Max) / 2f; @@ -55,6 +77,12 @@ namespace MoonTools.Core.Bonk return new AABB(newCenter - newExtent, newCenter + newExtent); } + /// + /// 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. + /// + /// + /// public static AABB FromVertices(IEnumerable vertices) { var minX = float.MaxValue; @@ -85,6 +113,11 @@ namespace MoonTools.Core.Bonk 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) { return obj is AABB aabb && Equals(aabb); diff --git a/Bonk/BroadPhase/SpatialHash.cs b/Bonk/BroadPhase/SpatialHash.cs index 0b2982a..0bf178e 100644 --- a/Bonk/BroadPhase/SpatialHash.cs +++ b/Bonk/BroadPhase/SpatialHash.cs @@ -73,7 +73,10 @@ namespace MoonTools.Core.Bonk foreach (var t in hashDictionary[key]) { 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); + } } } } diff --git a/Bonk/NarrowPhase/NarrowPhase.cs b/Bonk/NarrowPhase/NarrowPhase.cs index 4e7fc9a..337e7ce 100644 --- a/Bonk/NarrowPhase/NarrowPhase.cs +++ b/Bonk/NarrowPhase/NarrowPhase.cs @@ -1,53 +1,8 @@ using MoonTools.Core.Structs; using System.Numerics; -using System.Collections.Generic; namespace MoonTools.Core.Bonk { - internal unsafe struct SimplexVertexBuffer - { - private const int Size = 35; - - public int Length { get; private set; } - - public SimplexVertexBuffer(IEnumerable 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 { private enum PolygonWinding @@ -57,7 +12,7 @@ namespace MoonTools.Core.Bonk } /// - /// Tests if the two shape-transform pairs are overlapping. + /// Tests if two shape-transform pairs are overlapping. Automatically detects fast-path optimizations. /// public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) { diff --git a/Bonk/NarrowPhase/SimplexVertexBuffer.cs b/Bonk/NarrowPhase/SimplexVertexBuffer.cs new file mode 100644 index 0000000..799e42a --- /dev/null +++ b/Bonk/NarrowPhase/SimplexVertexBuffer.cs @@ -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 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]; +} diff --git a/Bonk/Shapes/Point.cs b/Bonk/Shapes/Point.cs index 79f8ee3..4aaed68 100644 --- a/Bonk/Shapes/Point.cs +++ b/Bonk/Shapes/Point.cs @@ -6,7 +6,6 @@ namespace MoonTools.Core.Bonk { public struct Point : IShape2D, IEquatable { - private Position2D Position { get; } public AABB AABB { get; } public AABB TransformedAABB(Transform2D transform) @@ -16,7 +15,7 @@ namespace MoonTools.Core.Bonk 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) @@ -31,12 +30,12 @@ namespace MoonTools.Core.Bonk public bool Equals(Point other) { - return Position == other.Position; + return true; } public override int GetHashCode() { - return HashCode.Combine(Position); + return 0; } public static bool operator ==(Point a, Point b) diff --git a/Bonk/Shapes/Simplex.cs b/Bonk/Simplex.cs similarity index 100% rename from Bonk/Shapes/Simplex.cs rename to Bonk/Simplex.cs