💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
12 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_GEOM_OCTREE_HPP
  20. #define ANTKEEPER_GEOM_OCTREE_HPP
  21. #include <cstdint>
  22. #include <limits>
  23. #include <type_traits>
  24. #include <unordered_set>
  25. #include <stack>
  26. namespace geom {
  27. /**
  28. * A general purpose (hashed) linear octree. Nodes are integer identifiers and no other data is stored in the octree.
  29. *
  30. * @tparam T Integer node type. Must be 16-bit, 32-bit, or 64-bit.
  31. *
  32. * @see http://codervil.blogspot.com/2015/10/octree-node-identifiers.html
  33. * @see https://geidav.wordpress.com/2014/08/18/advanced-octrees-2-node-representations/
  34. */
  35. template <class T>
  36. class octree
  37. {
  38. private:
  39. /// Compile-time calculation of the minimum bits required to represent `n` state changes.
  40. static constexpr T ceil_log2(T n);
  41. public:
  42. static_assert(std::is_integral<T>::value, "Node type must be integral.");
  43. static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Node type must be 16-bit, 32-bit, or 64-bit.");
  44. /// Maximum octree depth
  45. static constexpr T max_depth = (sizeof(T) == 2) ? 3 : (sizeof(T) == 4) ? 8 : 18;
  46. /// Number of bits in the node type
  47. static constexpr T node_bits = sizeof(T) * 8;
  48. /// Number of bits used to encode the depth of a node.
  49. static constexpr T depth_bits = ceil_log2(max_depth + 1);
  50. /// Number of bits used to encode the Morton code location a node.
  51. static constexpr T location_bits = (max_depth + 1) * 3;
  52. /// Integer node type.
  53. typedef T node_type;
  54. /// Root node which is always guaranteed to exist.
  55. static constexpr node_type root = 0;
  56. /**
  57. * Accesses nodes in their internal hashmap order.
  58. */
  59. struct unordered_iterator
  60. {
  61. inline unordered_iterator(const unordered_iterator& other): set_iterator(other.set_iterator) {};
  62. inline unordered_iterator& operator=(const unordered_iterator& other) { this->set_iterator = other.set_iterator; return *this; };
  63. inline unordered_iterator& operator++() { ++(this->set_iterator); return *this; };
  64. inline unordered_iterator& operator--() { --(this->set_iterator); return *this; };
  65. inline bool operator==(const unordered_iterator& other) const { return this->set_iterator == other.set_iterator; };
  66. inline bool operator!=(const unordered_iterator& other) const { return this->set_iterator != other.set_iterator; };
  67. inline const node_type& operator*() const { return *this->set_iterator; };
  68. private:
  69. friend class octree;
  70. inline explicit unordered_iterator(const typename std::unordered_set<node_type>::const_iterator& it): set_iterator(it) {};
  71. typename std::unordered_set<node_type>::const_iterator set_iterator;
  72. };
  73. /**
  74. * Accesses nodes in z-order. TODO: I think this can be done without a stack.
  75. */
  76. struct iterator
  77. {
  78. inline iterator(const iterator& other): octree(other.octree), stack(other.stack) {};
  79. inline iterator& operator=(const iterator& other) { this->octree = other.octree; this->stack = other.stack; return *this; };
  80. iterator& operator++();
  81. inline bool operator==(const iterator& other) const { return **this == *other; };
  82. inline bool operator!=(const iterator& other) const { return **this != *other; };
  83. inline const node_type& operator*() const { return stack.top(); };
  84. private:
  85. friend class octree;
  86. inline explicit iterator(const octree* octree, node_type node): octree(octree), stack({node}) {};
  87. const octree* octree;
  88. std::stack<node_type> stack;
  89. };
  90. /**
  91. * Returns the depth of a node.
  92. *
  93. * @param node Node.
  94. * @return Depth of the node.
  95. */
  96. static T depth(node_type node);
  97. /**
  98. * Returns the Morton code location of a node.
  99. *
  100. * @param node Node.
  101. * @return Morton code location of the node.
  102. */
  103. static T location(node_type node);
  104. /**
  105. * Returns the node at the given depth and location.
  106. *
  107. * @param depth Node depth.
  108. * @param location Node Morton code location.
  109. */
  110. static node_type node(T depth, T location);
  111. /**
  112. * Returns the ancestor of a node at the specified depth.
  113. *
  114. * @param node Node whose ancestor will be located.
  115. * @param depth Absolute depth of the ancestors.
  116. * @return Ancestral node.
  117. */
  118. static node_type ancestor(node_type node, T depth);
  119. /**
  120. * Returns the parent of a node.
  121. *
  122. * @param node Node.
  123. * @return Parent node.
  124. */
  125. static node_type parent(node_type node);
  126. /**
  127. * Returns the nth sibling of a node.
  128. *
  129. * @param node Node.
  130. * @param n Offset to next sibling. (Automatically wraps to 0..7)
  131. * @return Next sibling node.
  132. */
  133. static node_type sibling(node_type node, T n);
  134. /**
  135. * Returns the nth child of a node.
  136. *
  137. * @param node Parent node.
  138. * @param n Offset to the nth sibling of the first child node. (Automatically wraps to 0..7)
  139. * @return nth child node.
  140. */
  141. static node_type child(node_type node, T n);
  142. /**
  143. * Calculates the first common ancestor of two nodes.
  144. *
  145. * @param a First node.
  146. * @param b Second node.
  147. * @return First common ancestor of the two nodes.
  148. */
  149. static node_type common_ancestor(node_type a, node_type b);
  150. /// Creates an octree with a single root node.
  151. octree();
  152. /// Returns a z-order iterator to the root node.
  153. iterator begin() const;
  154. /// Returns a z-order iterator indicating the end of a traversal.
  155. iterator end() const;
  156. /// Returns an iterator to the specified node.
  157. iterator find(node_type node) const;
  158. /// Returns an unordered iterator indicating the beginning of a traversal.
  159. unordered_iterator unordered_begin() const;
  160. /// Returns an unordered iterator indicating the end of a traversal.
  161. unordered_iterator unordered_end() const;
  162. /**
  163. * Inserts a node and its siblings into the octree, creating its ancestors as necessary. Note: The root node is persistent and cannot be inserted.
  164. *
  165. * @param node Node to insert.
  166. */
  167. void insert(node_type node);
  168. /**
  169. * Erases a node along with its siblings and descendants. Note: The root node is persistent and cannot be erased.
  170. *
  171. * @param node Node to erase.
  172. */
  173. void erase(node_type node);
  174. /**
  175. * Erases all nodes except the root.
  176. */
  177. void clear();
  178. /// Returns `true` if the node exists in the octree, and `false` otherwise.
  179. bool exists(node_type node) const;
  180. /// Returns `true` if the node has no children, and `false` otherwise.
  181. bool is_leaf(node_type node) const;
  182. /// Returns the number of nodes in the octree.
  183. std::size_t size() const;
  184. private:
  185. /// Compile-time pow()
  186. static constexpr T pow(T x, T exponent);
  187. /// Count leading zeros
  188. static T clz(T x);
  189. std::unordered_set<node_type> nodes;
  190. };
  191. /**
  192. * Octree with a 16-bit node type and a maximum depth of `3`.
  193. */
  194. typedef octree<std::uint16_t> octree16;
  195. /**
  196. * Octree with a 32-bit node type and a maximum depth of `8`.
  197. */
  198. typedef octree<std::uint32_t> octree32;
  199. /**
  200. * Octree with a 64-bit node type and a maximum depth of `18`.
  201. */
  202. typedef octree<std::uint64_t> octree64;
  203. template <typename T>
  204. typename octree<T>::iterator& octree<T>::iterator::operator++()
  205. {
  206. // Get next node from top of stack
  207. node_type node = stack.top();
  208. stack.pop();
  209. // If the node has children
  210. if (!octree->is_leaf(node))
  211. {
  212. // Push first child onto the stack
  213. for (T i = 0; i < 8; ++i)
  214. stack.push(child(node, 7 - i));
  215. }
  216. if (stack.empty())
  217. stack.push(std::numeric_limits<T>::max());
  218. return *this;
  219. }
  220. template <class T>
  221. constexpr T octree<T>::ceil_log2(T n)
  222. {
  223. return (n <= 1) ? 0 : ceil_log2((n + 1) / 2) + 1;
  224. }
  225. template <class T>
  226. inline T octree<T>::depth(node_type node)
  227. {
  228. // Extract depth using a bit mask
  229. constexpr T mask = pow(2, depth_bits) - 1;
  230. return node & mask;
  231. }
  232. template <class T>
  233. inline T octree<T>::location(node_type node)
  234. {
  235. return node >> ((node_bits - 1) - depth(node) * 3);
  236. }
  237. template <class T>
  238. inline typename octree<T>::node_type octree<T>::node(T depth, T location)
  239. {
  240. return (location << ((node_bits - 1) - depth * 3)) | depth;
  241. }
  242. template <class T>
  243. inline typename octree<T>::node_type octree<T>::ancestor(node_type node, T depth)
  244. {
  245. const T mask = std::numeric_limits<T>::max() << ((node_bits - 1) - depth * 3);
  246. return (node & mask) | depth;
  247. }
  248. template <class T>
  249. inline typename octree<T>::node_type octree<T>::parent(node_type node)
  250. {
  251. return ancestor(node, depth(node) - 1);
  252. }
  253. template <class T>
  254. inline typename octree<T>::node_type octree<T>::sibling(node_type node, T n)
  255. {
  256. T depth = octree::depth(node);
  257. T location = node >> ((node_bits - 1) - depth * 3);
  258. return octree::node(depth, (location & (~0b111)) | ((location + n) & 0b111));
  259. }
  260. template <class T>
  261. inline typename octree<T>::node_type octree<T>::child(node_type node, T n)
  262. {
  263. return sibling(node + 1, n);
  264. }
  265. template <class T>
  266. inline typename octree<T>::node_type octree<T>::common_ancestor(node_type a, node_type b)
  267. {
  268. T bits = std::min<T>(depth(a), depth(b)) * 3;
  269. T marker = (T(1) << (node_bits - 1)) >> bits;
  270. T depth = clz((a ^ b) | marker) / 3;
  271. return ancestor(a, depth);
  272. }
  273. template <class T>
  274. inline octree<T>::octree():
  275. nodes({0})
  276. {}
  277. template <class T>
  278. void octree<T>::insert(node_type node)
  279. {
  280. if (exists(node))
  281. return;
  282. // Insert node
  283. nodes.emplace(node);
  284. // Insert siblings
  285. for (T i = 1; i < 8; ++i)
  286. nodes.emplace(sibling(node, i));
  287. // Insert parent as necessary
  288. node_type parent = octree::parent(node);
  289. if (!exists(parent))
  290. insert(parent);
  291. }
  292. template <class T>
  293. void octree<T>::erase(node_type node)
  294. {
  295. // Don't erase the root!
  296. if (node == root)
  297. return;
  298. for (T i = 0; i < 8; ++i)
  299. {
  300. // Erase node
  301. nodes.erase(node);
  302. // Erase descendants
  303. if (!is_leaf(node))
  304. {
  305. for (T j = 0; j < 8; ++j)
  306. erase(child(node, j));
  307. }
  308. // Go to next sibling
  309. if (i < 7)
  310. node = sibling(node, i);
  311. }
  312. }
  313. template <class T>
  314. void octree<T>::clear()
  315. {
  316. nodes = {0};
  317. }
  318. template <class T>
  319. inline bool octree<T>::exists(node_type node) const
  320. {
  321. return (nodes.find(node) != nodes.end());
  322. }
  323. template <class T>
  324. inline bool octree<T>::is_leaf(node_type node) const
  325. {
  326. return !exists(child(node, 0));
  327. }
  328. template <class T>
  329. inline std::size_t octree<T>::size() const
  330. {
  331. return nodes.size();
  332. }
  333. template <class T>
  334. typename octree<T>::iterator octree<T>::begin() const
  335. {
  336. return iterator(this, octree::root);
  337. }
  338. template <class T>
  339. typename octree<T>::iterator octree<T>::end() const
  340. {
  341. return iterator(this, std::numeric_limits<T>::max());
  342. }
  343. template <class T>
  344. typename octree<T>::iterator octree<T>::find(node_type node) const
  345. {
  346. return exists(node) ? iterator(node) : end();
  347. }
  348. template <class T>
  349. typename octree<T>::unordered_iterator octree<T>::unordered_begin() const
  350. {
  351. return unordered_iterator(nodes.begin());
  352. }
  353. template <class T>
  354. typename octree<T>::unordered_iterator octree<T>::unordered_end() const
  355. {
  356. return unordered_iterator(nodes.end());
  357. }
  358. template <class T>
  359. constexpr T octree<T>::pow(T x, T exponent)
  360. {
  361. return (exponent == 0) ? 1 : x * pow(x, exponent - 1);
  362. }
  363. template <class T>
  364. T octree<T>::clz(T x)
  365. {
  366. if (!x)
  367. return sizeof(T) * 8;
  368. #if defined(__GNU__)
  369. return __builtin_clz(x);
  370. #else
  371. T n = 0;
  372. while ((x & (T(1) << (8 * sizeof(x) - 1))) == 0)
  373. {
  374. x <<= 1;
  375. ++n;
  376. }
  377. return n;
  378. #endif
  379. }
  380. } // namespace geom
  381. #endif // ANTKEEPER_GEOM_OCTREE_HPP