13 if (cellSize <= 0.f) {
14 throw Exception(
"SpatialHash3D: cellSize must be > 0");
16 if (!items_.empty() && cellSize != cellSize_) {
17 auto snapshot = items_;
20 for (
const auto &kv : snapshot) {
21 insert(kv.first, kv.second.minX, kv.second.minY, kv.second.minZ, kv.second.maxX,
22 kv.second.maxY, kv.second.maxZ);
37void SpatialHash3D::cellRange(
const AABB3 &
b,
int &minCX,
int &minCY,
int &minCZ,
int &maxCX,
38 int &maxCY,
int &maxCZ)
const {
39 minCX =
static_cast<int>(std::floor(
b.minX / cellSize_));
40 minCY =
static_cast<int>(std::floor(
b.minY / cellSize_));
41 minCZ =
static_cast<int>(std::floor(
b.minZ / cellSize_));
42 maxCX =
static_cast<int>(std::floor(
b.maxX / cellSize_));
43 maxCY =
static_cast<int>(std::floor(
b.maxY / cellSize_));
44 maxCZ =
static_cast<int>(std::floor(
b.maxZ / cellSize_));
47void SpatialHash3D::insertCells(
int id,
const AABB3 &
b) {
48 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
49 cellRange(
b, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
50 for (
int cz = minCZ; cz <= maxCZ; ++cz) {
51 for (
int cy = minCY;
cy <= maxCY; ++
cy) {
52 for (
int cx = minCX;
cx <= maxCX; ++
cx) {
59void SpatialHash3D::eraseCells(
int id,
const AABB3 &
b) {
60 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
61 cellRange(
b, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
62 for (
int cz = minCZ; cz <= maxCZ; ++cz) {
63 for (
int cy = minCY;
cy <= maxCY; ++
cy) {
64 for (
int cx = minCX;
cx <= maxCX; ++
cx) {
66 if (it == cells_.end())
continue;
67 auto &vec = it->second;
68 vec.erase(std::remove(vec.begin(), vec.end(),
id), vec.end());
69 if (vec.empty()) cells_.erase(it);
78 if (!
b.valid())
return false;
86 auto it = items_.find(
id);
87 if (it == items_.end())
return false;
88 eraseCells(
id, it->second);
96 return insert(
id, minX, minY, minZ, maxX, maxY, maxZ);
99void SpatialHash3D::queryCells(
int minCX,
int minCY,
int minCZ,
int maxCX,
int maxCY,
int maxCZ,
101 bool useSphere,
bool usePoint) {
103 std::unordered_set<int> seen;
104 for (
int z = minCZ;
z <= maxCZ; ++
z) {
105 for (
int y = minCY;
y <= maxCY; ++
y) {
106 for (
int x = minCX;
x <= maxCX; ++
x) {
108 if (it == cells_.end())
continue;
109 for (
int id : it->
second) {
110 if (!seen.insert(
id).second)
continue;
111 auto item = items_.find(
id);
112 if (item == items_.end())
continue;
113 const AABB3 &
b = item->second;
117 }
else if (useSphere) {
119 }
else if (usePoint) {
130 const int cx =
static_cast<int>(std::floor(
x / cellSize_));
131 const int cy =
static_cast<int>(std::floor(
y / cellSize_));
132 const int cz =
static_cast<int>(std::floor(
z / cellSize_));
133 queryCells(
cx,
cy, cz,
cx,
cy, cz,
nullptr,
x,
y,
z, 0.f,
false,
true);
140 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
141 cellRange(box, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
142 queryCells(minCX, minCY, minCZ, maxCX, maxCY, maxCZ, &box, 0.f, 0.f, 0.f, 0.f,
false,
false);
150 int minCX, minCY, minCZ, maxCX, maxCY, maxCZ;
151 cellRange(box, minCX, minCY, minCZ, maxCX, maxCY, maxCZ);
152 queryCells(minCX, minCY, minCZ, maxCX, maxCY, maxCZ,
nullptr,
cx,
cy, cz,
radius,
true,
false);
EVENGINE_API_FOUNDATION public API.
void clear()
Removes all stored entries.
void addUnchecked(int id)
Appends id without uniqueness checks.
int getCount() const
Number of stored ids.
void clear()
Removes all stored entries.
SpatialHash3D(float cellSize=64.f)
Creates a 3D spatial hash with the given cell size.
bool insert(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
Inserts an item AABB; false if out of bounds or id already present.
int querySphere(float cx, float cy, float cz, float radius)
Finds items overlapping a sphere; fills the result buffer.
void setCellSize(float cellSize)
Sets cell size and clears existing entries.
bool update(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
Moves an existing item to a new AABB; false if unknown or out of bounds.
bool contains(int id) const
True if the id is currently stored.
bool remove(int id)
Removes an item by id; false if unknown.
int queryAABB(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
Finds items overlapping an AABB; fills the result buffer.
int queryPoint(float x, float y, float z)
Finds items overlapping a point; fills the result buffer.
AABB3 makeAABB3(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
Builds a normalized 3D AABB (swaps inverted mins/maxes).
uint64_t cellKey3(int cx, int cy, int cz)
Packs 3D cell indices into a 63-bit hash key (21 bits/axis).
Axis-aligned 3D bounding box (min/max inclusive).
bool intersectsAABB(const AABB3 &o) const
True if the boxes overlap (inclusive edges).