diff options
author | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:34 -0500 |
commit | cd17687f01420952712a500107e0f93e7ab8d5f8 (patch) | |
tree | ce48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/llmath/lloctree.h | |
parent | Second Life viewer sources 1.19.0.5 (diff) | |
download | meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2 meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz |
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/llmath/lloctree.h')
-rw-r--r-- | linden/indra/llmath/lloctree.h | 382 |
1 files changed, 176 insertions, 206 deletions
diff --git a/linden/indra/llmath/lloctree.h b/linden/indra/llmath/lloctree.h index 6eee9fb..203cb41 100644 --- a/linden/indra/llmath/lloctree.h +++ b/linden/indra/llmath/lloctree.h | |||
@@ -47,10 +47,9 @@ | |||
47 | #if LL_DARWIN | 47 | #if LL_DARWIN |
48 | #define LL_OCTREE_MAX_CAPACITY 32 | 48 | #define LL_OCTREE_MAX_CAPACITY 32 |
49 | #else | 49 | #else |
50 | #define LL_OCTREE_MAX_CAPACITY 256 | 50 | #define LL_OCTREE_MAX_CAPACITY 128 |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | template <class T> class LLOctreeState; | ||
54 | template <class T> class LLOctreeNode; | 53 | template <class T> class LLOctreeNode; |
55 | 54 | ||
56 | template <class T> | 55 | template <class T> |
@@ -64,15 +63,27 @@ public: | |||
64 | virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0; | 63 | virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0; |
65 | }; | 64 | }; |
66 | 65 | ||
66 | template <class T> | ||
67 | class LLOctreeTraveler : public LLTreeTraveler<T> | ||
68 | { | ||
69 | public: | ||
70 | virtual void traverse(const LLTreeNode<T>* node); | ||
71 | virtual void visit(const LLTreeNode<T>* state) { } | ||
72 | virtual void visit(const LLOctreeNode<T>* branch) = 0; | ||
73 | }; | ||
67 | 74 | ||
68 | template <class T> | 75 | template <class T> |
69 | class LLOctreeNode : public LLTreeNode<T> | 76 | class LLOctreeNode : public LLTreeNode<T> |
70 | { | 77 | { |
71 | public: | 78 | public: |
72 | 79 | typedef LLOctreeTraveler<T> oct_traveler; | |
80 | typedef LLTreeTraveler<T> tree_traveler; | ||
81 | typedef typename std::set<LLPointer<T> > element_list; | ||
82 | typedef typename std::set<LLPointer<T> >::iterator element_iter; | ||
83 | typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter; | ||
84 | typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; | ||
85 | typedef typename std::vector<LLOctreeNode<T>* > child_list; | ||
73 | typedef LLTreeNode<T> BaseType; | 86 | typedef LLTreeNode<T> BaseType; |
74 | typedef LLTreeState<T> tree_state; | ||
75 | typedef LLOctreeState<T> oct_state; | ||
76 | typedef LLOctreeNode<T> oct_node; | 87 | typedef LLOctreeNode<T> oct_node; |
77 | typedef LLOctreeListener<T> oct_listener; | 88 | typedef LLOctreeListener<T> oct_listener; |
78 | 89 | ||
@@ -82,11 +93,9 @@ public: | |||
82 | 93 | ||
83 | LLOctreeNode( LLVector3d center, | 94 | LLOctreeNode( LLVector3d center, |
84 | LLVector3d size, | 95 | LLVector3d size, |
85 | tree_state* state, | ||
86 | BaseType* parent, | 96 | BaseType* parent, |
87 | U8 octant = 255) | 97 | U8 octant = 255) |
88 | : BaseType(state), | 98 | : mParent((oct_node*)parent), |
89 | mParent((oct_node*)parent), | ||
90 | mCenter(center), | 99 | mCenter(center), |
91 | mSize(size), | 100 | mSize(size), |
92 | mOctant(octant) | 101 | mOctant(octant) |
@@ -96,9 +105,19 @@ public: | |||
96 | { | 105 | { |
97 | mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV); | 106 | mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV); |
98 | } | 107 | } |
108 | |||
109 | clearChildren(); | ||
99 | } | 110 | } |
100 | 111 | ||
101 | ~LLOctreeNode() { BaseType::destroyListeners(); delete this->mState; } | 112 | virtual ~LLOctreeNode() |
113 | { | ||
114 | BaseType::destroyListeners(); | ||
115 | |||
116 | for (U32 i = 0; i < getChildCount(); i++) | ||
117 | { | ||
118 | delete getChild(i); | ||
119 | } | ||
120 | } | ||
102 | 121 | ||
103 | inline const BaseType* getParent() const { return mParent; } | 122 | inline const BaseType* getParent() const { return mParent; } |
104 | inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } | 123 | inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } |
@@ -106,25 +125,12 @@ public: | |||
106 | inline const LLVector3d& getSize() const { return mSize; } | 125 | inline const LLVector3d& getSize() const { return mSize; } |
107 | inline void setCenter(LLVector3d center) { mCenter = center; } | 126 | inline void setCenter(LLVector3d center) { mCenter = center; } |
108 | inline void setSize(LLVector3d size) { mSize = size; } | 127 | inline void setSize(LLVector3d size) { mSize = size; } |
109 | inline bool balance() { return getOctState()->balance(); } | 128 | inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } |
110 | inline void validate() { getOctState()->validate(); } | ||
111 | inline U32 getChildCount() const { return getOctState()->getChildCount(); } | ||
112 | inline oct_node* getChild(U32 index) { return getOctState()->getChild(index); } | ||
113 | inline const oct_node* getChild(U32 index) const { return getOctState()->getChild(index); } | ||
114 | inline U32 getElementCount() const { return getOctState()->getElementCount(); } | ||
115 | inline void removeByAddress(T* data) { getOctState()->removeByAddress(data); } | ||
116 | inline bool hasLeafState() const { return getOctState()->isLeaf(); } | ||
117 | inline void destroy() { getOctState()->destroy(); } | ||
118 | inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } | ||
119 | inline oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) { return getOctState()->getNodeAt(pos, rad); } | ||
120 | inline U8 getOctant() const { return mOctant; } | 129 | inline U8 getOctant() const { return mOctant; } |
121 | inline void setOctant(U8 octant) { mOctant = octant; } | 130 | inline void setOctant(U8 octant) { mOctant = octant; } |
122 | inline const oct_state* getOctState() const { return (const oct_state*) BaseType::mState; } | ||
123 | inline oct_state* getOctState() { return (oct_state*) BaseType::mState; } | ||
124 | inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } | 131 | inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } |
125 | inline oct_node* getOctParent() { return (oct_node*) getParent(); } | 132 | inline oct_node* getOctParent() { return (oct_node*) getParent(); } |
126 | inline void deleteChild(oct_node* child) { getOctState()->deleteChild(child); } | 133 | |
127 | |||
128 | U8 getOctant(const F64 pos[]) const //get the octant pos is in | 134 | U8 getOctant(const F64 pos[]) const //get the octant pos is in |
129 | { | 135 | { |
130 | U8 ret = 0; | 136 | U8 ret = 0; |
@@ -205,9 +211,9 @@ public: | |||
205 | (radius <= p_size && radius > size); | 211 | (radius <= p_size && radius > size); |
206 | } | 212 | } |
207 | 213 | ||
208 | static void pushCenter(LLVector3d ¢er, LLVector3d &size, T* data) | 214 | static void pushCenter(LLVector3d ¢er, const LLVector3d &size, const T* data) |
209 | { | 215 | { |
210 | LLVector3d pos(data->getPositionGroup()); | 216 | const LLVector3d& pos = data->getPositionGroup(); |
211 | for (U32 i = 0; i < 3; i++) | 217 | for (U32 i = 0; i < 3; i++) |
212 | { | 218 | { |
213 | if (pos.mdV[i] > center.mdV[i]) | 219 | if (pos.mdV[i] > center.mdV[i]) |
@@ -221,76 +227,25 @@ public: | |||
221 | } | 227 | } |
222 | } | 228 | } |
223 | 229 | ||
224 | protected: | 230 | void accept(oct_traveler* visitor) { visitor->visit(this); } |
225 | oct_node* mParent; | 231 | virtual bool isLeaf() const { return mChild.empty(); } |
226 | LLVector3d mCenter; | ||
227 | LLVector3d mSize; | ||
228 | LLVector3d mMax; | ||
229 | LLVector3d mMin; | ||
230 | U8 mOctant; | ||
231 | }; | ||
232 | |||
233 | template <class T> | ||
234 | class LLOctreeTraveler : public LLTreeTraveler<T> | ||
235 | { | ||
236 | public: | ||
237 | virtual void traverse(const LLTreeNode<T>* node); | ||
238 | virtual void visit(const LLTreeState<T>* state) { } | ||
239 | virtual void visit(const LLOctreeState<T>* branch) = 0; | ||
240 | }; | ||
241 | |||
242 | //will pass requests to a child, might make a new child | ||
243 | template <class T> | ||
244 | class LLOctreeState : public LLTreeState<T> | ||
245 | { | ||
246 | public: | ||
247 | typedef LLTreeState<T> BaseType; | ||
248 | typedef LLOctreeTraveler<T> oct_traveler; | ||
249 | typedef LLOctreeNode<T> oct_node; | ||
250 | typedef LLOctreeListener<T> oct_listener; | ||
251 | typedef LLTreeTraveler<T> tree_traveler; | ||
252 | typedef typename std::set<LLPointer<T> > element_list; | ||
253 | typedef typename std::set<LLPointer<T> >::iterator element_iter; | ||
254 | typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter; | ||
255 | typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter; | ||
256 | typedef typename std::vector<LLOctreeNode<T>* > child_list; | ||
257 | 232 | ||
258 | LLOctreeState(oct_node* node = NULL): BaseType(node) { this->clearChildren(); } | 233 | U32 getElementCount() const { return mData.size(); } |
259 | virtual ~LLOctreeState() | 234 | element_list& getData() { return mData; } |
260 | { | 235 | const element_list& getData() const { return mData; } |
261 | for (U32 i = 0; i < getChildCount(); i++) | ||
262 | { | ||
263 | delete getChild(i); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | 236 | ||
268 | virtual void accept(oct_traveler* visitor) { visitor->visit(this); } | 237 | U32 getChildCount() const { return mChild.size(); } |
269 | virtual bool isLeaf() const { return mChild.empty(); } | 238 | oct_node* getChild(U32 index) { return mChild[index]; } |
239 | const oct_node* getChild(U32 index) const { return mChild[index]; } | ||
240 | child_list& getChildren() { return mChild; } | ||
241 | const child_list& getChildren() const { return mChild; } | ||
270 | 242 | ||
271 | virtual U32 getElementCount() const { return mData.size(); } | 243 | void accept(tree_traveler* visitor) const { visitor->visit(this); } |
272 | virtual element_list& getData() { return mData; } | 244 | void accept(oct_traveler* visitor) const { visitor->visit(this); } |
273 | virtual const element_list& getData() const { return mData; } | ||
274 | 245 | ||
275 | virtual U32 getChildCount() const { return mChild.size(); } | 246 | oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) |
276 | virtual oct_node* getChild(U32 index) { return mChild[index]; } | ||
277 | virtual const oct_node* getChild(U32 index) const { return mChild[index]; } | ||
278 | virtual child_list& getChildren() { return mChild; } | ||
279 | virtual const child_list& getChildren() const { return mChild; } | ||
280 | |||
281 | virtual void accept(tree_traveler* visitor) const { visitor->visit(this); } | ||
282 | virtual void accept(oct_traveler* visitor) const { visitor->visit(this); } | ||
283 | const oct_node* getOctNode() const { return (const oct_node*) BaseType::getNode(); } | ||
284 | oct_node* getOctNode() { return (oct_node*) BaseType::getNode(); } | ||
285 | |||
286 | virtual oct_node* getNodeAt(T* data) | ||
287 | { | ||
288 | return getNodeAt(data->getPositionGroup(), data->getBinRadius()); | ||
289 | } | ||
290 | |||
291 | virtual oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) | ||
292 | { | 247 | { |
293 | LLOctreeNode<T>* node = getOctNode(); | 248 | LLOctreeNode<T>* node = this; |
294 | 249 | ||
295 | if (node->isInside(pos, rad)) | 250 | if (node->isInside(pos, rad)) |
296 | { | 251 | { |
@@ -328,26 +283,19 @@ public: | |||
328 | { | 283 | { |
329 | if (data == NULL) | 284 | if (data == NULL) |
330 | { | 285 | { |
331 | OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; | 286 | //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; |
332 | return false; | 287 | return false; |
333 | } | 288 | } |
334 | LLOctreeNode<T>* node = getOctNode(); | 289 | LLOctreeNode<T>* parent = getOctParent(); |
335 | LLOctreeNode<T>* parent = node->getOctParent(); | ||
336 | 290 | ||
337 | //is it here? | 291 | //is it here? |
338 | if (node->isInside(data->getPositionGroup())) | 292 | if (isInside(data->getPositionGroup())) |
339 | { | 293 | { |
340 | if (getElementCount() < LL_OCTREE_MAX_CAPACITY && | 294 | if (getElementCount() < LL_OCTREE_MAX_CAPACITY && |
341 | (node->contains(data->getBinRadius()) || | 295 | (contains(data->getBinRadius()) || |
342 | (data->getBinRadius() > node->getSize().mdV[0] && | 296 | (data->getBinRadius() > getSize().mdV[0] && |
343 | parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) | 297 | parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) |
344 | { //it belongs here | 298 | { //it belongs here |
345 | if (data == NULL) | ||
346 | { | ||
347 | OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE LEAF !!!" << llendl; | ||
348 | return false; | ||
349 | } | ||
350 | |||
351 | #if LL_OCTREE_PARANOIA_CHECK | 299 | #if LL_OCTREE_PARANOIA_CHECK |
352 | //if this is a redundant insertion, error out (should never happen) | 300 | //if this is a redundant insertion, error out (should never happen) |
353 | if (mData.find(data) != mData.end()) | 301 | if (mData.find(data) != mData.end()) |
@@ -358,6 +306,7 @@ public: | |||
358 | #endif | 306 | #endif |
359 | 307 | ||
360 | mData.insert(data); | 308 | mData.insert(data); |
309 | BaseType::insert(data); | ||
361 | return true; | 310 | return true; |
362 | } | 311 | } |
363 | else | 312 | else |
@@ -375,8 +324,8 @@ public: | |||
375 | } | 324 | } |
376 | 325 | ||
377 | //it's here, but no kids are in the right place, make a new kid | 326 | //it's here, but no kids are in the right place, make a new kid |
378 | LLVector3d center(node->getCenter()); | 327 | LLVector3d center(getCenter()); |
379 | LLVector3d size(node->getSize()*0.5); | 328 | LLVector3d size(getSize()*0.5); |
380 | 329 | ||
381 | //push center in direction of data | 330 | //push center in direction of data |
382 | LLOctreeNode<T>::pushCenter(center, size, data); | 331 | LLOctreeNode<T>::pushCenter(center, size, data); |
@@ -386,7 +335,6 @@ public: | |||
386 | { | 335 | { |
387 | //this really isn't possible, something bad has happened | 336 | //this really isn't possible, something bad has happened |
388 | OCT_ERRS << "Octree detected floating point error and gave up." << llendl; | 337 | OCT_ERRS << "Octree detected floating point error and gave up." << llendl; |
389 | //bool check = node->isInside(data); | ||
390 | return false; | 338 | return false; |
391 | } | 339 | } |
392 | 340 | ||
@@ -396,25 +344,25 @@ public: | |||
396 | if (mChild[i]->getCenter() == center) | 344 | if (mChild[i]->getCenter() == center) |
397 | { | 345 | { |
398 | OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl; | 346 | OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl; |
399 | //bool check = node->isInside(data); | ||
400 | //check = getChild(i)->isInside(data); | ||
401 | return false; | 347 | return false; |
402 | } | 348 | } |
403 | } | 349 | } |
404 | #endif | 350 | #endif |
405 | 351 | ||
406 | //make the new kid | 352 | //make the new kid |
407 | LLOctreeState<T>* newstate = new LLOctreeState<T>(); | 353 | child = new LLOctreeNode<T>(center, size, this); |
408 | child = new LLOctreeNode<T>(center, size, newstate, node); | ||
409 | addChild(child); | 354 | addChild(child); |
410 | 355 | ||
411 | child->insert(data); | 356 | child->insert(data); |
412 | } | 357 | } |
413 | } | 358 | } |
414 | else | 359 | else |
415 | { | 360 | { |
416 | //it's not in here, give it to the root | 361 | //it's not in here, give it to the root |
417 | LLOctreeNode<T>* parent = node->getOctParent(); | 362 | //OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl; |
363 | |||
364 | oct_node* node = this; | ||
365 | |||
418 | while (parent) | 366 | while (parent) |
419 | { | 367 | { |
420 | node = parent; | 368 | node = parent; |
@@ -427,22 +375,20 @@ public: | |||
427 | return false; | 375 | return false; |
428 | } | 376 | } |
429 | 377 | ||
430 | virtual bool remove(T* data) | 378 | bool remove(T* data) |
431 | { | 379 | { |
432 | oct_node* node = getOctNode(); | ||
433 | |||
434 | if (mData.find(data) != mData.end()) | 380 | if (mData.find(data) != mData.end()) |
435 | { //we have data | 381 | { //we have data |
436 | mData.erase(data); | 382 | mData.erase(data); |
437 | node->notifyRemoval(data); | 383 | notifyRemoval(data); |
438 | checkAlive(); | 384 | checkAlive(); |
439 | return true; | 385 | return true; |
440 | } | 386 | } |
441 | else if (node->isInside(data)) | 387 | else if (isInside(data)) |
442 | { | 388 | { |
443 | oct_node* dest = getNodeAt(data); | 389 | oct_node* dest = getNodeAt(data); |
444 | 390 | ||
445 | if (dest != node) | 391 | if (dest != this) |
446 | { | 392 | { |
447 | return dest->remove(data); | 393 | return dest->remove(data); |
448 | } | 394 | } |
@@ -451,7 +397,9 @@ public: | |||
451 | //SHE'S GONE MISSING... | 397 | //SHE'S GONE MISSING... |
452 | //none of the children have it, let's just brute force this bastard out | 398 | //none of the children have it, let's just brute force this bastard out |
453 | //starting with the root node (UGLY CODE COMETH!) | 399 | //starting with the root node (UGLY CODE COMETH!) |
454 | oct_node* parent = node->getOctParent(); | 400 | oct_node* parent = getOctParent(); |
401 | oct_node* node = this; | ||
402 | |||
455 | while (parent != NULL) | 403 | while (parent != NULL) |
456 | { | 404 | { |
457 | node = parent; | 405 | node = parent; |
@@ -464,12 +412,12 @@ public: | |||
464 | return true; | 412 | return true; |
465 | } | 413 | } |
466 | 414 | ||
467 | virtual void removeByAddress(T* data) | 415 | void removeByAddress(T* data) |
468 | { | 416 | { |
469 | if (mData.find(data) != mData.end()) | 417 | if (mData.find(data) != mData.end()) |
470 | { | 418 | { |
471 | mData.erase(data); | 419 | mData.erase(data); |
472 | getOctNode()->notifyRemoval(data); | 420 | notifyRemoval(data); |
473 | llwarns << "FOUND!" << llendl; | 421 | llwarns << "FOUND!" << llendl; |
474 | checkAlive(); | 422 | checkAlive(); |
475 | return; | 423 | return; |
@@ -482,20 +430,18 @@ public: | |||
482 | } | 430 | } |
483 | } | 431 | } |
484 | 432 | ||
485 | virtual void clearChildren() | 433 | void clearChildren() |
486 | { | 434 | { |
487 | mChild.clear(); | 435 | mChild.clear(); |
488 | } | 436 | } |
489 | 437 | ||
490 | virtual void validate() | 438 | void validate() |
491 | { | 439 | { |
492 | #if LL_OCTREE_PARANOIA_CHECK | 440 | #if LL_OCTREE_PARANOIA_CHECK |
493 | LLOctreeNode<T>* node = this->getOctNode(); | ||
494 | |||
495 | for (U32 i = 0; i < getChildCount(); i++) | 441 | for (U32 i = 0; i < getChildCount(); i++) |
496 | { | 442 | { |
497 | mChild[i]->validate(); | 443 | mChild[i]->validate(); |
498 | if (mChild[i]->getParent() != node) | 444 | if (mChild[i]->getParent() != this) |
499 | { | 445 | { |
500 | llerrs << "Octree child has invalid parent." << llendl; | 446 | llerrs << "Octree child has invalid parent." << llendl; |
501 | } | 447 | } |
@@ -508,7 +454,7 @@ public: | |||
508 | return false; | 454 | return false; |
509 | } | 455 | } |
510 | 456 | ||
511 | virtual void destroy() | 457 | void destroy() |
512 | { | 458 | { |
513 | for (U32 i = 0; i < getChildCount(); i++) | 459 | for (U32 i = 0; i < getChildCount(); i++) |
514 | { | 460 | { |
@@ -517,7 +463,7 @@ public: | |||
517 | } | 463 | } |
518 | } | 464 | } |
519 | 465 | ||
520 | virtual void addChild(oct_node* child, BOOL silent = FALSE) | 466 | void addChild(oct_node* child, BOOL silent = FALSE) |
521 | { | 467 | { |
522 | #if LL_OCTREE_PARANOIA_CHECK | 468 | #if LL_OCTREE_PARANOIA_CHECK |
523 | for (U32 i = 0; i < getChildCount(); i++) | 469 | for (U32 i = 0; i < getChildCount(); i++) |
@@ -539,27 +485,24 @@ public: | |||
539 | #endif | 485 | #endif |
540 | 486 | ||
541 | mChild.push_back(child); | 487 | mChild.push_back(child); |
542 | child->setParent(getOctNode()); | 488 | child->setParent(this); |
543 | 489 | ||
544 | if (!silent) | 490 | if (!silent) |
545 | { | 491 | { |
546 | oct_node* node = getOctNode(); | 492 | for (U32 i = 0; i < this->getListenerCount(); i++) |
547 | |||
548 | for (U32 i = 0; i < node->getListenerCount(); i++) | ||
549 | { | 493 | { |
550 | oct_listener* listener = node->getOctListener(i); | 494 | oct_listener* listener = getOctListener(i); |
551 | listener->handleChildAddition(node, child); | 495 | listener->handleChildAddition(this, child); |
552 | } | 496 | } |
553 | } | 497 | } |
554 | } | 498 | } |
555 | 499 | ||
556 | virtual void removeChild(U8 index, BOOL destroy = FALSE) | 500 | void removeChild(U8 index, BOOL destroy = FALSE) |
557 | { | 501 | { |
558 | oct_node* node = getOctNode(); | 502 | for (U32 i = 0; i < this->getListenerCount(); i++) |
559 | for (U32 i = 0; i < node->getListenerCount(); i++) | ||
560 | { | 503 | { |
561 | oct_listener* listener = node->getOctListener(i); | 504 | oct_listener* listener = getOctListener(i); |
562 | listener->handleChildRemoval(node, getChild(index)); | 505 | listener->handleChildRemoval(this, getChild(index)); |
563 | } | 506 | } |
564 | 507 | ||
565 | if (destroy) | 508 | if (destroy) |
@@ -572,20 +515,19 @@ public: | |||
572 | checkAlive(); | 515 | checkAlive(); |
573 | } | 516 | } |
574 | 517 | ||
575 | virtual void checkAlive() | 518 | void checkAlive() |
576 | { | 519 | { |
577 | if (getChildCount() == 0 && getElementCount() == 0) | 520 | if (getChildCount() == 0 && getElementCount() == 0) |
578 | { | 521 | { |
579 | oct_node* node = getOctNode(); | 522 | oct_node* parent = getOctParent(); |
580 | oct_node* parent = node->getOctParent(); | ||
581 | if (parent) | 523 | if (parent) |
582 | { | 524 | { |
583 | parent->deleteChild(node); | 525 | parent->deleteChild(this); |
584 | } | 526 | } |
585 | } | 527 | } |
586 | } | 528 | } |
587 | 529 | ||
588 | virtual void deleteChild(oct_node* node) | 530 | void deleteChild(oct_node* node) |
589 | { | 531 | { |
590 | for (U32 i = 0; i < getChildCount(); i++) | 532 | for (U32 i = 0; i < getChildCount(); i++) |
591 | { | 533 | { |
@@ -596,55 +538,62 @@ public: | |||
596 | } | 538 | } |
597 | } | 539 | } |
598 | 540 | ||
599 | OCT_ERRS << "Octree failed to delete requested child." << llendl; | 541 | //OCT_ERRS << "Octree failed to delete requested child." << llendl; |
600 | } | 542 | } |
601 | 543 | ||
602 | protected: | 544 | protected: |
603 | child_list mChild; | 545 | child_list mChild; |
604 | element_list mData; | 546 | element_list mData; |
547 | oct_node* mParent; | ||
548 | LLVector3d mCenter; | ||
549 | LLVector3d mSize; | ||
550 | LLVector3d mMax; | ||
551 | LLVector3d mMin; | ||
552 | U8 mOctant; | ||
605 | }; | 553 | }; |
606 | 554 | ||
607 | //just like a branch, except it might expand the node it points to | 555 | //just like a regular node, except it might expand on insert and compress on balance |
608 | template <class T> | 556 | template <class T> |
609 | class LLOctreeRoot : public LLOctreeState<T> | 557 | class LLOctreeRoot : public LLOctreeNode<T> |
610 | { | 558 | { |
611 | public: | 559 | public: |
612 | typedef LLOctreeState<T> BaseType; | 560 | typedef LLOctreeNode<T> BaseType; |
613 | typedef LLOctreeNode<T> oct_node; | 561 | typedef LLOctreeNode<T> oct_node; |
562 | |||
563 | LLOctreeRoot( LLVector3d center, | ||
564 | LLVector3d size, | ||
565 | BaseType* parent) | ||
566 | : BaseType(center, size, parent) | ||
567 | { | ||
568 | } | ||
614 | 569 | ||
615 | LLOctreeRoot(oct_node* node = NULL) : BaseType(node) { } | 570 | bool isLeaf() { return false; } |
616 | |||
617 | oct_node* getOctNode() { return BaseType::getOctNode(); } | ||
618 | virtual bool isLeaf() { return false; } | ||
619 | 571 | ||
620 | virtual bool balance() | 572 | bool balance() |
621 | { | 573 | { |
622 | //the cached node might be invalid, so don't reference it | ||
623 | if (this->getChildCount() == 1 && | 574 | if (this->getChildCount() == 1 && |
624 | !(this->mChild[0]->hasLeafState()) && | 575 | !(this->mChild[0]->isLeaf()) && |
625 | this->mChild[0]->getElementCount() == 0) | 576 | this->mChild[0]->getElementCount() == 0) |
626 | { //if we have only one child and that child is an empty branch, make that child the root | 577 | { //if we have only one child and that child is an empty branch, make that child the root |
627 | BaseType* state = this->mChild[0]->getOctState(); | ||
628 | oct_node* child = this->mChild[0]; | 578 | oct_node* child = this->mChild[0]; |
629 | oct_node* root = getOctNode(); | 579 | |
630 | |||
631 | //make the root node look like the child | 580 | //make the root node look like the child |
632 | root->setCenter(this->mChild[0]->getCenter()); | 581 | this->setCenter(this->mChild[0]->getCenter()); |
633 | root->setSize(this->mChild[0]->getSize()); | 582 | this->setSize(this->mChild[0]->getSize()); |
634 | root->updateMinMax(); | 583 | this->updateMinMax(); |
635 | 584 | ||
636 | //reset root node child list | 585 | //reset root node child list |
637 | this->clearChildren(); | 586 | this->clearChildren(); |
638 | 587 | ||
639 | //copy the child's children into the root node silently | 588 | //copy the child's children into the root node silently |
640 | //(don't notify listeners of addition) | 589 | //(don't notify listeners of addition) |
641 | for (U32 i = 0; i < state->getChildCount(); i++) | 590 | for (U32 i = 0; i < child->getChildCount(); i++) |
642 | { | 591 | { |
643 | addChild(state->getChild(i), TRUE); | 592 | addChild(child->getChild(i), TRUE); |
644 | } | 593 | } |
645 | 594 | ||
646 | //destroy child | 595 | //destroy child |
647 | state->clearChildren(); | 596 | child->clearChildren(); |
648 | delete child; | 597 | delete child; |
649 | } | 598 | } |
650 | 599 | ||
@@ -652,69 +601,90 @@ public: | |||
652 | } | 601 | } |
653 | 602 | ||
654 | // LLOctreeRoot::insert | 603 | // LLOctreeRoot::insert |
655 | virtual bool insert(T* data) | 604 | bool insert(T* data) |
656 | { | 605 | { |
657 | if (data == NULL) | 606 | if (data == NULL) |
658 | { | 607 | { |
659 | OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl; | 608 | //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl; |
660 | return false; | 609 | return false; |
661 | } | 610 | } |
662 | 611 | ||
663 | if (data->getBinRadius() > 4096.0) | 612 | if (data->getBinRadius() > 4096.0) |
664 | { | 613 | { |
665 | OCT_ERRS << "!!! ELEMENT EXCEDES MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl; | 614 | //OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl; |
615 | return false; | ||
666 | } | 616 | } |
667 | 617 | ||
668 | LLOctreeNode<T>* node = getOctNode(); | 618 | const F64 MAX_MAG = 1024.0*1024.0; |
669 | if (node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup())) | 619 | |
620 | const LLVector3d& v = data->getPositionGroup(); | ||
621 | if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG && | ||
622 | fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG && | ||
623 | fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG)) | ||
624 | { | ||
625 | //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl; | ||
626 | return false; | ||
627 | } | ||
628 | |||
629 | if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())) | ||
670 | { | 630 | { |
671 | //we got it, just act like a branch | 631 | //we got it, just act like a branch |
672 | LLOctreeState<T>::insert(data); | 632 | oct_node* node = getNodeAt(data); |
633 | if (node == this) | ||
634 | { | ||
635 | LLOctreeNode<T>::insert(data); | ||
636 | } | ||
637 | else | ||
638 | { | ||
639 | node->insert(data); | ||
640 | } | ||
673 | } | 641 | } |
674 | else if (this->getChildCount() == 0) | 642 | else if (this->getChildCount() == 0) |
675 | { | 643 | { |
676 | //first object being added, just wrap it up | 644 | //first object being added, just wrap it up |
677 | while (!(node->getSize().mdV[0] > data->getBinRadius() && node->isInside(data->getPositionGroup()))) | 645 | while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) |
678 | { | 646 | { |
679 | LLVector3d center, size; | 647 | LLVector3d center, size; |
680 | center = node->getCenter(); | 648 | center = this->getCenter(); |
681 | size = node->getSize(); | 649 | size = this->getSize(); |
682 | LLOctreeNode<T>::pushCenter(center, size, data); | 650 | LLOctreeNode<T>::pushCenter(center, size, data); |
683 | node->setCenter(center); | 651 | this->setCenter(center); |
684 | node->setSize(size*2); | 652 | this->setSize(size*2); |
685 | node->updateMinMax(); | 653 | this->updateMinMax(); |
686 | } | 654 | } |
687 | LLOctreeState<T>::insert(data); | 655 | LLOctreeNode<T>::insert(data); |
688 | } | 656 | } |
689 | else | 657 | else |
690 | { | 658 | { |
691 | //the data is outside the root node, we need to grow | 659 | while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) |
692 | LLVector3d center(node->getCenter()); | ||
693 | LLVector3d size(node->getSize()); | ||
694 | |||
695 | //expand this node | ||
696 | LLVector3d newcenter(center); | ||
697 | LLOctreeNode<T>::pushCenter(newcenter, size, data); | ||
698 | node->setCenter(newcenter); | ||
699 | node->setSize(size*2); | ||
700 | node->updateMinMax(); | ||
701 | |||
702 | //copy our children to a new branch | ||
703 | LLOctreeState<T>* newstate = new LLOctreeState<T>(); | ||
704 | LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, newstate, node); | ||
705 | |||
706 | for (U32 i = 0; i < this->getChildCount(); i++) | ||
707 | { | 660 | { |
708 | LLOctreeNode<T>* child = this->getChild(i); | 661 | //the data is outside the root node, we need to grow |
709 | newstate->addChild(child); | 662 | LLVector3d center(this->getCenter()); |
710 | } | 663 | LLVector3d size(this->getSize()); |
664 | |||
665 | //expand this node | ||
666 | LLVector3d newcenter(center); | ||
667 | LLOctreeNode<T>::pushCenter(newcenter, size, data); | ||
668 | this->setCenter(newcenter); | ||
669 | this->setSize(size*2); | ||
670 | this->updateMinMax(); | ||
671 | |||
672 | //copy our children to a new branch | ||
673 | LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this); | ||
674 | |||
675 | for (U32 i = 0; i < this->getChildCount(); i++) | ||
676 | { | ||
677 | LLOctreeNode<T>* child = this->getChild(i); | ||
678 | newnode->addChild(child); | ||
679 | } | ||
711 | 680 | ||
712 | //clear our children and add the root copy | 681 | //clear our children and add the root copy |
713 | this->clearChildren(); | 682 | this->clearChildren(); |
714 | addChild(newnode); | 683 | addChild(newnode); |
684 | } | ||
715 | 685 | ||
716 | //insert the data | 686 | //insert the data |
717 | node->insert(data); | 687 | insert(data); |
718 | } | 688 | } |
719 | 689 | ||
720 | return false; | 690 | return false; |
@@ -726,13 +696,13 @@ public: | |||
726 | // LLOctreeTraveler | 696 | // LLOctreeTraveler |
727 | //======================== | 697 | //======================== |
728 | template <class T> | 698 | template <class T> |
729 | void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* node) | 699 | void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node) |
730 | { | 700 | { |
731 | const LLOctreeState<T>* state = (const LLOctreeState<T>*) node->getState(); | 701 | const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node; |
732 | state->accept(this); | 702 | node->accept(this); |
733 | for (U32 i = 0; i < state->getChildCount(); i++) | 703 | for (U32 i = 0; i < node->getChildCount(); i++) |
734 | { | 704 | { |
735 | traverse(state->getChild(i)); | 705 | traverse(node->getChild(i)); |
736 | } | 706 | } |
737 | } | 707 | } |
738 | 708 | ||