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);
}
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>
/// 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.

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
{
public interface IShape2D : IHasAABB2D, System.IEquatable<IShape2D>
public interface IShape2D : ICollidable, System.IEquatable<IShape2D>
{
/// <summary>
/// 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 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!

View File

@ -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<IShape2D> Shapes
{
get
{
yield return this;
}
}
public Circle(int radius)
{

View File

@ -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<IShape2D> Shapes
{
get
{
yield return this;
}
}
public Line(Vector2 start, Vector2 end)
{
Start = start;
End = end;

View File

@ -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<Point>
{
public AABB2D AABB { get; }
public IEnumerable<IShape2D> Shapes
{
get
{
yield return this;
}
}
public AABB2D TransformedAABB(Transform2D transform)
{

View File

@ -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<IShape2D> 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;
}

View File

@ -12,7 +12,7 @@ namespace MoonWorks.Collision
private readonly int cellSize;
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 MaxX { get; private set; } = 0;
@ -38,7 +38,7 @@ namespace MoonWorks.Collision
/// <param name="shape"></param>
/// <param name="transform2D"></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 minHash = Hash(box.Min);
@ -68,7 +68,7 @@ namespace MoonWorks.Collision
/// <summary>
/// Retrieves all the potential collisions of a shape-transform pair. Excludes any shape-transforms with the given ID.
/// </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();
@ -113,7 +113,7 @@ namespace MoonWorks.Collision
/// </summary>
/// <param name="aabb">A transformed AABB.</param>
/// <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();
@ -150,6 +150,14 @@ namespace MoonWorks.Collision
FreeHashSet(returned);
}
/// <summary>
/// Removes a specific ID from the SpatialHash.
/// </summary>
public void Remove(T id)
{
}
/// <summary>
/// Removes everything that has been inserted into the SpatialHash.
/// </summary>