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,
100 const AABB3 *box,
float cx,
float cy,
float cz,
float radius,
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) {
118 hit =
b.intersectsSphere(
cx,
cy, cz, radius);
119 }
else if (usePoint) {
120 hit =
b.containsPoint(
cx,
cy, cz);
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);
147 if (radius < 0.f) radius = 0.f;
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);
void addUnchecked(int id)
SpatialHash3D(float cellSize=64.f)
bool insert(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
int querySphere(float cx, float cy, float cz, float radius)
void setCellSize(float cellSize)
bool update(int id, float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
bool contains(int id) const
int queryAABB(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
int queryPoint(float x, float y, float z)
AABB3 makeAABB3(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
uint64_t cellKey3(int cx, int cy, int cz)
bool intersectsAABB(const AABB3 &o) const