Nebula
Loading...
Searching...
No Matches
occupancyquadtree.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
9//------------------------------------------------------------------------------
10#include "core/types.h"
11#include "math/scalar.h"
12#include "util/fixedarray.h"
14
15namespace Util
16{
17
19{
20public:
25
27 void Setup(uint textureSize, uint maxSize, uint minSize);
31 bool Deallocate(const Math::uint2 coord, uint size);
33 bool IsOccupied(const Math::uint2 coord, uint size);
35 void Clear();
36
37 struct Node
38 {
40 : topLeft(nullptr)
41 , topRight(nullptr)
42 , bottomLeft(nullptr)
43 , bottomRight(nullptr)
44 , occupied(false)
46 , size(1)
47 , x(UINT32_MAX)
48 , y(UINT32_MAX)
49 {
50 }
59 };
60
62
63private:
64
66 bool RecursiveAllocate(Node* node, uint size, Math::uint2& outCoord);
68 bool RecursiveDeallocate(Node* node, Math::uint2 coord, uint size);
70 bool RecursiveSearch(Node* node, Math::uint2 coord, uint size);
71
75};
76
77//------------------------------------------------------------------------------
80inline
85
86//------------------------------------------------------------------------------
89inline
94
95//------------------------------------------------------------------------------
98inline void
100{
101 this->minSize = minSize;
102 uint numNodes = textureSize / maxSize;
103 this->topLevelNodes.Resize(numNodes);
104 for (uint x = 0; x < numNodes; x++)
105 {
106 this->topLevelNodes[x].Resize(numNodes);
107 for (uint y = 0; y < numNodes; y++)
108 {
109 this->topLevelNodes[x][y].x = x * maxSize;
110 this->topLevelNodes[x][y].y = y * maxSize;
111 this->topLevelNodes[x][y].size = maxSize;
112 this->topLevelNodes[x][y].occupied = false;
113 this->topLevelNodes[x][y].occupancyCounter = 0;
114 this->topLevelNodes[x][y].topLeft = nullptr;
115 this->topLevelNodes[x][y].topRight = nullptr;
116 this->topLevelNodes[x][y].bottomLeft = nullptr;
117 this->topLevelNodes[x][y].bottomRight = nullptr;
118 }
119 }
120}
121
122//------------------------------------------------------------------------------
125inline bool
127{
128 // if the node is not occupied, proceed
129 if (!node->occupied)
130 {
131 // if size matches and no children are used, return
132 if (node->size == size && node->occupancyCounter == 0)
133 {
134 n_assert(node->occupied == false);
135 outCoord = Math::uint2{ node->x, node->y };
136 node->occupied = true;
137 return true;
138 }
139 else if (node->size > size && node->size != this->minSize)
140 {
141 // if the size of the node is bigger than the requested size, visit the children
142 if (node->topLeft == nullptr)
143 {
144 // initialize children, topleft is the origin point
145 const uint halfNodeSize = node->size / 2;
146 node->topLeft = this->allocator.Alloc<Node>();
147 node->topLeft->x = node->x;
148 node->topLeft->y = node->y;
149 node->topLeft->size = halfNodeSize;
150
151 node->topRight = this->allocator.Alloc<Node>();
152 node->topRight->x = node->x + halfNodeSize;
153 node->topRight->y = node->y;
154 node->topRight->size = halfNodeSize;
155
156 node->bottomLeft = this->allocator.Alloc<Node>();
157 node->bottomLeft->x = node->x;
158 node->bottomLeft->y = node->y + halfNodeSize;
159 node->bottomLeft->size = halfNodeSize;
160
161 node->bottomRight = this->allocator.Alloc<Node>();
162 node->bottomRight->x = node->x + halfNodeSize;
163 node->bottomRight->y = node->y + halfNodeSize;
164 node->bottomRight->size = halfNodeSize;
165 }
166
167 if (RecursiveAllocate(node->topLeft, size, outCoord))
168 {
169 node->occupancyCounter++;
170 return true;
171 }
172 if (RecursiveAllocate(node->topRight, size, outCoord))
173 {
174 node->occupancyCounter++;
175 return true;
176 }
177 if (RecursiveAllocate(node->bottomLeft, size, outCoord))
178 {
179 node->occupancyCounter++;
180 return true;
181 }
182 if (RecursiveAllocate(node->bottomRight, size, outCoord))
183 {
184 node->occupancyCounter++;
185 return true;
186 }
187 }
188 }
189
190 return false;
191}
192
193//------------------------------------------------------------------------------
196inline Math::uint2
198{
199 Math::uint2 ret{ UINT32_MAX, UINT32_MAX };
200 for (int x = 0; x < this->topLevelNodes.Size(); x++)
201 {
202 for (int y = 0; y < this->topLevelNodes[x].Size(); y++)
203 {
204 // try to allocate node in this subtree, if failed, just skip to the next top-level node
205 if (RecursiveAllocate(&this->topLevelNodes[x][y], size, ret))
206 return ret;
207 }
208 }
209 return ret;
210}
211
212//------------------------------------------------------------------------------
215inline bool
217{
218 // if node matches size, look for the coordinate
219 if (node->size == size)
220 {
221 if (node->x == coord.x && node->y == coord.y)
222 {
223 node->occupied = false;
224 return true;
225 }
226 }
227 else if (node->size > size)
228 {
229 // if node size is bigger than the requested size, visit children and unset the bits
230 if (node->topLeft == nullptr)
231 return false;
232
233 if (RecursiveDeallocate(node->topLeft, coord, size))
234 {
235 node->occupancyCounter--;
236 return true;
237 }
238 if (RecursiveDeallocate(node->topRight, coord, size))
239 {
240 node->occupancyCounter--;
241 return true;
242 }
243 if (RecursiveDeallocate(node->bottomLeft, coord, size))
244 {
245 node->occupancyCounter--;
246 return true;
247 }
248 if (RecursiveDeallocate(node->bottomRight, coord, size))
249 {
250 node->occupancyCounter--;
251 return true;
252 }
253 }
254
255 return false;
256}
257
258
259//------------------------------------------------------------------------------
262inline bool
264{
265 // find root node where the coord belongs
266 for (int x = 0; x < this->topLevelNodes.Size(); x++)
267 {
268 for (int y = 0; y < this->topLevelNodes[x].Size(); y++)
269 {
270 Node& node = this->topLevelNodes[x][y];
271 if (RecursiveDeallocate(&node, coord, size))
272 return true;
273 }
274 }
275 return false;
276}
277
278//------------------------------------------------------------------------------
281inline bool
283{
284 // if node matches size, look for the coordinate
285 if (node->size == size)
286 {
287 if (node->x == coord.x && node->y == coord.y)
288 {
289 return node->occupied;
290 }
291 }
292 else if (node->size > size)
293 {
294 // if node size is bigger than the requested size, visit children and unset the bits
295 if (node->topLeft == nullptr)
296 return false;
297
298 if (RecursiveDeallocate(node->topLeft, coord, size))
299 {
300 return true;
301 }
302 if (RecursiveDeallocate(node->topRight, coord, size))
303 {
304 return true;
305 }
306 if (RecursiveDeallocate(node->bottomLeft, coord, size))
307 {
308 return true;
309 }
310 if (RecursiveDeallocate(node->bottomRight, coord, size))
311 {
312 return true;
313 }
314 }
315
316 return false;
317}
318
319//------------------------------------------------------------------------------
322inline void
324{
325 this->allocator.Release();
326 for (uint x = 0; x < this->topLevelNodes.Size(); x++)
327 {
328 for (uint y = 0; y < this->topLevelNodes[x].Size(); y++)
329 {
330 this->topLevelNodes[x][y].topLeft = nullptr;
331 this->topLevelNodes[x][y].topRight = nullptr;
332 this->topLevelNodes[x][y].bottomLeft = nullptr;
333 this->topLevelNodes[x][y].bottomRight = nullptr;
334 this->topLevelNodes[x][y].occupied = false;
335 this->topLevelNodes[x][y].occupancyCounter = 0;
336 }
337 }
338}
339
340//------------------------------------------------------------------------------
343inline bool
345{
346 // find root node where the coord belongs
347 for (int x = 0; x < this->topLevelNodes.Size(); x++)
348 {
349 for (int y = 0; y < this->topLevelNodes[x].Size(); y++)
350 {
351 Node& node = this->topLevelNodes[x][y];
352 if (RecursiveSearch(&node, coord, size))
353 return true;
354 }
355 }
356 return false;
357}
358
359} // namespace Terrain
Allocates memory in chunks.
Definition arenaallocator.h:36
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
void Clear()
Clear the tree.
Definition occupancyquadtree.h:323
Memory::ArenaAllocator< sizeof(Node) *64 > allocator
Definition occupancyquadtree.h:72
Util::FixedArray< Util::FixedArray< Node > > topLevelNodes
Definition occupancyquadtree.h:73
uint minSize
Definition occupancyquadtree.h:74
bool RecursiveDeallocate(Node *node, Math::uint2 coord, uint size)
recursively traverse tree and deallocate
Definition occupancyquadtree.h:216
bool IsOccupied(const Math::uint2 coord, uint size)
check if region is alloced
Definition occupancyquadtree.h:344
bool RecursiveSearch(Node *node, Math::uint2 coord, uint size)
recursively traverse tree and find if allocated
Definition occupancyquadtree.h:282
OccupancyQuadTree()
constructor
Definition occupancyquadtree.h:81
bool RecursiveAllocate(Node *node, uint size, Math::uint2 &outCoord)
recursively traverse tree to allocate node from tree
Definition occupancyquadtree.h:126
void Setup(uint textureSize, uint maxSize, uint minSize)
setup with a world size and a biggest allocation size
Definition occupancyquadtree.h:99
Math::uint2 Allocate(uint size)
allocate a region, return region
Definition occupancyquadtree.h:197
bool Deallocate(const Math::uint2 coord, uint size)
deallocate region
Definition occupancyquadtree.h:263
const Util::FixedArray< Util::FixedArray< Node > > & GetTopLevelNodes()
~OccupancyQuadTree()
destructor
Definition occupancyquadtree.h:90
#define n_assert(exp)
Definition debug.h:50
A quad tree designed to return regions of free 2D space.
Definition String.cs:6
Nebula's scalar datatype.
Definition scalar.h:112
unsigned int x
Definition scalar.h:115
unsigned int y
Definition scalar.h:115
Definition occupancyquadtree.h:38
uint occupancyCounter
Definition occupancyquadtree.h:56
uint y
Definition occupancyquadtree.h:58
Node * bottomRight
Definition occupancyquadtree.h:54
uint size
Definition occupancyquadtree.h:57
Node * topLeft
Definition occupancyquadtree.h:51
Node * topRight
Definition occupancyquadtree.h:52
Node()
Definition occupancyquadtree.h:39
Node * bottomLeft
Definition occupancyquadtree.h:53
bool occupied
Definition occupancyquadtree.h:55
uint x
Definition occupancyquadtree.h:58
unsigned int uint
Definition types.h:33