Nebula
Loading...
Searching...
No Matches
quadtree.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
14#include "util/fixedarray.h"
15#include "math/bbox.h"
16#include "math/vec4.h"
17
18namespace Util
19{
20//------------------------------------------------------------------------------
21template<class TYPE> class QuadTree
22{
23public:
24 class Node;
25
27 QuadTree();
29 ~QuadTree();
31 void Setup(const Math::bbox& box, uchar depth);
33 const Math::bbox& GetBoundingBox() const;
35 uchar GetDepth() const;
37 SizeT GetNumNodes(uchar level) const;
39 IndexT GetNodeIndex(uchar level, ushort col, ushort row) const;
43 const Node& GetNodeByIndex(IndexT i) const;
48
50 class Node
51 {
52 public:
54 Node();
56 ~Node();
58 void Setup(QuadTree<TYPE>* tree, uchar _level, ushort _col, ushort _row);
60 char Level() const;
62 ushort Column() const;
64 ushort Row() const;
66 const Math::bbox& GetBoundingBox() const;
70 void SetElement(const TYPE& elm);
72 const TYPE& GetElement() const;
75
76 private:
77 friend class QuadTree;
78
80 char level;
84 TYPE element;
85 };
86
87private:
88 friend class Node;
89
91 Math::bbox boundingBox; // global bounding box
92 Math::vector baseNodeSize; // base chunk bounding box
94};
95
96//------------------------------------------------------------------------------
100template<class TYPE>
102 treeDepth(0),
103 baseNodeSize(0.0f, 0.0f, 0.0f)
104{
105 // empty
106}
107
108//------------------------------------------------------------------------------
112template<class TYPE>
114{
115 // empty
116}
117
118
119
120//------------------------------------------------------------------------------
124template<class TYPE> void
126{
127 #if NEBULA_BOUNDSCHECKS
128 n_assert(depth > 0);
129 #endif
130
131 this->treeDepth = depth;
132 this->boundingBox = box;
133
134 int baseDimension = 1 << (this->treeDepth - 1);
135 this->baseNodeSize.set(this->boundingBox.size().x / baseDimension,
136 this->boundingBox.size().y,
137 this->boundingBox.size().z / baseDimension);
138
139 SizeT numNodes = this->GetNumNodes(this->treeDepth);
140 this->nodeArray.SetSize(numNodes);
141 this->nodeArray[0].Setup(this, 0, 0, 0);
142
143 // make sure all nodes have been initialized
144 #if NEBULA_BOUNDSCHECKS
145 int i;
146 int num = this->nodeArray.Size();
147 for (i = 0; i < num; i++)
148 {
149 n_assert(this->nodeArray[i].Level() >= 0);
150 }
151 #endif
152}
153
154//------------------------------------------------------------------------------
158template<class TYPE> uchar
160{
161 return this->treeDepth;
162}
163
164//------------------------------------------------------------------------------
168template<class TYPE> const Math::bbox&
170{
171 return this->boundingBox;
172}
173
174//------------------------------------------------------------------------------
178template<class TYPE> SizeT
180{
181 //FIXME WTF
182 return 0x55555555 & ((1 << level * 2) - 1);
183}
184
185//------------------------------------------------------------------------------
189template<class TYPE> SizeT
191{
192 return this->nodeArray.Size();
193}
194
195//------------------------------------------------------------------------------
200template<class TYPE> IndexT
202{
203 #if NEBULA_BOUNDSCHECKS
204 n_assert((col >= 0) && (col < (1 << level)));
205 n_assert((row >= 0) && (row < (1 << level)));
206 #endif
207 return this->GetNumNodes(level) + (row << level) + col;
208}
209
210//------------------------------------------------------------------------------
215template<class TYPE> typename QuadTree<TYPE>::Node*
217{
218 return this->nodeArray[0].FindContainmentNode(checkBox);
219}
220
221//------------------------------------------------------------------------------
224template<class TYPE>
226 level(-1),
227 col(0),
228 row(0)
229{
230 int i;
231 for (i = 0; i < 4; i++)
232 {
233 this->children[i] = 0;
234 }
235}
236
237//------------------------------------------------------------------------------
240template<class TYPE>
242{
243 // empty
244}
245
246//------------------------------------------------------------------------------
250template<class TYPE> void
252{
253 #if NEBULA_BOUNDSCHECKS
254 n_assert(tree);
255 n_assert(this->level == -1);
256 n_assert(_col < (1 << _level));
257 n_assert(_row < (1 << _level));
258 #endif
259
260 // store address
261 this->level = _level;
262 this->col = _col;
263 this->row = _row;
264
265 // update my bounding box
266 float levelFactor = float(1 << (tree->treeDepth - 1 - this->level));
267 static Math::vector center;
268 static Math::vector extent;
269 const Math::vector& baseSize = tree->baseNodeSize;
270 const Math::bbox& treeBox = tree->boundingBox;
271 Math::vector treeSize = treeBox.size();
272 Math::vector treeCenter = treeBox.center();
273
274 center.set(treeCenter.x + (((this->col + 0.5f) * levelFactor * baseSize.x) - (treeSize.x * 0.5f)),
275 treeCenter.y,
276 treeCenter.z + (((this->row + 0.5f) * levelFactor * baseSize.z) - (treeSize.z * 0.5f)));
277
278 extent.set(levelFactor * baseSize.x * 0.5f,
279 treeBox.extents().y,
280 levelFactor * baseSize.z * 0.5f );
281
282 this->box.set(center, extent);
283
284 // recurse into children
285 uchar childLevel = this->level + 1;
286 if (childLevel < tree->treeDepth)
287 {
288 ushort i;
289 for (i = 0; i < 4; i++)
290 {
291 ushort childCol = 2 * this->col + (i & 1);
292 ushort childRow = 2 * this->row + ((i & 2) >> 1);
293 IndexT childIndex = tree->GetNodeIndex(childLevel, childCol, childRow);
294 this->children[i] = &(tree->nodeArray[childIndex]);
295 this->children[i]->Setup(tree, childLevel, childCol, childRow);
296 }
297 }
298}
299
300//------------------------------------------------------------------------------
305template<class TYPE> typename QuadTree<TYPE>::Node*
307{
308 if (this->box.contains(checkBox))
309 {
310 // recurse into children
311 if (this->children[0] != 0)
312 {
313 int i;
314 for (i = 0; i < 4; i++)
315 {
316 Node* containNode = this->children[i]->FindContainmentNode(checkBox);
317 if (containNode)
318 {
319 return containNode;
320 }
321 }
322 }
323
324 // not contained in children, but still contained in this
325 return this;
326 }
327 else
328 {
329 // not contained in this, break recursion
330 return 0;
331 }
332}
333
334//------------------------------------------------------------------------------
337template<class TYPE> const typename QuadTree<TYPE>::Node&
339{
340 return this->nodeArray[index];
341}
342
343//------------------------------------------------------------------------------
346template<class TYPE> typename QuadTree<TYPE>::Node&
348{
349 return this->nodeArray[index];
350}
351
352//------------------------------------------------------------------------------
355template<class TYPE> const Math::bbox&
357{
358 return this->box;
359}
360
361//------------------------------------------------------------------------------
364template<class TYPE> char
366{
367 return this->level;
368}
369
370//------------------------------------------------------------------------------
373template<class TYPE> ushort
375{
376 return this->col;
377}
378
379//------------------------------------------------------------------------------
382template<class TYPE> ushort
384{
385 return this->row;
386}
387
388//------------------------------------------------------------------------------
391template<class TYPE> void
393{
394 this->element = elm;
395}
396
397//------------------------------------------------------------------------------
400template<class TYPE> const TYPE&
402{
403 return this->element;
404}
405
406//------------------------------------------------------------------------------
409template<class TYPE> typename QuadTree<TYPE>::Node*
411{
412 return this->children[i];
413}
414} // namespace Util
415//------------------------------------------------------------------------------
Nebula's bounding box class.
Definition bbox.h:24
vec3 size() const
get size of box
Definition bbox.h:164
vector extents() const
get extents of box
Definition bbox.h:155
point center() const
get center of box
Definition bbox.h:146
void set(const mat4 &m)
set from mat4
Definition bbox.h:124
Implements a fixed size one-dimensional array.
Definition fixedarray.h:20
node in quad tree
Definition quadtree.h:51
Node * children[4]
Definition quadtree.h:79
void SetElement(const TYPE &elm)
set data element associated with node
Definition quadtree.h:392
TYPE element
Definition quadtree.h:84
Node()
constructor
Definition quadtree.h:225
ushort Column() const
get the node's column
Definition quadtree.h:374
ushort row
Definition quadtree.h:82
const TYPE & GetElement() const
get data element
Definition quadtree.h:401
Math::bbox box
Definition quadtree.h:83
ushort col
Definition quadtree.h:81
ushort Row() const
get the node's row
Definition quadtree.h:383
char level
Definition quadtree.h:80
Node * GetChildAt(IndexT i)
get child at index
Definition quadtree.h:410
~Node()
destructor
Definition quadtree.h:241
Node * FindContainmentNode(const Math::bbox &box)
recursively find the smallest child node which contains the bounding box
Definition quadtree.h:306
const Math::bbox & GetBoundingBox() const
compute the node's bounding box
Definition quadtree.h:356
char Level() const
get the node's level
Definition quadtree.h:365
void Setup(QuadTree< TYPE > *tree, uchar _level, ushort _col, ushort _row)
recursively initialize the node
Definition quadtree.h:251
Definition quadtree.h:22
Node * FindContainmentNode(const Math::bbox &box)
recursively find the smallest child node which contains the bounding box
Definition quadtree.h:216
Math::bbox boundingBox
Definition quadtree.h:91
Util::FixedArray< Node > nodeArray
Definition quadtree.h:93
SizeT GetNumNodes(uchar level) const
compute number of nodes in a level, including its children
Definition quadtree.h:179
SizeT GetNumNodesInTree() const
get overall number of nodes in the tree
Definition quadtree.h:190
uchar GetDepth() const
get the tree depth
Definition quadtree.h:159
uchar treeDepth
Definition quadtree.h:90
const Math::bbox & GetBoundingBox() const
get the top level bounding box
Definition quadtree.h:169
QuadTree()
constructor
Definition quadtree.h:101
~QuadTree()
destructor
Definition quadtree.h:113
Node & NodeByIndex(IndexT i)
read/write access to node
Definition quadtree.h:347
Math::vector baseNodeSize
Definition quadtree.h:92
const Node & GetNodeByIndex(IndexT i) const
get pointer to node by index
Definition quadtree.h:338
void Setup(const Math::bbox &box, uchar depth)
initialize quad tree
Definition quadtree.h:125
IndexT GetNodeIndex(uchar level, ushort col, ushort row) const
compute linear chunk index from level, col and row
Definition quadtree.h:201
#define n_assert(exp)
Definition debug.h:50
A pinned array is an array which manages its own virtual memory.
Definition String.cs:6
A vector is a 3D direction in space.
Definition vector.h:22
float z
Definition vector.h:85
float x
Definition vector.h:85
float y
Definition vector.h:85
void set(scalar x, scalar y, scalar z)
set content
Definition vector.h:353
unsigned char uchar
Definition types.h:33
int SizeT
Definition types.h:49
unsigned short ushort
Definition types.h:32
int IndexT
Definition types.h:48