00001
00032 #ifndef LL_LLOCTREE_H
00033 #define LL_LLOCTREE_H
00034
00035 #include "lltreenode.h"
00036 #include "v3math.h"
00037 #include <vector>
00038 #include <set>
00039
00040 #ifdef LL_RELEASE_FOR_DOWNLOAD
00041 #define OCT_ERRS LL_WARNS("OctreeErrors")
00042 #else
00043 #define OCT_ERRS LL_ERRS("OctreeErrors")
00044 #endif
00045
00046 #define LL_OCTREE_PARANOIA_CHECK 0
00047 #if LL_DARWIN
00048 #define LL_OCTREE_MAX_CAPACITY 32
00049 #else
00050 #define LL_OCTREE_MAX_CAPACITY 128
00051 #endif
00052
00053 template <class T> class LLOctreeNode;
00054
00055 template <class T>
00056 class LLOctreeListener: public LLTreeListener<T>
00057 {
00058 public:
00059 typedef LLTreeListener<T> BaseType;
00060 typedef LLOctreeNode<T> oct_node;
00061
00062 virtual void handleChildAddition(const oct_node* parent, oct_node* child) = 0;
00063 virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;
00064 };
00065
00066 template <class T>
00067 class LLOctreeTraveler : public LLTreeTraveler<T>
00068 {
00069 public:
00070 virtual void traverse(const LLTreeNode<T>* node);
00071 virtual void visit(const LLTreeNode<T>* state) { }
00072 virtual void visit(const LLOctreeNode<T>* branch) = 0;
00073 };
00074
00075 template <class T>
00076 class LLOctreeNode : public LLTreeNode<T>
00077 {
00078 public:
00079 typedef LLOctreeTraveler<T> oct_traveler;
00080 typedef LLTreeTraveler<T> tree_traveler;
00081 typedef typename std::set<LLPointer<T> > element_list;
00082 typedef typename std::set<LLPointer<T> >::iterator element_iter;
00083 typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
00084 typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
00085 typedef typename std::vector<LLOctreeNode<T>* > child_list;
00086 typedef LLTreeNode<T> BaseType;
00087 typedef LLOctreeNode<T> oct_node;
00088 typedef LLOctreeListener<T> oct_listener;
00089
00090 static const U8 OCTANT_POSITIVE_X = 0x01;
00091 static const U8 OCTANT_POSITIVE_Y = 0x02;
00092 static const U8 OCTANT_POSITIVE_Z = 0x04;
00093
00094 LLOctreeNode( LLVector3d center,
00095 LLVector3d size,
00096 BaseType* parent,
00097 U8 octant = 255)
00098 : mParent((oct_node*)parent),
00099 mCenter(center),
00100 mSize(size),
00101 mOctant(octant)
00102 {
00103 updateMinMax();
00104 if ((mOctant == 255) && mParent)
00105 {
00106 mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV);
00107 }
00108
00109 clearChildren();
00110 }
00111
00112 virtual ~LLOctreeNode()
00113 {
00114 BaseType::destroyListeners();
00115
00116 for (U32 i = 0; i < getChildCount(); i++)
00117 {
00118 delete getChild(i);
00119 }
00120 }
00121
00122 inline const BaseType* getParent() const { return mParent; }
00123 inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
00124 inline const LLVector3d& getCenter() const { return mCenter; }
00125 inline const LLVector3d& getSize() const { return mSize; }
00126 inline void setCenter(LLVector3d center) { mCenter = center; }
00127 inline void setSize(LLVector3d size) { mSize = size; }
00128 inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
00129 inline U8 getOctant() const { return mOctant; }
00130 inline void setOctant(U8 octant) { mOctant = octant; }
00131 inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
00132 inline oct_node* getOctParent() { return (oct_node*) getParent(); }
00133
00134 U8 getOctant(const F64 pos[]) const
00135 {
00136 U8 ret = 0;
00137
00138 if (pos[0] > mCenter.mdV[0])
00139 {
00140 ret |= OCTANT_POSITIVE_X;
00141 }
00142 if (pos[1] > mCenter.mdV[1])
00143 {
00144 ret |= OCTANT_POSITIVE_Y;
00145 }
00146 if (pos[2] > mCenter.mdV[2])
00147 {
00148 ret |= OCTANT_POSITIVE_Z;
00149 }
00150
00151 return ret;
00152 }
00153
00154 inline bool isInside(const LLVector3d& pos, const F64& rad) const
00155 {
00156 return rad <= mSize.mdV[0]*2.0 && isInside(pos);
00157 }
00158
00159 inline bool isInside(T* data) const
00160 {
00161 return isInside(data->getPositionGroup(), data->getBinRadius());
00162 }
00163
00164 bool isInside(const LLVector3d& pos) const
00165 {
00166 const F64& x = pos.mdV[0];
00167 const F64& y = pos.mdV[1];
00168 const F64& z = pos.mdV[2];
00169
00170 if (x > mMax.mdV[0] || x <= mMin.mdV[0] ||
00171 y > mMax.mdV[1] || y <= mMin.mdV[1] ||
00172 z > mMax.mdV[2] || z <= mMin.mdV[2])
00173 {
00174 return false;
00175 }
00176
00177 return true;
00178 }
00179
00180 void updateMinMax()
00181 {
00182 for (U32 i = 0; i < 3; i++)
00183 {
00184 mMax.mdV[i] = mCenter.mdV[i] + mSize.mdV[i];
00185 mMin.mdV[i] = mCenter.mdV[i] - mSize.mdV[i];
00186 mCenter.mdV[i] = mCenter.mdV[i];
00187 }
00188 }
00189
00190 inline oct_listener* getOctListener(U32 index)
00191 {
00192 return (oct_listener*) BaseType::getListener(index);
00193 }
00194
00195 inline bool contains(T* xform)
00196 {
00197 return contains(xform->getBinRadius());
00198 }
00199
00200 bool contains(F64 radius)
00201 {
00202 if (mParent == NULL)
00203 {
00204 return false;
00205 }
00206
00207 F64 size = mSize.mdV[0];
00208 F64 p_size = size * 2.0;
00209
00210 return (radius <= 0.001 && size <= 0.001) ||
00211 (radius <= p_size && radius > size);
00212 }
00213
00214 static void pushCenter(LLVector3d ¢er, const LLVector3d &size, const T* data)
00215 {
00216 const LLVector3d& pos = data->getPositionGroup();
00217 for (U32 i = 0; i < 3; i++)
00218 {
00219 if (pos.mdV[i] > center.mdV[i])
00220 {
00221 center.mdV[i] += size.mdV[i];
00222 }
00223 else
00224 {
00225 center.mdV[i] -= size.mdV[i];
00226 }
00227 }
00228 }
00229
00230 void accept(oct_traveler* visitor) { visitor->visit(this); }
00231 virtual bool isLeaf() const { return mChild.empty(); }
00232
00233 U32 getElementCount() const { return mData.size(); }
00234 element_list& getData() { return mData; }
00235 const element_list& getData() const { return mData; }
00236
00237 U32 getChildCount() const { return mChild.size(); }
00238 oct_node* getChild(U32 index) { return mChild[index]; }
00239 const oct_node* getChild(U32 index) const { return mChild[index]; }
00240 child_list& getChildren() { return mChild; }
00241 const child_list& getChildren() const { return mChild; }
00242
00243 void accept(tree_traveler* visitor) const { visitor->visit(this); }
00244 void accept(oct_traveler* visitor) const { visitor->visit(this); }
00245
00246 oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
00247 {
00248 LLOctreeNode<T>* node = this;
00249
00250 if (node->isInside(pos, rad))
00251 {
00252
00253 U8 octant = node->getOctant(pos.mdV);
00254 BOOL keep_going = TRUE;
00255
00256
00257
00258
00259
00260 while (keep_going && node->getSize().mdV[0] >= rad)
00261 {
00262 keep_going = FALSE;
00263 for (U32 i = 0; i < node->getChildCount() && !keep_going; i++)
00264 {
00265 if (node->getChild(i)->getOctant() == octant)
00266 {
00267 node = node->getChild(i);
00268 octant = node->getOctant(pos.mdV);
00269 keep_going = TRUE;
00270 }
00271 }
00272 }
00273 }
00274 else if (!node->contains(rad) && node->getParent())
00275 {
00276 return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(pos, rad);
00277 }
00278
00279 return node;
00280 }
00281
00282 virtual bool insert(T* data)
00283 {
00284 if (data == NULL)
00285 {
00286
00287 return false;
00288 }
00289 LLOctreeNode<T>* parent = getOctParent();
00290
00291
00292 if (isInside(data->getPositionGroup()))
00293 {
00294 if (getElementCount() < LL_OCTREE_MAX_CAPACITY &&
00295 (contains(data->getBinRadius()) ||
00296 (data->getBinRadius() > getSize().mdV[0] &&
00297 parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
00298 {
00299 #if LL_OCTREE_PARANOIA_CHECK
00300
00301 if (mData.find(data) != mData.end())
00302 {
00303 llwarns << "Redundant octree insertion detected. " << data << llendl;
00304 return false;
00305 }
00306 #endif
00307
00308 mData.insert(data);
00309 BaseType::insert(data);
00310 return true;
00311 }
00312 else
00313 {
00314
00315 oct_node* child = NULL;
00316 for (U32 i = 0; i < getChildCount(); i++)
00317 {
00318 child = getChild(i);
00319 if (child->isInside(data->getPositionGroup()))
00320 {
00321 child->insert(data);
00322 return false;
00323 }
00324 }
00325
00326
00327 LLVector3d center(getCenter());
00328 LLVector3d size(getSize()*0.5);
00329
00330
00331 LLOctreeNode<T>::pushCenter(center, size, data);
00332
00333 #if LL_OCTREE_PARANOIA_CHECK
00334 if (getChildCount() == 8)
00335 {
00336
00337 OCT_ERRS << "Octree detected floating point error and gave up." << llendl;
00338 return false;
00339 }
00340
00341
00342 for (U32 i = 0; i < getChildCount(); i++)
00343 {
00344 if (mChild[i]->getCenter() == center)
00345 {
00346 OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl;
00347 return false;
00348 }
00349 }
00350 #endif
00351
00352
00353 child = new LLOctreeNode<T>(center, size, this);
00354 addChild(child);
00355
00356 child->insert(data);
00357 }
00358 }
00359 else
00360 {
00361
00362
00363
00364 oct_node* node = this;
00365
00366 while (parent)
00367 {
00368 node = parent;
00369 parent = node->getOctParent();
00370 }
00371
00372 node->insert(data);
00373 }
00374
00375 return false;
00376 }
00377
00378 bool remove(T* data)
00379 {
00380 if (mData.find(data) != mData.end())
00381 {
00382 mData.erase(data);
00383 notifyRemoval(data);
00384 checkAlive();
00385 return true;
00386 }
00387 else if (isInside(data))
00388 {
00389 oct_node* dest = getNodeAt(data);
00390
00391 if (dest != this)
00392 {
00393 return dest->remove(data);
00394 }
00395 }
00396
00397
00398
00399
00400 oct_node* parent = getOctParent();
00401 oct_node* node = this;
00402
00403 while (parent != NULL)
00404 {
00405 node = parent;
00406 parent = node->getOctParent();
00407 }
00408
00409
00410 llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl;
00411 node->removeByAddress(data);
00412 return true;
00413 }
00414
00415 void removeByAddress(T* data)
00416 {
00417 if (mData.find(data) != mData.end())
00418 {
00419 mData.erase(data);
00420 notifyRemoval(data);
00421 llwarns << "FOUND!" << llendl;
00422 checkAlive();
00423 return;
00424 }
00425
00426 for (U32 i = 0; i < getChildCount(); i++)
00427 {
00428 LLOctreeNode<T>* child = (LLOctreeNode<T>*) getChild(i);
00429 child->removeByAddress(data);
00430 }
00431 }
00432
00433 void clearChildren()
00434 {
00435 mChild.clear();
00436 }
00437
00438 void validate()
00439 {
00440 #if LL_OCTREE_PARANOIA_CHECK
00441 for (U32 i = 0; i < getChildCount(); i++)
00442 {
00443 mChild[i]->validate();
00444 if (mChild[i]->getParent() != this)
00445 {
00446 llerrs << "Octree child has invalid parent." << llendl;
00447 }
00448 }
00449 #endif
00450 }
00451
00452 virtual bool balance()
00453 {
00454 return false;
00455 }
00456
00457 void destroy()
00458 {
00459 for (U32 i = 0; i < getChildCount(); i++)
00460 {
00461 mChild[i]->destroy();
00462 delete mChild[i];
00463 }
00464 }
00465
00466 void addChild(oct_node* child, BOOL silent = FALSE)
00467 {
00468 #if LL_OCTREE_PARANOIA_CHECK
00469 for (U32 i = 0; i < getChildCount(); i++)
00470 {
00471 if(mChild[i]->getSize() != child->getSize())
00472 {
00473 OCT_ERRS <<"Invalid octree child size." << llendl;
00474 }
00475 if (mChild[i]->getCenter() == child->getCenter())
00476 {
00477 OCT_ERRS <<"Duplicate octree child position." << llendl;
00478 }
00479 }
00480
00481 if (mChild.size() >= 8)
00482 {
00483 OCT_ERRS <<"Octree node has too many children... why?" << llendl;
00484 }
00485 #endif
00486
00487 mChild.push_back(child);
00488 child->setParent(this);
00489
00490 if (!silent)
00491 {
00492 for (U32 i = 0; i < this->getListenerCount(); i++)
00493 {
00494 oct_listener* listener = getOctListener(i);
00495 listener->handleChildAddition(this, child);
00496 }
00497 }
00498 }
00499
00500 void removeChild(U8 index, BOOL destroy = FALSE)
00501 {
00502 for (U32 i = 0; i < this->getListenerCount(); i++)
00503 {
00504 oct_listener* listener = getOctListener(i);
00505 listener->handleChildRemoval(this, getChild(index));
00506 }
00507
00508 if (destroy)
00509 {
00510 mChild[index]->destroy();
00511 delete mChild[index];
00512 }
00513 mChild.erase(mChild.begin() + index);
00514
00515 checkAlive();
00516 }
00517
00518 void checkAlive()
00519 {
00520 if (getChildCount() == 0 && getElementCount() == 0)
00521 {
00522 oct_node* parent = getOctParent();
00523 if (parent)
00524 {
00525 parent->deleteChild(this);
00526 }
00527 }
00528 }
00529
00530 void deleteChild(oct_node* node)
00531 {
00532 for (U32 i = 0; i < getChildCount(); i++)
00533 {
00534 if (getChild(i) == node)
00535 {
00536 removeChild(i, TRUE);
00537 return;
00538 }
00539 }
00540
00541
00542 }
00543
00544 protected:
00545 child_list mChild;
00546 element_list mData;
00547 oct_node* mParent;
00548 LLVector3d mCenter;
00549 LLVector3d mSize;
00550 LLVector3d mMax;
00551 LLVector3d mMin;
00552 U8 mOctant;
00553 };
00554
00555
00556 template <class T>
00557 class LLOctreeRoot : public LLOctreeNode<T>
00558 {
00559 public:
00560 typedef LLOctreeNode<T> BaseType;
00561 typedef LLOctreeNode<T> oct_node;
00562
00563 LLOctreeRoot( LLVector3d center,
00564 LLVector3d size,
00565 BaseType* parent)
00566 : BaseType(center, size, parent)
00567 {
00568 }
00569
00570 bool balance()
00571 {
00572 if (this->getChildCount() == 1 &&
00573 !(this->mChild[0]->isLeaf()) &&
00574 this->mChild[0]->getElementCount() == 0)
00575 {
00576 oct_node* child = this->mChild[0];
00577
00578
00579 this->setCenter(this->mChild[0]->getCenter());
00580 this->setSize(this->mChild[0]->getSize());
00581 this->updateMinMax();
00582
00583
00584 this->clearChildren();
00585
00586
00587
00588 for (U32 i = 0; i < child->getChildCount(); i++)
00589 {
00590 addChild(child->getChild(i), TRUE);
00591 }
00592
00593
00594 child->clearChildren();
00595 delete child;
00596 }
00597
00598 return true;
00599 }
00600
00601
00602 bool insert(T* data)
00603 {
00604 if (data == NULL)
00605 {
00606
00607 return false;
00608 }
00609
00610 if (data->getBinRadius() > 4096.0)
00611 {
00612
00613 return false;
00614 }
00615
00616 const F64 MAX_MAG = 1024.0*1024.0;
00617
00618 const LLVector3d& v = data->getPositionGroup();
00619 if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG &&
00620 fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG &&
00621 fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG))
00622 {
00623
00624 return false;
00625 }
00626
00627 if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))
00628 {
00629
00630 oct_node* node = getNodeAt(data);
00631 if (node == this)
00632 {
00633 LLOctreeNode<T>::insert(data);
00634 }
00635 else
00636 {
00637 node->insert(data);
00638 }
00639 }
00640 else if (this->getChildCount() == 0)
00641 {
00642
00643 while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
00644 {
00645 LLVector3d center, size;
00646 center = this->getCenter();
00647 size = this->getSize();
00648 LLOctreeNode<T>::pushCenter(center, size, data);
00649 this->setCenter(center);
00650 this->setSize(size*2);
00651 this->updateMinMax();
00652 }
00653 LLOctreeNode<T>::insert(data);
00654 }
00655 else
00656 {
00657 while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
00658 {
00659
00660 LLVector3d center(this->getCenter());
00661 LLVector3d size(this->getSize());
00662
00663
00664 LLVector3d newcenter(center);
00665 LLOctreeNode<T>::pushCenter(newcenter, size, data);
00666 this->setCenter(newcenter);
00667 this->setSize(size*2);
00668 this->updateMinMax();
00669
00670
00671 LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
00672
00673 for (U32 i = 0; i < this->getChildCount(); i++)
00674 {
00675 LLOctreeNode<T>* child = this->getChild(i);
00676 newnode->addChild(child);
00677 }
00678
00679
00680 this->clearChildren();
00681 addChild(newnode);
00682 }
00683
00684
00685 insert(data);
00686 }
00687
00688 return false;
00689 }
00690 };
00691
00692
00693
00694
00695
00696 template <class T>
00697 void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node)
00698 {
00699 const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node;
00700 node->accept(this);
00701 for (U32 i = 0; i < node->getChildCount(); i++)
00702 {
00703 traverse(node->getChild(i));
00704 }
00705 }
00706
00707 #endif