From dccd81e02965ac220df10ce06aadd5c27d0d6cf3 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 18 Apr 2022 11:33:40 -0700 Subject: [PATCH] change collision API to support multi shapes --- src/Collision/AABB2D.cs | 27 +++++++++++++++++++++++++++ src/Collision/ICollidable.cs | 12 ++++++++++++ src/Collision/IHasAABB2D.cs | 16 ---------------- src/Collision/IShape2D.cs | 2 +- src/Collision/NarrowPhase.cs | 16 ++++++++++++++++ src/Collision/Shapes/Circle.cs | 8 ++++++++ src/Collision/Shapes/Line.cs | 11 ++++++++++- src/Collision/Shapes/Point.cs | 8 ++++++++ src/Collision/Shapes/Rectangle.cs | 17 +++++++++++++---- src/Collision/SpatialHash2D.cs | 16 ++++++++++++---- 10 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 src/Collision/ICollidable.cs delete mode 100644 src/Collision/IHasAABB2D.cs diff --git a/src/Collision/AABB2D.cs b/src/Collision/AABB2D.cs index 5f3f932..207917a 100644 --- a/src/Collision/AABB2D.cs +++ b/src/Collision/AABB2D.cs @@ -77,6 +77,33 @@ namespace MoonWorks.Collision return new AABB2D(newCenter - newExtent, newCenter + newExtent); } + public AABB2D Compose(AABB2D aabb) + { + float left = Left; + float top = Top; + float right = Right; + float bottom = Bottom; + + if (aabb.Left < left) + { + left = aabb.Left; + } + if (aabb.Right > right) + { + right = aabb.Right; + } + if (aabb.Top < top) + { + top = aabb.Top; + } + if (aabb.Bottom > bottom) + { + bottom = aabb.Bottom; + } + + return new AABB2D(left, top, right, bottom); + } + /// /// 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. diff --git a/src/Collision/ICollidable.cs b/src/Collision/ICollidable.cs new file mode 100644 index 0000000..9e8b9b2 --- /dev/null +++ b/src/Collision/ICollidable.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using MoonWorks.Math; + +namespace MoonWorks.Collision +{ + public interface ICollidable + { + IEnumerable Shapes { get; } + AABB2D AABB { get; } + AABB2D TransformedAABB(Transform2D transform); + } +} diff --git a/src/Collision/IHasAABB2D.cs b/src/Collision/IHasAABB2D.cs deleted file mode 100644 index 31bb5b3..0000000 --- a/src/Collision/IHasAABB2D.cs +++ /dev/null @@ -1,16 +0,0 @@ -using MoonWorks.Math; - -namespace MoonWorks.Collision -{ - public interface IHasAABB2D - { - AABB2D AABB { get; } - - /// - /// Returns a bounding box based on the shape. - /// - /// A Transform for transforming the shape vertices. - /// Returns a bounding box based on the shape. - AABB2D TransformedAABB(Transform2D transform); - } -} diff --git a/src/Collision/IShape2D.cs b/src/Collision/IShape2D.cs index 91f224a..2b48d47 100644 --- a/src/Collision/IShape2D.cs +++ b/src/Collision/IShape2D.cs @@ -2,7 +2,7 @@ using MoonWorks.Math; namespace MoonWorks.Collision { - public interface IShape2D : IHasAABB2D, System.IEquatable + public interface IShape2D : ICollidable, System.IEquatable { /// /// A Minkowski support function. Gives the farthest point on the edge of a shape along the given direction. diff --git a/src/Collision/NarrowPhase.cs b/src/Collision/NarrowPhase.cs index 7197875..14442fa 100644 --- a/src/Collision/NarrowPhase.cs +++ b/src/Collision/NarrowPhase.cs @@ -11,6 +11,22 @@ namespace MoonWorks.Collision public int Index; } + public static bool TestCollision(ICollidable collidableA, Transform2D transformA, ICollidable collidableB, Transform2D transformB) + { + foreach (var shapeA in collidableA.Shapes) + { + foreach (var shapeB in collidableB.Shapes) + { + if (TestCollision(shapeA, transformA, shapeB, transformB)) + { + return true; + } + } + } + + return false; + } + public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB) { // If we can use a fast path check, let's do that! diff --git a/src/Collision/Shapes/Circle.cs b/src/Collision/Shapes/Circle.cs index 579e63f..49fb46e 100644 --- a/src/Collision/Shapes/Circle.cs +++ b/src/Collision/Shapes/Circle.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using MoonWorks.Math; namespace MoonWorks.Collision @@ -9,6 +10,13 @@ namespace MoonWorks.Collision { public int Radius { get; } public AABB2D AABB { get; } + public IEnumerable Shapes + { + get + { + yield return this; + } + } public Circle(int radius) { diff --git a/src/Collision/Shapes/Line.cs b/src/Collision/Shapes/Line.cs index 72efd67..5948704 100644 --- a/src/Collision/Shapes/Line.cs +++ b/src/Collision/Shapes/Line.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using MoonWorks.Math; namespace MoonWorks.Collision @@ -12,7 +13,15 @@ namespace MoonWorks.Collision public AABB2D AABB { get; } - public Line(Vector2 start, Vector2 end) + public IEnumerable Shapes + { + get + { + yield return this; + } + } + + public Line(Vector2 start, Vector2 end) { Start = start; End = end; diff --git a/src/Collision/Shapes/Point.cs b/src/Collision/Shapes/Point.cs index 7bdc672..41fdeee 100644 --- a/src/Collision/Shapes/Point.cs +++ b/src/Collision/Shapes/Point.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using MoonWorks.Math; namespace MoonWorks.Collision @@ -9,6 +10,13 @@ namespace MoonWorks.Collision public struct Point : IShape2D, System.IEquatable { public AABB2D AABB { get; } + public IEnumerable Shapes + { + get + { + yield return this; + } + } public AABB2D TransformedAABB(Transform2D transform) { diff --git a/src/Collision/Shapes/Rectangle.cs b/src/Collision/Shapes/Rectangle.cs index 09681ab..3653b62 100644 --- a/src/Collision/Shapes/Rectangle.cs +++ b/src/Collision/Shapes/Rectangle.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using MoonWorks.Math; namespace MoonWorks.Collision @@ -15,12 +16,20 @@ namespace MoonWorks.Collision public int Left { get; } public int Top { get; } public int Bottom { get; } - public Vector2 BottomLeft { get; } - public Vector2 TopRight { get; } + public Vector2 TopLeft { get; } + public Vector2 BottomRight { get; } public Vector2 Min { get; } public Vector2 Max { get; } + public IEnumerable Shapes + { + get + { + yield return this; + } + } + public Rectangle(int left, int top, int width, int height) { Width = width; @@ -30,8 +39,8 @@ namespace MoonWorks.Collision Top = top; Bottom = top + height; AABB = new AABB2D(left, top, Right, Bottom); - BottomLeft = new Vector2(Left, Bottom); - TopRight = new Vector2(Top, Right); + TopLeft = new Vector2(Left, Top); + BottomRight = new Vector2(Right, Bottom); Min = AABB.Min; Max = AABB.Max; } diff --git a/src/Collision/SpatialHash2D.cs b/src/Collision/SpatialHash2D.cs index d9748e5..522e681 100644 --- a/src/Collision/SpatialHash2D.cs +++ b/src/Collision/SpatialHash2D.cs @@ -12,7 +12,7 @@ namespace MoonWorks.Collision private readonly int cellSize; private readonly Dictionary> hashDictionary = new Dictionary>(); - private readonly Dictionary IDLookup = new Dictionary(); + private readonly Dictionary IDLookup = new Dictionary(); public int MinX { get; private set; } = 0; public int MaxX { get; private set; } = 0; @@ -38,7 +38,7 @@ namespace MoonWorks.Collision /// /// /// A bitmask value specifying the groups this object belongs to. - public void Insert(T id, IHasAABB2D shape, Transform2D transform2D, uint collisionGroups = uint.MaxValue) + public void Insert(T id, ICollidable shape, Transform2D transform2D, uint collisionGroups = uint.MaxValue) { var box = shape.TransformedAABB(transform2D); var minHash = Hash(box.Min); @@ -68,7 +68,7 @@ namespace MoonWorks.Collision /// /// Retrieves all the potential collisions of a shape-transform pair. Excludes any shape-transforms with the given ID. /// - public IEnumerable<(T, IHasAABB2D, Transform2D, uint)> Retrieve(T id, IHasAABB2D shape, Transform2D transform2D, uint collisionMask = uint.MaxValue) + public IEnumerable<(T, ICollidable, Transform2D, uint)> Retrieve(T id, ICollidable shape, Transform2D transform2D, uint collisionMask = uint.MaxValue) { var returned = AcquireHashSet(); @@ -113,7 +113,7 @@ namespace MoonWorks.Collision /// /// A transformed AABB. /// - public IEnumerable<(T, IHasAABB2D, Transform2D, uint)> Retrieve(AABB2D aabb, uint collisionMask = uint.MaxValue) + public IEnumerable<(T, ICollidable, Transform2D, uint)> Retrieve(AABB2D aabb, uint collisionMask = uint.MaxValue) { var returned = AcquireHashSet(); @@ -150,6 +150,14 @@ namespace MoonWorks.Collision FreeHashSet(returned); } + /// + /// Removes a specific ID from the SpatialHash. + /// + public void Remove(T id) + { + + } + /// /// Removes everything that has been inserted into the SpatialHash. ///