diff --git a/src/Collision/Fixed/SpatialHash2D.cs b/src/Collision/Fixed/SpatialHash2D.cs
index 0821799..9d1a87a 100644
--- a/src/Collision/Fixed/SpatialHash2D.cs
+++ b/src/Collision/Fixed/SpatialHash2D.cs
@@ -7,17 +7,20 @@ namespace MoonWorks.Collision.Fixed
/// Used to quickly check if two shapes are potentially overlapping.
///
/// The type that will be used to uniquely identify shape-transform pairs.
- public class SpatialHash2D where T : struct, System.IEquatable where U : IHasAABB2D
+ public class SpatialHash2D where T : struct, System.IEquatable
{
private readonly Fix64 cellSize;
private readonly Dictionary> hashDictionary = new Dictionary>();
- private readonly Dictionary IDLookup = new Dictionary();
+ private readonly Dictionary IDBoxLookup = new Dictionary();
+ private readonly Dictionary IDDataLookup = new Dictionary();
- public int MinX { get; private set; } = 0;
- public int MaxX { get; private set; } = 0;
- public int MinY { get; private set; } = 0;
- public int MaxY { get; private set; } = 0;
+ private readonly HashSet DynamicIDs = new HashSet();
+
+ private int MinX;
+ private int MaxX;
+ private int MinY;
+ private int MaxY;
private Queue> hashSetPool = new Queue>();
@@ -35,12 +38,11 @@ namespace MoonWorks.Collision.Fixed
/// Inserts an element into the SpatialHash.
///
/// A unique ID for the shape-transform pair.
- ///
- ///
- /// A bitmask value specifying the groups this object belongs to.
- public void Insert(T id, U shape, Transform2D transform2D, uint collisionGroups = uint.MaxValue)
+ public void Insert(T id, AABB2D aabb, Transform2D transform2D, U data, bool dynamic = true)
{
- var box = AABB2D.Transformed(shape.AABB, transform2D);
+ Remove(id);
+
+ var box = AABB2D.Transformed(aabb, transform2D);
var minHash = Hash(box.Min);
var maxHash = Hash(box.Max);
@@ -52,19 +54,26 @@ namespace MoonWorks.Collision.Fixed
}
hashDictionary[key].Add(id);
- IDLookup[id] = (shape, transform2D, collisionGroups);
+ IDDataLookup[id] = data;
}
MinX = System.Math.Min(MinX, minHash.Item1);
MinY = System.Math.Min(MinY, minHash.Item2);
MaxX = System.Math.Max(MaxX, maxHash.Item1);
MaxY = System.Math.Max(MaxY, maxHash.Item2);
+
+ if (dynamic)
+ {
+ DynamicIDs.Add(id);
+ }
+
+ IDBoxLookup[id] = box;
}
///
/// Retrieves all the potential collisions of a shape-transform pair. Excludes any shape-transforms with the given ID.
///
- public RetrieveEnumerator Retrieve(T id, V hasAABB, Transform2D transform2D, uint collisionMask = uint.MaxValue) where V : IHasAABB2D
+ public RetrieveEnumerator Retrieve(T id, V hasAABB, Transform2D transform2D) where V : IHasAABB2D
{
var box = AABB2D.Transformed(hasAABB.AABB, transform2D);
var (minX, minY) = Hash(box.Min);
@@ -78,18 +87,17 @@ namespace MoonWorks.Collision.Fixed
return new RetrieveEnumerator(
this,
Keys(minX, minY, maxX, maxY),
- id,
- collisionMask
+ id
);
}
///
/// Retrieves all the potential collisions of a shape-transform pair.
///
- public RetrieveEnumerator Retrieve(V hasAABB, Transform2D transform2D, uint collisionMask = uint.MaxValue) where V : IHasAABB2D
+ public RetrieveEnumerator Retrieve(V hasAABB, Transform2D transform2D) where V : IHasAABB2D
{
var box = AABB2D.Transformed(hasAABB.AABB, transform2D);
- return Retrieve(box, collisionMask);
+ return Retrieve(box);
}
///
@@ -97,7 +105,7 @@ namespace MoonWorks.Collision.Fixed
///
/// A transformed AABB.
///
- public RetrieveEnumerator Retrieve(AABB2D aabb, uint collisionMask = uint.MaxValue)
+ public RetrieveEnumerator Retrieve(T id, AABB2D aabb)
{
var (minX, minY) = Hash(aabb.Min);
var (maxX, maxY) = Hash(aabb.Max);
@@ -110,14 +118,29 @@ namespace MoonWorks.Collision.Fixed
return new RetrieveEnumerator(
this,
Keys(minX, minY, maxX, maxY),
- collisionMask
+ id
);
}
- public void Update(T id, U shape, Transform2D transform2D, uint collisionGroups = uint.MaxValue)
+ ///
+ /// Retrieves objects based on a pre-transformed AABB.
+ ///
+ /// A transformed AABB.
+ ///
+ public RetrieveEnumerator Retrieve(AABB2D aabb)
{
- Remove(id);
- Insert(id, shape, transform2D, collisionGroups);
+ var (minX, minY) = Hash(aabb.Min);
+ var (maxX, maxY) = Hash(aabb.Max);
+
+ if (minX < MinX) { minX = MinX; }
+ if (maxX > MaxX) { maxX = MaxX; }
+ if (minY < MinY) { minY = MinY; }
+ if (maxY > MaxY) { maxY = MaxY; }
+
+ return new RetrieveEnumerator(
+ this,
+ Keys(minX, minY, maxX, maxY)
+ );
}
///
@@ -125,24 +148,24 @@ namespace MoonWorks.Collision.Fixed
///
public void Remove(T id)
{
- if (IDLookup.TryGetValue(id, out var data))
+ if (IDBoxLookup.TryGetValue(id, out var aabb))
{
- var (shape, transform, collisionGroups) = data;
-
- var box = AABB2D.Transformed(shape.AABB, transform);
- var minHash = Hash(box.Min);
- var maxHash = Hash(box.Max);
+ var minHash = Hash(aabb.Min);
+ var maxHash = Hash(aabb.Max);
foreach (var key in Keys(minHash.Item1, minHash.Item2, maxHash.Item1, maxHash.Item2))
{
- if (hashDictionary.ContainsKey(key))
+ if (hashDictionary.TryGetValue(key, out HashSet value))
{
- hashDictionary[key].Remove(id);
+ value.Remove(id);
}
}
- IDLookup.Remove(id);
+ IDDataLookup.Remove(id);
+ IDBoxLookup.Remove(id);
}
+
+ DynamicIDs.Remove(id);
}
///
@@ -155,7 +178,19 @@ namespace MoonWorks.Collision.Fixed
hash.Clear();
}
- IDLookup.Clear();
+ IDDataLookup.Clear();
+ IDBoxLookup.Clear();
+ }
+
+ ///
+ /// Removes
+ ///
+ public void ClearDynamic()
+ {
+ foreach (var id in DynamicIDs)
+ {
+ Remove(id);
+ }
}
private static long MakeLong(int left, int right)
@@ -239,15 +274,13 @@ namespace MoonWorks.Collision.Fixed
private bool HashSetEnumeratorActive;
private HashSet Duplicates;
private T? ID;
- private uint CollisionMask;
public RetrieveEnumerator GetEnumerator() => this;
internal RetrieveEnumerator(
SpatialHash2D spatialHash,
KeysEnumerator keysEnumerator,
- T id,
- uint collisionMask
+ T id
) {
SpatialHash = spatialHash;
KeysEnumerator = keysEnumerator;
@@ -255,13 +288,11 @@ namespace MoonWorks.Collision.Fixed
HashSetEnumeratorActive = false;
Duplicates = SpatialHash.AcquireHashSet();
ID = id;
- CollisionMask = collisionMask;
}
internal RetrieveEnumerator(
SpatialHash2D spatialHash,
- KeysEnumerator keysEnumerator,
- uint collisionMask
+ KeysEnumerator keysEnumerator
) {
SpatialHash = spatialHash;
KeysEnumerator = keysEnumerator;
@@ -269,7 +300,6 @@ namespace MoonWorks.Collision.Fixed
HashSetEnumeratorActive = false;
Duplicates = SpatialHash.AcquireHashSet();
ID = null;
- CollisionMask = collisionMask;
}
public bool MoveNext()
@@ -293,7 +323,6 @@ namespace MoonWorks.Collision.Fixed
// conditions
var t = HashSetEnumerator.Current;
- var collisionGroups = SpatialHash.IDLookup[t].Item3;
if (Duplicates.Contains(t))
{
@@ -302,7 +331,7 @@ namespace MoonWorks.Collision.Fixed
if (ID.HasValue)
{
- if (ID.Value.Equals(t) || (CollisionMask & collisionGroups) == 0)
+ if (ID.Value.Equals(t))
{
return MoveNext();
}
@@ -312,13 +341,13 @@ namespace MoonWorks.Collision.Fixed
return true;
}
- public (T, U, Transform2D, uint) Current
+ public (T, U) Current
{
get
{
var t = HashSetEnumerator.Current;
- var (u, transform, groups) = SpatialHash.IDLookup[t];
- return (t, u, transform, groups);
+ var u = SpatialHash.IDDataLookup[t];
+ return (t, u);
}
}
}