BsOctree.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2017 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "Prerequisites/BsPrerequisitesUtil.h"
  5. #include "Math/BsMath.h"
  6. #include "Math/BsVector4I.h"
  7. #include "Math/BsSIMD.h"
  8. #include "Allocators/BsPoolAlloc.h"
  9. namespace bs
  10. {
  11. /** @addtogroup General
  12. * @{
  13. */
  14. /** Identifier that may be used for finding an element in the octree. */
  15. class OctreeElementId
  16. {
  17. public:
  18. OctreeElementId()
  19. :node(nullptr), elementIdx(0)
  20. { }
  21. OctreeElementId(void* node, UINT32 elementIdx)
  22. :node(node), elementIdx(elementIdx)
  23. { }
  24. private:
  25. template<class, class>
  26. friend class Octree;
  27. void* node;
  28. UINT32 elementIdx;
  29. };
  30. /**
  31. * Spatial partitioning tree for 3D space.
  32. *
  33. * @tparam ElemType Type of elements to be stored in the tree.
  34. * @tparam Options Class that controls various options of the tree. It must provide the following enums:
  35. * - LoosePadding: Denominator used to determine how much padding to add to each child node.
  36. * The extra padding percent is determined as (1.0f / LoosePadding). Larger
  37. * padding ensures elements are less likely to get stuck on a higher node
  38. * due to them straddling the boundary between the nodes.
  39. * - MinElementsPerNode: Determines at which point should node's children be removed and moved
  40. * back into the parent (node is collapsed). This can occurr on element
  41. * removal, when the element count drops below the specified number.
  42. * - MaxElementsPerNode: Determines at which point should a node be split into child nodes.
  43. * If an element counter moves past this number the elements will be
  44. * added to child nodes, if possible. If a node is already at maximum
  45. * depth, this is ignored.
  46. * - MaxDepth: Maximum depth of nodes in the tree. Nodes at this depth will not be subdivided
  47. * even if they element counts go past MaxElementsPerNode.
  48. * It must also provide the following methods:
  49. * - "static simd::AABox getBounds(const ElemType&, void*)"
  50. * - Returns the bounds for the provided element
  51. * - "static void setElementId(const Octree::ElementId&, void*)"
  52. * - Gets called when element's ID is first assigned or subsequentily modified
  53. */
  54. template<class ElemType, class Options>
  55. class Octree
  56. {
  57. /**
  58. * A sequential group of elements within a node. If number of elements exceeds the limit of the group multiple
  59. * groups will be linked together in a linked list fashion.
  60. */
  61. struct ElementGroup
  62. {
  63. ElemType v[Options::MaxElementsPerNode];
  64. ElementGroup* next = nullptr;
  65. };
  66. /**
  67. * A sequential group of element bounds within a node. If number of elements exceeds the limit of the group multiple
  68. * groups will be linked together in a linked list fashion.
  69. */
  70. struct ElementBoundGroup
  71. {
  72. simd::AABox v[Options::MaxElementsPerNode];
  73. ElementBoundGroup* next = nullptr;
  74. };
  75. /** Container class for all elements (and their bounds) within a single node. */
  76. struct NodeElements
  77. {
  78. ElementGroup* values = nullptr;
  79. ElementBoundGroup* bounds = nullptr;
  80. UINT32 count = 0;
  81. };
  82. public:
  83. /** Contains a reference to one of the eight child nodes in an octree node. */
  84. struct HChildNode
  85. {
  86. union
  87. {
  88. struct
  89. {
  90. UINT32 x : 1;
  91. UINT32 y : 1;
  92. UINT32 z : 1;
  93. UINT32 empty : 1;
  94. };
  95. UINT32 index : 3;
  96. };
  97. HChildNode()
  98. :empty(true)
  99. { }
  100. HChildNode(UINT32 x, UINT32 y, UINT32 z)
  101. :x(x), y(y), z(z), empty(false)
  102. { }
  103. HChildNode(UINT32 index)
  104. :index(index)
  105. {
  106. empty = false;
  107. }
  108. };
  109. /** Contains a range of child nodes in an octree node. */
  110. struct NodeChildRange
  111. {
  112. union
  113. {
  114. struct
  115. {
  116. UINT32 posX : 1;
  117. UINT32 posY : 1;
  118. UINT32 posZ : 1;
  119. UINT32 negX : 1;
  120. UINT32 negY : 1;
  121. UINT32 negZ : 1;
  122. };
  123. struct
  124. {
  125. UINT32 posBits : 3;
  126. UINT32 negBits : 3;
  127. };
  128. UINT32 allBits : 6;
  129. };
  130. /** Constructs a range overlapping no nodes. */
  131. NodeChildRange()
  132. :allBits(0)
  133. { }
  134. /** Constructs a range overlapping a single node. */
  135. NodeChildRange(HChildNode child)
  136. :posBits(child.index), negBits(~child.index)
  137. { }
  138. /** Checks if the range contains the provided child. */
  139. bool contains(HChildNode child)
  140. {
  141. NodeChildRange childRange(child);
  142. return (allBits & childRange.allBits) == childRange.allBits;
  143. }
  144. };
  145. /** Represents a single octree node. */
  146. class Node
  147. {
  148. public:
  149. /** Constructs a new leaf node with the specified parent. */
  150. Node(Node* parent)
  151. :mParent(parent), mTotalNumElements(0), mIsLeaf(true)
  152. {
  153. for(auto& entry : mChildren)
  154. entry = nullptr;
  155. }
  156. /** Returns a child node with the specified index. May return null. */
  157. Node* getChild(HChildNode child) const
  158. {
  159. return mChildren[child.index];
  160. }
  161. /** Checks has the specified child node been created. */
  162. bool hasChild(HChildNode child) const
  163. {
  164. return mChildren[child.index] != nullptr;
  165. }
  166. private:
  167. friend class ElementIterator;
  168. friend class Octree;
  169. /** Maps a global element index to a set of element groups and an index within those groups. */
  170. UINT32 mapToGroup(UINT32 elementIdx, ElementGroup** elements, ElementBoundGroup** bounds)
  171. {
  172. UINT32 numGroups = Math::divideAndRoundUp(mElements.count, (UINT32)Options::MaxElementsPerNode);
  173. UINT32 groupIdx = numGroups - elementIdx / Options::MaxElementsPerNode - 1;
  174. *elements = mElements.values;
  175. *bounds = mElements.bounds;
  176. for (UINT32 i = 0; i < groupIdx; i++)
  177. {
  178. *elements = (*elements)->next;
  179. *bounds = (*bounds)->next;
  180. }
  181. return elementIdx % Options::MaxElementsPerNode;
  182. }
  183. NodeElements mElements;
  184. Node* mParent;
  185. Node* mChildren[8];
  186. UINT32 mTotalNumElements : 31;
  187. UINT32 mIsLeaf : 1;
  188. };
  189. /**
  190. * Contains bounds for a specific node. This is necessary since the nodes themselves do not store bounds
  191. * information. Instead we construct it on-the-fly as we traverse the tree, using this class.
  192. */
  193. class NodeBounds
  194. {
  195. public:
  196. NodeBounds() = default;
  197. /** Initializes a new bounds object using the provided node bounds. */
  198. NodeBounds(const simd::AABox& bounds)
  199. :mBounds(bounds)
  200. {
  201. static constexpr float childExtentScale = 0.5f * (1.0f + 1.0f / Options::LoosePadding);
  202. mChildExtent = bounds.extents.x * childExtentScale;
  203. mChildOffset = bounds.extents.x - mChildExtent;
  204. }
  205. /** Returns the bounds of the node this object represents. */
  206. const simd::AABox& getBounds() const { return mBounds; }
  207. /** Attempts to find a child node that can fully contain the provided bounds. */
  208. HChildNode findContainingChild(const simd::AABox& bounds) const
  209. {
  210. auto queryCenter = simd::load<simd::float32x4>(&bounds.center);
  211. auto nodeCenter = simd::load<simd::float32x4>(&mBounds.center);
  212. auto childOffset = simd::load_splat<simd::float32x4>(&mChildOffset);
  213. auto negativeCenter = simd::sub(nodeCenter, childOffset);
  214. auto negativeDiff = simd::sub(queryCenter, negativeCenter);
  215. auto positiveCenter = simd::add(nodeCenter, childOffset);
  216. auto positiveDiff = simd::sub(positiveCenter, queryCenter);
  217. auto diff = simd::min(negativeDiff, positiveDiff);
  218. auto queryExtents = simd::load<simd::float32x4>(&bounds.extents);
  219. auto childExtent = simd::load_splat<simd::float32x4>(&mChildExtent);
  220. HChildNode output;
  221. simd::mask_float32x4 mask = simd::cmp_gt(simd::add(queryExtents, diff), childExtent);
  222. if(simd::test_bits_any(simd::bit_cast<simd::uint32x4>(mask)) == false)
  223. {
  224. auto ones = simd::make_uint<simd::uint32x4>(1, 1, 1, 1);
  225. auto zeroes = simd::make_uint<simd::uint32x4>(0, 0, 0, 0);
  226. // Find node closest to the query center
  227. mask = simd::cmp_gt(queryCenter, nodeCenter);
  228. auto result = simd::blend(ones, zeroes, mask);
  229. Vector4I scalarResult;
  230. simd::store(&scalarResult, result);
  231. output.x = scalarResult.x;
  232. output.y = scalarResult.y;
  233. output.z = scalarResult.z;
  234. output.empty = false;
  235. }
  236. return output;
  237. }
  238. /** Returns a range of child nodes that intersect the provided bounds. */
  239. NodeChildRange findIntersectingChildren(const simd::AABox& bounds) const
  240. {
  241. auto queryCenter = simd::load<simd::float32x4>(&bounds.center);
  242. auto queryExtents = simd::load<simd::float32x4>(&bounds.extents);
  243. auto queryMax = simd::add(queryCenter, queryExtents);
  244. auto queryMin = simd::sub(queryCenter, queryExtents);
  245. auto nodeCenter = simd::load<simd::float32x4>(&mBounds.center);
  246. auto childOffset = simd::load_splat<simd::float32x4>(&mChildOffset);
  247. auto negativeCenter = simd::sub(nodeCenter, childOffset);
  248. auto positiveCenter = simd::add(nodeCenter, childOffset);
  249. auto childExtent = simd::load_splat<simd::float32x4>(&mChildExtent);
  250. auto negativeMax = simd::add(negativeCenter, childExtent);
  251. auto positiveMin = simd::sub(positiveCenter, childExtent);
  252. NodeChildRange output;
  253. auto ones = simd::make_uint<simd::uint32x4>(1, 1, 1, 1);
  254. auto zeroes = simd::make_uint<simd::uint32x4>(0, 0, 0, 0);
  255. simd::mask_float32x4 mask = simd::cmp_gt(queryMax, positiveMin);
  256. simd::uint32x4 result = simd::blend(ones, zeroes, mask);
  257. Vector4I scalarResult;
  258. simd::store(&scalarResult, result);
  259. output.posX = scalarResult.x;
  260. output.posY = scalarResult.y;
  261. output.posZ = scalarResult.z;
  262. mask = simd::cmp_le(queryMin, negativeMax);
  263. result = simd::blend(ones, zeroes, mask);
  264. simd::store(&scalarResult, result);
  265. output.negX = scalarResult.x;
  266. output.negY = scalarResult.y;
  267. output.negZ = scalarResult.z;
  268. return output;
  269. }
  270. /** Calculates bounds for the provided child node. */
  271. NodeBounds getChild(HChildNode child) const
  272. {
  273. static constexpr float map[] = { -1.0f, 1.0f };
  274. return NodeBounds(
  275. simd::AABox(
  276. Vector3(
  277. mBounds.center.x + mChildOffset * map[child.x],
  278. mBounds.center.y + mChildOffset * map[child.y],
  279. mBounds.center.z + mChildOffset * map[child.z]
  280. ),
  281. mChildExtent
  282. )
  283. );
  284. }
  285. private:
  286. simd::AABox mBounds;
  287. float mChildExtent;
  288. float mChildOffset;
  289. };
  290. /** Contains a reference to a specific octree node, as well as information about its bounds. */
  291. class HNode
  292. {
  293. public:
  294. HNode()
  295. :mNode(nullptr)
  296. { }
  297. HNode(const Node* node, const NodeBounds& bounds)
  298. :mNode(node), mBounds(bounds)
  299. { }
  300. /** Returns the referenced node. */
  301. const Node* getNode() const { return mNode; }
  302. /** Returns the node bounds. */
  303. const NodeBounds& getBounds() const { return mBounds; }
  304. private:
  305. const Node* mNode;
  306. NodeBounds mBounds;
  307. };
  308. /**
  309. * Iterator that iterates over octree nodes. By default only the first inserted node will be iterated over and it
  310. * is up the the user to add new ones using pushChild(). The iterator takes care of updating the node bounds
  311. * accordingly.
  312. */
  313. class NodeIterator
  314. {
  315. public:
  316. /** Initializes the iterator, starting with the root octree node. */
  317. NodeIterator(const Octree& tree)
  318. :mCurrentNode(HNode(&tree.mRoot, tree.mRootBounds)), mStackAlloc(), mNodeStack(&mStackAlloc)
  319. {
  320. mNodeStack.push_back(mCurrentNode);
  321. }
  322. /** Initializes the iterator using a specific node and its bounds. */
  323. NodeIterator(const Node* node, const NodeBounds& bounds)
  324. :mCurrentNode(HNode(node, bounds)), mStackAlloc(), mNodeStack(&mStackAlloc)
  325. {
  326. mNodeStack.push_back(mCurrentNode);
  327. }
  328. /**
  329. * Returns a reference to the current node. moveNext() must be called at least once and it must return true
  330. * prior to attempting to access this data.
  331. */
  332. const HNode& getCurrent() const { return mCurrentNode; }
  333. /**
  334. * Moves to the next entry in the iterator. Iterator starts at a position before the first element, therefore
  335. * this method must be called at least once before attempting to access the current node. If the method returns
  336. * false it means the iterator end has been reached and attempting to access data will result in an error.
  337. */
  338. bool moveNext()
  339. {
  340. if(mNodeStack.empty())
  341. {
  342. mCurrentNode = HNode();
  343. return false;
  344. }
  345. mCurrentNode = mNodeStack.back();
  346. mNodeStack.erase(mNodeStack.end() - 1);
  347. return true;
  348. }
  349. /** Inserts a child of the current node to be iterated over. */
  350. void pushChild(const HChildNode& child)
  351. {
  352. Node* childNode = mCurrentNode.getNode()->getChild(child);
  353. NodeBounds childBounds = mCurrentNode.getBounds().getChild(child);
  354. mNodeStack.emplace_back(childNode, childBounds);
  355. }
  356. private:
  357. HNode mCurrentNode;
  358. StaticAlloc<Options::MaxDepth * 8 * sizeof(HNode), FreeAlloc> mStackAlloc;
  359. StaticVector<HNode, Options::MaxDepth * 8> mNodeStack;
  360. };
  361. /** Iterator that iterates over all elements in a single node. */
  362. class ElementIterator
  363. {
  364. public:
  365. ElementIterator()
  366. : mCurrentIdx(-1), mCurrentElemGroup(nullptr), mCurrentBoundGroup(nullptr)
  367. { }
  368. /** Constructs an iterator that iterates over the specified node's elements. */
  369. ElementIterator(const Node* node)
  370. : mCurrentIdx(-1)
  371. , mCurrentElemGroup(node->mElements.values)
  372. , mCurrentBoundGroup(node->mElements.bounds)
  373. {
  374. UINT32 numGroups = Math::divideAndRoundUp(node->mElements.count, (UINT32)Options::MaxElementsPerNode);
  375. mElemsInGroup = node->mElements.count - (numGroups - 1) * Options::MaxElementsPerNode;
  376. }
  377. /**
  378. * Moves to the next element in the node. Iterator starts at a position before the first element, therefore
  379. * this method must be called at least once before attempting to access the current element data. If the method
  380. * returns false it means iterator end has been reached and attempting to access data will result in an error.
  381. */
  382. bool moveNext()
  383. {
  384. if(!mCurrentElemGroup)
  385. return false;
  386. mCurrentIdx++;
  387. if(mCurrentIdx == mElemsInGroup) // Next group
  388. {
  389. mCurrentElemGroup = mCurrentElemGroup->next;
  390. mCurrentBoundGroup = mCurrentBoundGroup->next;
  391. mElemsInGroup = Options::MaxElementsPerNode; // Following groups are always full
  392. mCurrentIdx = 0;
  393. if(!mCurrentElemGroup)
  394. return false;
  395. }
  396. return true;
  397. }
  398. /**
  399. * Returns the bounds of the current element. moveNext() must be called at least once and it must return true
  400. * prior to attempting to access this data.
  401. */
  402. const simd::AABox& getCurrentBounds() const { return mCurrentBoundGroup->v[mCurrentIdx]; }
  403. /**
  404. * Returns the contents of the current element. moveNext() must be called at least once and it must return true
  405. * prior to attempting to access this data.
  406. */
  407. const ElemType& getCurrentElem() const { return mCurrentElemGroup->v[mCurrentIdx]; }
  408. private:
  409. INT32 mCurrentIdx;
  410. ElementGroup* mCurrentElemGroup;
  411. ElementBoundGroup* mCurrentBoundGroup;
  412. UINT32 mElemsInGroup;
  413. };
  414. /** Iterators that iterates over all elements intersecting the specified AABox. */
  415. class BoxIntersectIterator
  416. {
  417. public:
  418. /**
  419. * Constructs an iterator that iterates over all elements in the specified tree that intersect the specified
  420. * bounds.
  421. */
  422. BoxIntersectIterator(const Octree& tree, const AABox& bounds)
  423. :mNodeIter(tree), mBounds(simd::AABox(bounds))
  424. { }
  425. /**
  426. * Returns the contents of the current element. moveNext() must be called at least once and it must return true
  427. * prior to attempting to access this data.
  428. */
  429. const ElemType& getElement() const
  430. {
  431. return mElemIter.getCurrentElem();
  432. }
  433. /**
  434. * Moves to the next intersecting element. Iterator starts at a position before the first element, therefore
  435. * this method must be called at least once before attempting to access the current element data. If the method
  436. * returns false it means iterator end has been reached and attempting to access data will result in an error.
  437. */
  438. bool moveNext()
  439. {
  440. while(true)
  441. {
  442. // First check elements of the current node (if any)
  443. while (mElemIter.moveNext())
  444. {
  445. const simd::AABox& bounds = mElemIter.getCurrentBounds();
  446. if (bounds.intersects(mBounds))
  447. return true;
  448. }
  449. // No more elements in this node, move to the next one
  450. if(!mNodeIter.moveNext())
  451. return false; // No more nodes to check
  452. const HNode& nodeRef = mNodeIter.getCurrent();
  453. mElemIter = ElementIterator(nodeRef.getNode());
  454. // Add all intersecting child nodes to the iterator
  455. NodeChildRange childRange = nodeRef.getBounds().findIntersectingChildren(mBounds);
  456. for(UINT32 i = 0; i < 8; i++)
  457. {
  458. if(childRange.contains(i) && nodeRef.getNode()->hasChild(i))
  459. mNodeIter.pushChild(i);
  460. }
  461. }
  462. return false;
  463. }
  464. private:
  465. NodeIterator mNodeIter;
  466. ElementIterator mElemIter;
  467. simd::AABox mBounds;
  468. };
  469. /**
  470. * Constructs an octree with the specified bounds.
  471. *
  472. * @param[in] center Origin of the root node.
  473. * @param[in] extent Extent (half-size) of the root node in all directions;
  474. * @param[in] context Optional user context that will be passed along to getBounds() and setElementId()
  475. * methods on the provided Options class.
  476. */
  477. Octree(const Vector3& center, float extent, void* context = nullptr)
  478. : mRoot(nullptr)
  479. , mRootBounds(simd::AABox(center, extent))
  480. , mMinNodeExtent(extent * std::pow(0.5f * (1.0f + 1.0f / Options::LoosePadding), Options::MaxDepth))
  481. , mContext(context)
  482. {
  483. }
  484. ~Octree()
  485. {
  486. destroyNode(&mRoot);
  487. }
  488. /** Adds a new element to the octree. */
  489. void addElement(const ElemType& elem)
  490. {
  491. addElementToNode(elem, &mRoot, mRootBounds);
  492. }
  493. /** Removes an existing element from the octree. */
  494. void removeElement(const OctreeElementId& elemId)
  495. {
  496. Node* node = (Node*)elemId.node;
  497. popElement(node, elemId.elementIdx);
  498. // Reduce element counts in this and any parent nodes, check if nodes need collapsing
  499. Node* iterNode = node;
  500. Node* nodeToCollapse = nullptr;
  501. while(iterNode)
  502. {
  503. --iterNode->mTotalNumElements;
  504. if(iterNode->mTotalNumElements < Options::MinElementsPerNode)
  505. nodeToCollapse = iterNode;
  506. iterNode = iterNode->mParent;
  507. }
  508. if(nodeToCollapse)
  509. {
  510. // Add all the child node elements to the current node
  511. bs_frame_mark();
  512. {
  513. FrameStack<Node*> todo;
  514. todo.push(node);
  515. while(!todo.empty())
  516. {
  517. Node* curNode = todo.top();
  518. todo.pop();
  519. for(UINT32 i = 0; i < 8; i++)
  520. {
  521. if(curNode->hasChild(i))
  522. {
  523. Node* childNode = curNode->getChild(i);
  524. ElementIterator elemIter(childNode);
  525. while(elemIter.moveNext())
  526. pushElement(node, elemIter.getCurrentElem(), elemIter.getCurrentBounds());
  527. todo.push(childNode);
  528. }
  529. }
  530. }
  531. }
  532. bs_frame_clear();
  533. node->mIsLeaf = true;
  534. // Recursively delete all child nodes
  535. for (UINT32 i = 0; i < 8; i++)
  536. {
  537. if(node->mChildren[i])
  538. {
  539. destroyNode(node->mChildren[i]);
  540. mNodeAlloc.destruct(node->mChildren[i]);
  541. node->mChildren[i] = nullptr;
  542. }
  543. }
  544. }
  545. }
  546. private:
  547. /** Adds a new element to the specified node. Potentially also subdivides the node. */
  548. void addElementToNode(const ElemType& elem, Node* node, const NodeBounds& nodeBounds)
  549. {
  550. simd::AABox elemBounds = Options::getBounds(elem, mContext);
  551. ++node->mTotalNumElements;
  552. if (node->mIsLeaf)
  553. {
  554. const simd::AABox& bounds = nodeBounds.getBounds();
  555. // Check if the node has too many elements and should be broken up
  556. if ((node->mElements.count + 1) > Options::MaxElementsPerNode && bounds.extents.x > mMinNodeExtent)
  557. {
  558. // Clear all elements from the current node
  559. NodeElements elements = node->mElements;
  560. ElementIterator elemIter(node);
  561. node->mElements = NodeElements();
  562. // Mark the node as non-leaf, allowing children to be created
  563. node->mIsLeaf = false;
  564. node->mTotalNumElements = 0;
  565. // Re-insert all previous elements into this node (likely creating child nodes)
  566. while(elemIter.moveNext())
  567. addElementToNode(elemIter.getCurrentElem(), node, nodeBounds);
  568. // Free the element and bound groups from this node
  569. freeElements(elements);
  570. // Insert the current element
  571. addElementToNode(elem, node, nodeBounds);
  572. }
  573. else
  574. {
  575. // No need to sub-divide, just add the element to this node
  576. pushElement(node, elem, elemBounds);
  577. }
  578. }
  579. else
  580. {
  581. // Attempt to find a child the element fits into
  582. HChildNode child = nodeBounds.findContainingChild(elemBounds);
  583. if (child.empty)
  584. {
  585. // Element doesn't fit into a child, add it to this node
  586. pushElement(node, elem, elemBounds);
  587. }
  588. else
  589. {
  590. // Create the child node if needed, and add the element to it
  591. if (!node->mChildren[child.index])
  592. node->mChildren[child.index] = mNodeAlloc.template construct<Node>(node);
  593. addElementToNode(elem, node->mChildren[child.index], nodeBounds.getChild(child));
  594. }
  595. }
  596. }
  597. /** Cleans up memory used by the provided node. Should be called instead of the node destructor. */
  598. void destroyNode(Node* node)
  599. {
  600. freeElements(node->mElements);
  601. for (auto& entry : node->mChildren)
  602. {
  603. if (entry != nullptr)
  604. {
  605. destroyNode(entry);
  606. mNodeAlloc.destruct(entry);
  607. }
  608. }
  609. }
  610. /** Adds a new element to the node's element list. */
  611. void pushElement(Node* node, const ElemType& elem, const simd::AABox& bounds)
  612. {
  613. NodeElements& elements = node->mElements;
  614. UINT32 freeIdx = elements.count % Options::MaxElementsPerNode;
  615. if(freeIdx == 0) // New group needed
  616. {
  617. ElementGroup* elementGroup = (ElementGroup*)mElemAlloc.template construct<ElementGroup>();
  618. ElementBoundGroup* boundGroup = (ElementBoundGroup*)mElemBoundsAlloc.template construct<ElementBoundGroup>();
  619. elementGroup->next = elements.values;
  620. boundGroup->next = elements.bounds;
  621. elements.values = elementGroup;
  622. elements.bounds = boundGroup;
  623. }
  624. elements.values->v[freeIdx] = elem;
  625. elements.bounds->v[freeIdx] = bounds;
  626. UINT32 elementIdx = elements.count;
  627. Options::setElementId(elem, OctreeElementId(node, elementIdx), mContext);
  628. ++elements.count;
  629. }
  630. /** Removes the specified element from the node's element list. */
  631. void popElement(Node* node, UINT32 elementIdx)
  632. {
  633. NodeElements& elements = node->mElements;
  634. ElementGroup* elemGroup;
  635. ElementBoundGroup* boundGroup;
  636. elementIdx = node->mapToGroup(elementIdx, &elemGroup, &boundGroup);
  637. ElementGroup* lastElemGroup;
  638. ElementBoundGroup* lastBoundGroup;
  639. UINT32 lastElementIdx = node->mapToGroup(elements.count - 1, &lastElemGroup, &lastBoundGroup);
  640. if(elements.count > 1)
  641. {
  642. std::swap(elemGroup->v[elementIdx], lastElemGroup->v[lastElementIdx]);
  643. std::swap(boundGroup->v[elementIdx], lastBoundGroup->v[lastElementIdx]);
  644. Options::setElementId(elemGroup->v[elementIdx], OctreeElementId(node, elementIdx), mContext);
  645. }
  646. if(lastElementIdx == 0) // Last element in that group, remove it completely
  647. {
  648. elements.values = lastElemGroup->next;
  649. elements.bounds = lastBoundGroup->next;
  650. mElemAlloc.destruct(lastElemGroup);
  651. mElemBoundsAlloc.destruct(lastBoundGroup);
  652. }
  653. --elements.count;
  654. }
  655. /** Clears all elements from a node. */
  656. void freeElements(NodeElements& elements)
  657. {
  658. // Free the element and bound groups from this node
  659. ElementGroup* curElemGroup = elements.values;
  660. while (curElemGroup)
  661. {
  662. ElementGroup* toDelete = curElemGroup;
  663. curElemGroup = curElemGroup->next;
  664. mElemAlloc.destruct(toDelete);
  665. }
  666. ElementBoundGroup* curBoundGroup = elements.bounds;
  667. while (curBoundGroup)
  668. {
  669. ElementBoundGroup* toDelete = curBoundGroup;
  670. curBoundGroup = curBoundGroup->next;
  671. mElemBoundsAlloc.destruct(toDelete);
  672. }
  673. elements.values = nullptr;
  674. elements.bounds = nullptr;
  675. elements.count = 0;
  676. }
  677. Node mRoot;
  678. NodeBounds mRootBounds;
  679. float mMinNodeExtent;
  680. void* mContext;
  681. PoolAlloc<sizeof(Node)> mNodeAlloc;
  682. PoolAlloc<sizeof(ElementGroup)> mElemAlloc;
  683. PoolAlloc<sizeof(ElementBoundGroup), 512, 16> mElemBoundsAlloc;
  684. };
  685. /** @} */
  686. }