lloctree.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:17k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lloctree.h
  3.  * @brief Octree declaration. 
  4.  *
  5.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2005-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #ifndef LL_LLOCTREE_H
  33. #define LL_LLOCTREE_H
  34. #include "lltreenode.h"
  35. #include "v3math.h"
  36. #include <vector>
  37. #include <set>
  38. #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
  39. #define OCT_ERRS LL_ERRS("OctreeErrors")
  40. #else
  41. #define OCT_ERRS LL_WARNS("OctreeErrors")
  42. #endif
  43. #define LL_OCTREE_PARANOIA_CHECK 0
  44. #if LL_DARWIN
  45. #define LL_OCTREE_MAX_CAPACITY 32
  46. #else
  47. #define LL_OCTREE_MAX_CAPACITY 128
  48. #endif
  49. template <class T> class LLOctreeNode;
  50. template <class T>
  51. class LLOctreeListener: public LLTreeListener<T>
  52. {
  53. public:
  54. typedef LLTreeListener<T> BaseType;
  55. typedef LLOctreeNode<T> oct_node;
  56. virtual void handleChildAddition(const oct_node* parent, oct_node* child) = 0;
  57. virtual void handleChildRemoval(const oct_node* parent, const oct_node* child) = 0;
  58. };
  59. template <class T>
  60. class LLOctreeTraveler
  61. {
  62. public:
  63. virtual void traverse(const LLOctreeNode<T>* node);
  64. virtual void visit(const LLOctreeNode<T>* branch) = 0;
  65. };
  66. template <class T>
  67. class LLOctreeNode : public LLTreeNode<T>
  68. {
  69. public:
  70. typedef LLOctreeTraveler<T> oct_traveler;
  71. typedef LLTreeTraveler<T> tree_traveler;
  72. typedef typename std::set<LLPointer<T> > element_list;
  73. typedef typename std::set<LLPointer<T> >::iterator element_iter;
  74. typedef typename std::set<LLPointer<T> >::const_iterator const_element_iter;
  75. typedef typename std::vector<LLTreeListener<T>*>::iterator tree_listener_iter;
  76. typedef typename std::vector<LLOctreeNode<T>* > child_list;
  77. typedef LLTreeNode<T> BaseType;
  78. typedef LLOctreeNode<T> oct_node;
  79. typedef LLOctreeListener<T> oct_listener;
  80. static const U8 OCTANT_POSITIVE_X = 0x01;
  81. static const U8 OCTANT_POSITIVE_Y = 0x02;
  82. static const U8 OCTANT_POSITIVE_Z = 0x04;
  83. LLOctreeNode( LLVector3d center, 
  84. LLVector3d size, 
  85. BaseType* parent, 
  86. U8 octant = 255)
  87. : mParent((oct_node*)parent), 
  88. mCenter(center), 
  89. mSize(size), 
  90. mOctant(octant) 
  91. updateMinMax();
  92. if ((mOctant == 255) && mParent)
  93. {
  94. mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV);
  95. }
  96. clearChildren();
  97. }
  98. virtual ~LLOctreeNode()
  99. BaseType::destroyListeners(); 
  100. for (U32 i = 0; i < getChildCount(); i++)
  101. {
  102. delete getChild(i);
  103. }
  104. inline const BaseType* getParent() const { return mParent; }
  105. inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; }
  106. inline const LLVector3d& getCenter() const { return mCenter; }
  107. inline const LLVector3d& getSize() const { return mSize; }
  108. inline void setCenter(LLVector3d center) { mCenter = center; }
  109. inline void setSize(LLVector3d size) { mSize = size; }
  110.     inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); }
  111. inline U8 getOctant() const { return mOctant; }
  112. inline void setOctant(U8 octant) { mOctant = octant; }
  113. inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); }
  114. inline oct_node* getOctParent()  { return (oct_node*) getParent(); }
  115. U8 getOctant(const F64 pos[]) const //get the octant pos is in
  116. {
  117. U8 ret = 0;
  118. if (pos[0] > mCenter.mdV[0])
  119. {
  120. ret |= OCTANT_POSITIVE_X;
  121. }
  122. if (pos[1] > mCenter.mdV[1])
  123. {
  124. ret |= OCTANT_POSITIVE_Y;
  125. }
  126. if (pos[2] > mCenter.mdV[2])
  127. {
  128. ret |= OCTANT_POSITIVE_Z;
  129. }
  130. return ret;
  131. }
  132. inline bool isInside(const LLVector3d& pos, const F64& rad) const
  133. {
  134. return rad <= mSize.mdV[0]*2.0 && isInside(pos); 
  135. }
  136. inline bool isInside(T* data) const
  137. return isInside(data->getPositionGroup(), data->getBinRadius());
  138. }
  139. bool isInside(const LLVector3d& pos) const
  140. {
  141. const F64& x = pos.mdV[0];
  142. const F64& y = pos.mdV[1];
  143. const F64& z = pos.mdV[2];
  144. if (x > mMax.mdV[0] || x <= mMin.mdV[0] ||
  145. y > mMax.mdV[1] || y <= mMin.mdV[1] ||
  146. z > mMax.mdV[2] || z <= mMin.mdV[2])
  147. {
  148. return false;
  149. }
  150. return true;
  151. }
  152. void updateMinMax()
  153. {
  154. for (U32 i = 0; i < 3; i++)
  155. {
  156. mMax.mdV[i] = mCenter.mdV[i] + mSize.mdV[i];
  157. mMin.mdV[i] = mCenter.mdV[i] - mSize.mdV[i];
  158. }
  159. }
  160. inline oct_listener* getOctListener(U32 index) 
  161. return (oct_listener*) BaseType::getListener(index); 
  162. }
  163. inline bool contains(T* xform)
  164. {
  165. return contains(xform->getBinRadius());
  166. }
  167. bool contains(F64 radius)
  168. {
  169. if (mParent == NULL)
  170. { //root node contains nothing
  171. return false;
  172. }
  173. F64 size = mSize.mdV[0];
  174. F64 p_size = size * 2.0;
  175. return (radius <= 0.001 && size <= 0.001) ||
  176. (radius <= p_size && radius > size);
  177. }
  178. static void pushCenter(LLVector3d &center, const LLVector3d &size, const T* data)
  179. {
  180. const LLVector3d& pos = data->getPositionGroup();
  181. for (U32 i = 0; i < 3; i++)
  182. {
  183. if (pos.mdV[i] > center.mdV[i])
  184. {
  185. center.mdV[i] += size.mdV[i];
  186. }
  187. else 
  188. {
  189. center.mdV[i] -= size.mdV[i];
  190. }
  191. }
  192. }
  193. void accept(oct_traveler* visitor) { visitor->visit(this); }
  194. virtual bool isLeaf() const { return mChild.empty(); }
  195. U32 getElementCount() const { return mData.size(); }
  196. element_list& getData() { return mData; }
  197. const element_list& getData() const { return mData; }
  198. U32 getChildCount() const { return mChild.size(); }
  199. oct_node* getChild(U32 index) { return mChild[index]; }
  200. const oct_node* getChild(U32 index) const { return mChild[index]; }
  201. child_list& getChildren() { return mChild; }
  202. const child_list& getChildren() const { return mChild; }
  203. void accept(tree_traveler* visitor) const { visitor->visit(this); }
  204. void accept(oct_traveler* visitor) const { visitor->visit(this); }
  205. oct_node* getNodeAt(const LLVector3d& pos, const F64& rad)
  206. LLOctreeNode<T>* node = this;
  207. if (node->isInside(pos, rad))
  208. {
  209. //do a quick search by octant
  210. U8 octant = node->getOctant(pos.mdV);
  211. BOOL keep_going = TRUE;
  212. //traverse the tree until we find a node that has no node
  213. //at the appropriate octant or is smaller than the object.  
  214. //by definition, that node is the smallest node that contains 
  215. // the data
  216. while (keep_going && node->getSize().mdV[0] >= rad)
  217. {
  218. keep_going = FALSE;
  219. for (U32 i = 0; i < node->getChildCount() && !keep_going; i++)
  220. {
  221. if (node->getChild(i)->getOctant() == octant)
  222. {
  223. node = node->getChild(i);
  224. octant = node->getOctant(pos.mdV);
  225. keep_going = TRUE;
  226. }
  227. }
  228. }
  229. }
  230. else if (!node->contains(rad) && node->getParent())
  231. { //if we got here, data does not exist in this node
  232. return ((LLOctreeNode<T>*) node->getParent())->getNodeAt(pos, rad);
  233. }
  234. return node;
  235. }
  236. virtual bool insert(T* data)
  237. {
  238. if (data == NULL)
  239. {
  240. //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
  241. return false;
  242. }
  243. LLOctreeNode<T>* parent = getOctParent();
  244. //is it here?
  245. if (isInside(data->getPositionGroup()))
  246. {
  247. if (getElementCount() < LL_OCTREE_MAX_CAPACITY &&
  248. (contains(data->getBinRadius()) ||
  249. (data->getBinRadius() > getSize().mdV[0] &&
  250. parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) 
  251. { //it belongs here
  252. #if LL_OCTREE_PARANOIA_CHECK
  253. //if this is a redundant insertion, error out (should never happen)
  254. if (mData.find(data) != mData.end())
  255. {
  256. llwarns << "Redundant octree insertion detected. " << data << llendl;
  257. return false;
  258. }
  259. #endif
  260. mData.insert(data);
  261. BaseType::insert(data);
  262. return true;
  263. }
  264. else
  265. //find a child to give it to
  266. oct_node* child = NULL;
  267. for (U32 i = 0; i < getChildCount(); i++)
  268. {
  269. child = getChild(i);
  270. if (child->isInside(data->getPositionGroup()))
  271. {
  272. child->insert(data);
  273. return false;
  274. }
  275. }
  276. //it's here, but no kids are in the right place, make a new kid
  277. LLVector3d center(getCenter());
  278. LLVector3d size(getSize()*0.5);
  279.         
  280. //push center in direction of data
  281. LLOctreeNode<T>::pushCenter(center, size, data);
  282. // handle case where floating point number gets too small
  283. if( llabs(center.mdV[0] - getCenter().mdV[0]) < F_APPROXIMATELY_ZERO &&
  284. llabs(center.mdV[1] - getCenter().mdV[1]) < F_APPROXIMATELY_ZERO &&
  285. llabs(center.mdV[2] - getCenter().mdV[2]) < F_APPROXIMATELY_ZERO)
  286. {
  287. mData.insert(data);
  288. BaseType::insert(data);
  289. return true;
  290. }
  291. #if LL_OCTREE_PARANOIA_CHECK
  292. if (getChildCount() == 8)
  293. {
  294. //this really isn't possible, something bad has happened
  295. OCT_ERRS << "Octree detected floating point error and gave up." << llendl;
  296. return false;
  297. }
  298. //make sure no existing node matches this position
  299. for (U32 i = 0; i < getChildCount(); i++)
  300. {
  301. if (mChild[i]->getCenter() == center)
  302. {
  303. OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl;
  304. return false;
  305. }
  306. }
  307. #endif
  308. //make the new kid
  309. child = new LLOctreeNode<T>(center, size, this);
  310. addChild(child);
  311. child->insert(data);
  312. }
  313. }
  314. else 
  315. {
  316. //it's not in here, give it to the root
  317. //OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl;
  318. oct_node* node = this;
  319. while (parent)
  320. {
  321. node = parent;
  322. parent = node->getOctParent();
  323. }
  324. node->insert(data);
  325. }
  326. return false;
  327. }
  328. bool remove(T* data)
  329. {
  330. if (mData.find(data) != mData.end())
  331. { //we have data
  332. mData.erase(data);
  333. notifyRemoval(data);
  334. checkAlive();
  335. return true;
  336. }
  337. else if (isInside(data))
  338. {
  339. oct_node* dest = getNodeAt(data);
  340. if (dest != this)
  341. {
  342. return dest->remove(data);
  343. }
  344. }
  345. //SHE'S GONE MISSING...
  346. //none of the children have it, let's just brute force this bastard out
  347. //starting with the root node (UGLY CODE COMETH!)
  348. oct_node* parent = getOctParent();
  349. oct_node* node = this;
  350. while (parent != NULL)
  351. {
  352. node = parent;
  353. parent = node->getOctParent();
  354. }
  355. //node is now root
  356. llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl;
  357. node->removeByAddress(data);
  358. return true;
  359. }
  360. void removeByAddress(T* data)
  361. {
  362.         if (mData.find(data) != mData.end())
  363. {
  364. mData.erase(data);
  365. notifyRemoval(data);
  366. llwarns << "FOUND!" << llendl;
  367. checkAlive();
  368. return;
  369. }
  370. for (U32 i = 0; i < getChildCount(); i++)
  371. { //we don't contain data, so pass this guy down
  372. LLOctreeNode<T>* child = (LLOctreeNode<T>*) getChild(i);
  373. child->removeByAddress(data);
  374. }
  375. }
  376. void clearChildren()
  377. {
  378. mChild.clear();
  379. }
  380. void validate()
  381. {
  382. #if LL_OCTREE_PARANOIA_CHECK
  383. for (U32 i = 0; i < getChildCount(); i++)
  384. {
  385. mChild[i]->validate();
  386. if (mChild[i]->getParent() != this)
  387. {
  388. llerrs << "Octree child has invalid parent." << llendl;
  389. }
  390. }
  391. #endif
  392. }
  393. virtual bool balance()
  394. {
  395. return false;
  396. }
  397. void destroy()
  398. {
  399. for (U32 i = 0; i < getChildCount(); i++) 
  400. {
  401. mChild[i]->destroy();
  402. delete mChild[i];
  403. }
  404. }
  405. void addChild(oct_node* child, BOOL silent = FALSE) 
  406. {
  407. #if LL_OCTREE_PARANOIA_CHECK
  408. for (U32 i = 0; i < getChildCount(); i++)
  409. {
  410. if(mChild[i]->getSize() != child->getSize()) 
  411. {
  412. OCT_ERRS <<"Invalid octree child size." << llendl;
  413. }
  414. if (mChild[i]->getCenter() == child->getCenter())
  415. {
  416. OCT_ERRS <<"Duplicate octree child position." << llendl;
  417. }
  418. }
  419. if (mChild.size() >= 8)
  420. {
  421. OCT_ERRS <<"Octree node has too many children... why?" << llendl;
  422. }
  423. #endif
  424. mChild.push_back(child);
  425. child->setParent(this);
  426. if (!silent)
  427. {
  428. for (U32 i = 0; i < this->getListenerCount(); i++)
  429. {
  430. oct_listener* listener = getOctListener(i);
  431. listener->handleChildAddition(this, child);
  432. }
  433. }
  434. }
  435. void removeChild(U8 index, BOOL destroy = FALSE)
  436. {
  437. for (U32 i = 0; i < this->getListenerCount(); i++)
  438. {
  439. oct_listener* listener = getOctListener(i);
  440. listener->handleChildRemoval(this, getChild(index));
  441. }
  442. if (destroy)
  443. {
  444. mChild[index]->destroy();
  445. delete mChild[index];
  446. }
  447. mChild.erase(mChild.begin() + index);
  448. checkAlive();
  449. }
  450. void checkAlive()
  451. {
  452. if (getChildCount() == 0 && getElementCount() == 0)
  453. {
  454. oct_node* parent = getOctParent();
  455. if (parent)
  456. {
  457. parent->deleteChild(this);
  458. }
  459. }
  460. }
  461. void deleteChild(oct_node* node)
  462. {
  463. for (U32 i = 0; i < getChildCount(); i++)
  464. {
  465. if (getChild(i) == node)
  466. {
  467. removeChild(i, TRUE);
  468. return;
  469. }
  470. }
  471. //OCT_ERRS << "Octree failed to delete requested child." << llendl;
  472. }
  473. protected:
  474. child_list mChild;
  475. element_list mData;
  476. oct_node* mParent;
  477. LLVector3d mCenter;
  478. LLVector3d mSize;
  479. LLVector3d mMax;
  480. LLVector3d mMin;
  481. U8 mOctant;
  482. };
  483. //just like a regular node, except it might expand on insert and compress on balance
  484. template <class T>
  485. class LLOctreeRoot : public LLOctreeNode<T>
  486. {
  487. public:
  488. typedef LLOctreeNode<T> BaseType;
  489. typedef LLOctreeNode<T> oct_node;
  490. LLOctreeRoot( LLVector3d center, 
  491. LLVector3d size, 
  492. BaseType* parent)
  493. : BaseType(center, size, parent)
  494. {
  495. }
  496. bool balance()
  497. {
  498. if (this->getChildCount() == 1 && 
  499. !(this->mChild[0]->isLeaf()) &&
  500. this->mChild[0]->getElementCount() == 0) 
  501. { //if we have only one child and that child is an empty branch, make that child the root
  502. oct_node* child = this->mChild[0];
  503. //make the root node look like the child
  504. this->setCenter(this->mChild[0]->getCenter());
  505. this->setSize(this->mChild[0]->getSize());
  506. this->updateMinMax();
  507. //reset root node child list
  508. this->clearChildren();
  509. //copy the child's children into the root node silently 
  510. //(don't notify listeners of addition)
  511. for (U32 i = 0; i < child->getChildCount(); i++)
  512. {
  513. addChild(child->getChild(i), TRUE);
  514. }
  515. //destroy child
  516. child->clearChildren();
  517. delete child;
  518. }
  519. return true;
  520. }
  521. // LLOctreeRoot::insert
  522. bool insert(T* data)
  523. {
  524. if (data == NULL) 
  525. {
  526. //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
  527. return false;
  528. }
  529. if (data->getBinRadius() > 4096.0)
  530. {
  531. //OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
  532. return false;
  533. }
  534. const F64 MAX_MAG = 1024.0*1024.0;
  535. const LLVector3d& v = data->getPositionGroup();
  536. if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG &&
  537.       fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG &&
  538.       fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG))
  539. {
  540. //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
  541. return false;
  542. }
  543. if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))
  544. {
  545. //we got it, just act like a branch
  546. oct_node* node = getNodeAt(data);
  547. if (node == this)
  548. {
  549. LLOctreeNode<T>::insert(data);
  550. }
  551. else
  552. {
  553. node->insert(data);
  554. }
  555. }
  556. else if (this->getChildCount() == 0)
  557. {
  558. //first object being added, just wrap it up
  559. while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
  560. {
  561. LLVector3d center, size;
  562. center = this->getCenter();
  563. size = this->getSize();
  564. LLOctreeNode<T>::pushCenter(center, size, data);
  565. this->setCenter(center);
  566. this->setSize(size*2);
  567. this->updateMinMax();
  568. }
  569. LLOctreeNode<T>::insert(data);
  570. }
  571. else
  572. {
  573. while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())))
  574. {
  575. //the data is outside the root node, we need to grow
  576. LLVector3d center(this->getCenter());
  577. LLVector3d size(this->getSize());
  578. //expand this node
  579. LLVector3d newcenter(center);
  580. LLOctreeNode<T>::pushCenter(newcenter, size, data);
  581. this->setCenter(newcenter);
  582. this->setSize(size*2);
  583. this->updateMinMax();
  584. //copy our children to a new branch
  585. LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
  586. for (U32 i = 0; i < this->getChildCount(); i++)
  587. {
  588. LLOctreeNode<T>* child = this->getChild(i);
  589. newnode->addChild(child);
  590. }
  591. //clear our children and add the root copy
  592. this->clearChildren();
  593. addChild(newnode);
  594. }
  595. //insert the data
  596. insert(data);
  597. }
  598. return false;
  599. }
  600. };
  601. //========================
  602. // LLOctreeTraveler
  603. //========================
  604. template <class T>
  605. void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node)
  606. {
  607. node->accept(this);
  608. for (U32 i = 0; i < node->getChildCount(); i++)
  609. {
  610. traverse(node->getChild(i));
  611. }
  612. }
  613. #endif