bvh_node_aabb.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "bvh_node_base.h"
  5. namespace embree
  6. {
  7. /*! BVHN AABBNode */
  8. template<typename NodeRef, int N>
  9. struct AABBNode_t : public BaseNode_t<NodeRef, N>
  10. {
  11. using BaseNode_t<NodeRef,N>::children;
  12. struct Create
  13. {
  14. __forceinline NodeRef operator() (const FastAllocator::CachedAllocator& alloc, size_t numChildren = 0) const
  15. {
  16. AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t),NodeRef::byteNodeAlignment); node->clear();
  17. return NodeRef::encodeNode(node);
  18. }
  19. };
  20. struct Set
  21. {
  22. __forceinline void operator() (NodeRef node, size_t i, NodeRef child, const BBox3fa& bounds) const {
  23. node.getAABBNode()->setRef(i,child);
  24. node.getAABBNode()->setBounds(i,bounds);
  25. }
  26. };
  27. struct Create2
  28. {
  29. template<typename BuildRecord>
  30. __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
  31. {
  32. AABBNode_t* node = (AABBNode_t*) alloc.malloc0(sizeof(AABBNode_t), NodeRef::byteNodeAlignment); node->clear();
  33. for (size_t i=0; i<num; i++) node->setBounds(i,children[i].bounds());
  34. return NodeRef::encodeNode(node);
  35. }
  36. };
  37. struct Set2
  38. {
  39. template<typename BuildRecord>
  40. __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
  41. {
  42. #if defined(DEBUG)
  43. // check that empty children are only at the end of the child list
  44. bool emptyChild = false;
  45. for (size_t i=0; i<num; i++) {
  46. emptyChild |= (children[i] == NodeRef::emptyNode);
  47. assert(emptyChild == (children[i] == NodeRef::emptyNode));
  48. }
  49. #endif
  50. AABBNode_t* node = ref.getAABBNode();
  51. for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
  52. return ref;
  53. }
  54. };
  55. struct Set3
  56. {
  57. Set3 (FastAllocator* allocator, PrimRef* prims)
  58. : allocator(allocator), prims(prims) {}
  59. template<typename BuildRecord>
  60. __forceinline NodeRef operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRef* children, const size_t num) const
  61. {
  62. #if defined(DEBUG)
  63. // check that empty children are only at the end of the child list
  64. bool emptyChild = false;
  65. for (size_t i=0; i<num; i++) {
  66. emptyChild |= (children[i] == NodeRef::emptyNode);
  67. assert(emptyChild == (children[i] == NodeRef::emptyNode));
  68. }
  69. #endif
  70. AABBNode_t* node = ref.getAABBNode();
  71. for (size_t i=0; i<num; i++) node->setRef(i,children[i]);
  72. if (unlikely(precord.alloc_barrier))
  73. {
  74. PrimRef* begin = &prims[precord.prims.begin()];
  75. PrimRef* end = &prims[precord.prims.end()]; // FIXME: extended end for spatial split builder!!!!!
  76. size_t bytes = (size_t)end - (size_t)begin;
  77. allocator->addBlock(begin,bytes);
  78. }
  79. return ref;
  80. }
  81. FastAllocator* const allocator;
  82. PrimRef* const prims;
  83. };
  84. /*! Clears the node. */
  85. __forceinline void clear() {
  86. lower_x = lower_y = lower_z = pos_inf;
  87. upper_x = upper_y = upper_z = neg_inf;
  88. BaseNode_t<NodeRef,N>::clear();
  89. }
  90. /*! Sets bounding box and ID of child. */
  91. __forceinline void setRef(size_t i, const NodeRef& ref) {
  92. assert(i < N);
  93. children[i] = ref;
  94. }
  95. /*! Sets bounding box of child. */
  96. __forceinline void setBounds(size_t i, const BBox3fa& bounds)
  97. {
  98. assert(i < N);
  99. lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
  100. upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
  101. }
  102. /*! Sets bounding box and ID of child. */
  103. __forceinline void set(size_t i, const NodeRef& ref, const BBox3fa& bounds) {
  104. setBounds(i,bounds);
  105. children[i] = ref;
  106. }
  107. /*! Returns bounds of node. */
  108. __forceinline BBox3fa bounds() const {
  109. const Vec3fa lower(reduce_min(lower_x),reduce_min(lower_y),reduce_min(lower_z));
  110. const Vec3fa upper(reduce_max(upper_x),reduce_max(upper_y),reduce_max(upper_z));
  111. return BBox3fa(lower,upper);
  112. }
  113. /*! Returns bounds of specified child. */
  114. __forceinline BBox3fa bounds(size_t i) const
  115. {
  116. assert(i < N);
  117. const Vec3fa lower(lower_x[i],lower_y[i],lower_z[i]);
  118. const Vec3fa upper(upper_x[i],upper_y[i],upper_z[i]);
  119. return BBox3fa(lower,upper);
  120. }
  121. /*! Returns extent of bounds of specified child. */
  122. __forceinline Vec3fa extend(size_t i) const {
  123. return bounds(i).size();
  124. }
  125. /*! Returns bounds of all children (implemented later as specializations) */
  126. __forceinline void bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const;
  127. /*! swap two children of the node */
  128. __forceinline void swap(size_t i, size_t j)
  129. {
  130. assert(i<N && j<N);
  131. std::swap(children[i],children[j]);
  132. std::swap(lower_x[i],lower_x[j]);
  133. std::swap(lower_y[i],lower_y[j]);
  134. std::swap(lower_z[i],lower_z[j]);
  135. std::swap(upper_x[i],upper_x[j]);
  136. std::swap(upper_y[i],upper_y[j]);
  137. std::swap(upper_z[i],upper_z[j]);
  138. }
  139. /*! swap the children of two nodes */
  140. __forceinline static void swap(AABBNode_t* a, size_t i, AABBNode_t* b, size_t j)
  141. {
  142. assert(i<N && j<N);
  143. std::swap(a->children[i],b->children[j]);
  144. std::swap(a->lower_x[i],b->lower_x[j]);
  145. std::swap(a->lower_y[i],b->lower_y[j]);
  146. std::swap(a->lower_z[i],b->lower_z[j]);
  147. std::swap(a->upper_x[i],b->upper_x[j]);
  148. std::swap(a->upper_y[i],b->upper_y[j]);
  149. std::swap(a->upper_z[i],b->upper_z[j]);
  150. }
  151. /*! compacts a node (moves empty children to the end) */
  152. __forceinline static void compact(AABBNode_t* a)
  153. {
  154. /* find right most filled node */
  155. ssize_t j=N;
  156. for (j=j-1; j>=0; j--)
  157. if (a->child(j) != NodeRef::emptyNode)
  158. break;
  159. /* replace empty nodes with filled nodes */
  160. for (ssize_t i=0; i<j; i++) {
  161. if (a->child(i) == NodeRef::emptyNode) {
  162. a->swap(i,j);
  163. for (j=j-1; j>i; j--)
  164. if (a->child(j) != NodeRef::emptyNode)
  165. break;
  166. }
  167. }
  168. }
  169. /*! Returns reference to specified child */
  170. __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
  171. __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
  172. /*! output operator */
  173. friend embree_ostream operator<<(embree_ostream o, const AABBNode_t& n)
  174. {
  175. o << "AABBNode { " << embree_endl;
  176. o << " lower_x " << n.lower_x << embree_endl;
  177. o << " upper_x " << n.upper_x << embree_endl;
  178. o << " lower_y " << n.lower_y << embree_endl;
  179. o << " upper_y " << n.upper_y << embree_endl;
  180. o << " lower_z " << n.lower_z << embree_endl;
  181. o << " upper_z " << n.upper_z << embree_endl;
  182. o << " children = ";
  183. for (size_t i=0; i<N; i++) o << n.children[i] << " ";
  184. o << embree_endl;
  185. o << "}" << embree_endl;
  186. return o;
  187. }
  188. public:
  189. vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
  190. vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
  191. vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
  192. vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
  193. vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
  194. vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
  195. };
  196. template<>
  197. __forceinline void AABBNode_t<NodeRefPtr<4>,4>::bounds(BBox<vfloat4>& bounds0, BBox<vfloat4>& bounds1, BBox<vfloat4>& bounds2, BBox<vfloat4>& bounds3) const {
  198. transpose(lower_x,lower_y,lower_z,vfloat4(zero),bounds0.lower,bounds1.lower,bounds2.lower,bounds3.lower);
  199. transpose(upper_x,upper_y,upper_z,vfloat4(zero),bounds0.upper,bounds1.upper,bounds2.upper,bounds3.upper);
  200. }
  201. }