using Unity.Mathematics; namespace GameCommon.Spatial { public struct SpatialHash { public const int Goffset = 10000; public const int Max = 20480; public int CellSize; public float ConvFactor; public int Width; public static SpatialHash Default { get { return new SpatialHash(100); } } public SpatialHash(int cellSize) { CellSize = cellSize; ConvFactor = 1.0f / CellSize; Width = Max / CellSize; } public int HashWithOffset(float x, float y) { x += Goffset; y += Goffset; return Hash(x, y); } public int Hash(float x, float y) { return (int)((x * ConvFactor)) + (int)((y * ConvFactor)) * Width; } public bool InRangeOf(float x0, float y0, float x1, float y1) { int otherHash = HashWithOffset(x1, y1); x0 += Goffset; y0 += Goffset; SetStartEnd(x0, y0, out int2 start, out int2 end); for (int rowNum = start.x; rowNum <= end.x; rowNum += CellSize) { for (int colNum = start.y; colNum <= end.y; colNum += CellSize) { if (rowNum >= 0 && colNum >= 0) { int hash = Hash(rowNum, colNum); if (hash == otherHash) { return true; } } } } return false; } public int CellsWithinBounds(float x, float y, int[] cells) { int index = 0; x += Goffset; y += Goffset; SetStartEnd(x, y, out int2 start, out int2 end); for (int rowNum = start.x; rowNum <= end.x; rowNum += CellSize) { for (int colNum = start.y; colNum <= end.y; colNum += CellSize) { if (rowNum >= 0 && colNum >= 0) { cells[index] = Hash(rowNum, colNum); index++; } } } return index; } public void SetStartEnd(float x, float y, out int2 start, out int2 end) { start = new int2 { x = (int)(x - CellSize), y = (int)(y - CellSize) }; end = new int2 { x = (int)(x + CellSize), y = (int)(y + CellSize) }; } } }