change collision API to support multi shapes

pull/19/head
cosmonaut 2022-04-18 11:33:40 -07:00
parent 65568ea234
commit dccd81e029
10 changed files with 107 additions and 26 deletions

View File

@ -77,6 +77,33 @@ namespace MoonWorks.Collision
return new AABB2D(newCenter - newExtent, newCenter + newExtent); 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);
}
/// <summary> /// <summary>
/// Creates an AABB for an arbitrary collection of positions. /// 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. /// This is less efficient than defining a custom AABB method for most shapes, so avoid using this if possible.

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
using MoonWorks.Math;
namespace MoonWorks.Collision
{
public interface ICollidable
{
IEnumerable<IShape2D> Shapes { get; }
AABB2D AABB { get; }
AABB2D TransformedAABB(Transform2D transform);
}
}

View File

@ -1,16 +0,0 @@
using MoonWorks.Math;
namespace MoonWorks.Collision
{
public interface IHasAABB2D
{
AABB2D AABB { get; }
/// <summary>
/// Returns a bounding box based on the shape.
/// </summary>
/// <param name="transform">A Transform for transforming the shape vertices.</param>
/// <returns>Returns a bounding box based on the shape.</returns>
AABB2D TransformedAABB(Transform2D transform);
}
}

View File

@ -2,7 +2,7 @@ using MoonWorks.Math;
namespace MoonWorks.Collision namespace MoonWorks.Collision
{ {
public interface IShape2D : IHasAABB2D, System.IEquatable<IShape2D> public interface IShape2D : ICollidable, System.IEquatable<IShape2D>
{ {
/// <summary> /// <summary>
/// A Minkowski support function. Gives the farthest point on the edge of a shape along the given direction. /// A Minkowski support function. Gives the farthest point on the edge of a shape along the given direction.

View File

@ -11,6 +11,22 @@ namespace MoonWorks.Collision
public int Index; 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) public static bool TestCollision(IShape2D shapeA, Transform2D transformA, IShape2D shapeB, Transform2D transformB)
{ {
// If we can use a fast path check, let's do that! // If we can use a fast path check, let's do that!

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using MoonWorks.Math; using MoonWorks.Math;
namespace MoonWorks.Collision namespace MoonWorks.Collision
@ -9,6 +10,13 @@ namespace MoonWorks.Collision
{ {
public int Radius { get; } public int Radius { get; }
public AABB2D AABB { get; } public AABB2D AABB { get; }
public IEnumerable<IShape2D> Shapes
{
get
{
yield return this;
}
}
public Circle(int radius) public Circle(int radius)
{ {

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using MoonWorks.Math; using MoonWorks.Math;
namespace MoonWorks.Collision namespace MoonWorks.Collision
@ -12,7 +13,15 @@ namespace MoonWorks.Collision
public AABB2D AABB { get; } public AABB2D AABB { get; }
public Line(Vector2 start, Vector2 end) public IEnumerable<IShape2D> Shapes
{
get
{
yield return this;
}
}
public Line(Vector2 start, Vector2 end)
{ {
Start = start; Start = start;
End = end; End = end;

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using MoonWorks.Math; using MoonWorks.Math;
namespace MoonWorks.Collision namespace MoonWorks.Collision
@ -9,6 +10,13 @@ namespace MoonWorks.Collision
public struct Point : IShape2D, System.IEquatable<Point> public struct Point : IShape2D, System.IEquatable<Point>
{ {
public AABB2D AABB { get; } public AABB2D AABB { get; }
public IEnumerable<IShape2D> Shapes
{
get
{
yield return this;
}
}
public AABB2D TransformedAABB(Transform2D transform) public AABB2D TransformedAABB(Transform2D transform)
{ {

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using MoonWorks.Math; using MoonWorks.Math;
namespace MoonWorks.Collision namespace MoonWorks.Collision
@ -15,12 +16,20 @@ namespace MoonWorks.Collision
public int Left { get; } public int Left { get; }
public int Top { get; } public int Top { get; }
public int Bottom { get; } public int Bottom { get; }
public Vector2 BottomLeft { get; } public Vector2 TopLeft { get; }
public Vector2 TopRight { get; } public Vector2 BottomRight { get; }
public Vector2 Min { get; } public Vector2 Min { get; }
public Vector2 Max { get; } public Vector2 Max { get; }
public IEnumerable<IShape2D> Shapes
{
get
{
yield return this;
}
}
public Rectangle(int left, int top, int width, int height) public Rectangle(int left, int top, int width, int height)
{ {
Width = width; Width = width;
@ -30,8 +39,8 @@ namespace MoonWorks.Collision
Top = top; Top = top;
Bottom = top + height; Bottom = top + height;
AABB = new AABB2D(left, top, Right, Bottom); AABB = new AABB2D(left, top, Right, Bottom);
BottomLeft = new Vector2(Left, Bottom); TopLeft = new Vector2(Left, Top);
TopRight = new Vector2(Top, Right); BottomRight = new Vector2(Right, Bottom);
Min = AABB.Min; Min = AABB.Min;
Max = AABB.Max; Max = AABB.Max;
} }

View File

@ -12,7 +12,7 @@ namespace MoonWorks.Collision
private readonly int cellSize; private readonly int cellSize;
private readonly Dictionary<long, HashSet<T>> hashDictionary = new Dictionary<long, HashSet<T>>(); private readonly Dictionary<long, HashSet<T>> hashDictionary = new Dictionary<long, HashSet<T>>();
private readonly Dictionary<T, (IHasAABB2D, Transform2D, uint)> IDLookup = new Dictionary<T, (IHasAABB2D, Transform2D, uint)>(); private readonly Dictionary<T, (ICollidable, Transform2D, uint)> IDLookup = new Dictionary<T, (ICollidable, Transform2D, uint)>();
public int MinX { get; private set; } = 0; public int MinX { get; private set; } = 0;
public int MaxX { get; private set; } = 0; public int MaxX { get; private set; } = 0;
@ -38,7 +38,7 @@ namespace MoonWorks.Collision
/// <param name="shape"></param> /// <param name="shape"></param>
/// <param name="transform2D"></param> /// <param name="transform2D"></param>
/// <param name="collisionGroups">A bitmask value specifying the groups this object belongs to.</param> /// <param name="collisionGroups">A bitmask value specifying the groups this object belongs to.</param>
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 box = shape.TransformedAABB(transform2D);
var minHash = Hash(box.Min); var minHash = Hash(box.Min);
@ -68,7 +68,7 @@ namespace MoonWorks.Collision
/// <summary> /// <summary>
/// Retrieves all the potential collisions of a shape-transform pair. Excludes any shape-transforms with the given ID. /// Retrieves all the potential collisions of a shape-transform pair. Excludes any shape-transforms with the given ID.
/// </summary> /// </summary>
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(); var returned = AcquireHashSet();
@ -113,7 +113,7 @@ namespace MoonWorks.Collision
/// </summary> /// </summary>
/// <param name="aabb">A transformed AABB.</param> /// <param name="aabb">A transformed AABB.</param>
/// <returns></returns> /// <returns></returns>
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(); var returned = AcquireHashSet();
@ -150,6 +150,14 @@ namespace MoonWorks.Collision
FreeHashSet(returned); FreeHashSet(returned);
} }
/// <summary>
/// Removes a specific ID from the SpatialHash.
/// </summary>
public void Remove(T id)
{
}
/// <summary> /// <summary>
/// Removes everything that has been inserted into the SpatialHash. /// Removes everything that has been inserted into the SpatialHash.
/// </summary> /// </summary>