llvolumeoctree.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /**
  2. * @file llvolumeoctree.h
  3. * @brief LLVolume octree classes.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-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_LLVOLUME_OCTREE_H
  33. #define LL_LLVOLUME_OCTREE_H
  34. #include "lloctree.h"
  35. #include "llvolume.h"
  36. class alignas(16) LLVolumeTriangle : public LLRefCount
  37. {
  38. public:
  39. LL_VOLUME_AREANA_NEW_DELETE
  40. LLVolumeTriangle()
  41. {
  42. mBinIndex = -1;
  43. }
  44. LLVolumeTriangle(const LLVolumeTriangle& rhs)
  45. {
  46. *this = rhs;
  47. }
  48. const LLVolumeTriangle& operator=(const LLVolumeTriangle& rhs)
  49. {
  50. llerrs << "Illegal operation !" << llendl;
  51. return *this;
  52. }
  53. virtual const LLVector4a& getPositionGroup() const;
  54. virtual const F32& getBinRadius() const;
  55. S32 getBinIndex() const { return mBinIndex; }
  56. void setBinIndex(S32 idx) const { mBinIndex = idx; }
  57. public:
  58. // Note: before these variables, we find the 32 bits counter from
  59. // LLRefCount... Since mPositionGroup will be 16-bytes aligned, fill-up
  60. // the gap and align in the cache line with other member variables. HB
  61. F32 mRadius;
  62. const LLVector4a* mV[3];
  63. LLVector4a mPositionGroup;
  64. mutable S32 mBinIndex;
  65. U16 mIndex[3];
  66. };
  67. template <typename T_PTR>
  68. class alignas(16) _LLVolumeOctreeListener
  69. : public _LLOctreeListener<LLVolumeTriangle, T_PTR>
  70. {
  71. public:
  72. LL_VOLUME_AREANA_NEW_DELETE
  73. _LLVolumeOctreeListener(_LLOctreeNode<LLVolumeTriangle, T_PTR>* node);
  74. _LLVolumeOctreeListener(const _LLVolumeOctreeListener& rhs)
  75. {
  76. *this = rhs;
  77. }
  78. ~_LLVolumeOctreeListener() override;
  79. const _LLVolumeOctreeListener& operator=(const _LLVolumeOctreeListener&)
  80. {
  81. llerrs << "Illegal operation !" << llendl;
  82. return *this;
  83. }
  84. // LISTENER FUNCTIONS
  85. void handleChildAddition(const _LLOctreeNode<LLVolumeTriangle, T_PTR>* parent,
  86. _LLOctreeNode<LLVolumeTriangle, T_PTR>* child) override;
  87. void handleStateChange(const LLTreeNode<LLVolumeTriangle>* node) override
  88. {
  89. }
  90. void handleChildRemoval(const _LLOctreeNode<LLVolumeTriangle, T_PTR>* parent,
  91. const _LLOctreeNode<LLVolumeTriangle, T_PTR>* child) override
  92. {
  93. }
  94. void handleInsertion(const LLTreeNode<LLVolumeTriangle>* node,
  95. LLVolumeTriangle* tri) override
  96. {
  97. }
  98. void handleRemoval(const LLTreeNode<LLVolumeTriangle>* node,
  99. LLVolumeTriangle* tri) override
  100. {
  101. }
  102. void handleDestruction(const LLTreeNode<LLVolumeTriangle>* node) override
  103. {
  104. }
  105. public:
  106. // Bounding box (center, size) of this node and all its children (tight fit
  107. // to objects)
  108. alignas(16) LLVector4a mBounds[2];
  109. // Extents (min, max) of this node and all its children
  110. alignas(16) LLVector4a mExtents[2];
  111. };
  112. using LLVolumeOctreeListener = _LLVolumeOctreeListener<LLPointer<LLVolumeTriangle> >;
  113. using LLVolumeOctreeListenerNoOwnership = _LLVolumeOctreeListener<LLVolumeTriangle*>;
  114. template<typename T_PTR>
  115. class alignas(16) _LLOctreeTriangleRayIntersect
  116. : public _LLOctreeTraveler<LLVolumeTriangle, T_PTR>
  117. {
  118. public:
  119. _LLOctreeTriangleRayIntersect(const LLVector4a& start,
  120. const LLVector4a& dir,
  121. LLVolumeFace* face,
  122. F32* closest_t,
  123. LLVector4a* intersection,
  124. LLVector2* tex_coord,
  125. LLVector4a* normal,
  126. LLVector4a* tangent);
  127. void traverse(const _LLOctreeNode<LLVolumeTriangle, T_PTR>* node) override;
  128. void visit(const _LLOctreeNode<LLVolumeTriangle, T_PTR>* node) override;
  129. public:
  130. LLVector4a mStart;
  131. LLVector4a mDir;
  132. LLVector4a mEnd;
  133. LLVector4a* mIntersection;
  134. LLVector2* mTexCoord;
  135. LLVector4a* mNormal;
  136. LLVector4a* mTangent;
  137. F32* mClosestT;
  138. LLVolumeFace* mFace;
  139. const LLVolumeTriangle* mHitTriangle;
  140. bool mHitFace;
  141. };
  142. using LLOctreeTriangleRayIntersect = _LLOctreeTriangleRayIntersect<LLPointer<LLVolumeTriangle> >;
  143. using LLOctreeTriangleRayIntersectNoOwnership = _LLOctreeTriangleRayIntersect<LLVolumeTriangle*>;
  144. template <typename T_PTR>
  145. class _LLVolumeOctreeValidate
  146. : public _LLOctreeTraveler<LLVolumeTriangle, T_PTR>
  147. {
  148. void visit(const _LLOctreeNode<LLVolumeTriangle, T_PTR>* branch) override;
  149. };
  150. using LLVolumeOctreeValidate = _LLVolumeOctreeValidate<LLPointer<LLVolumeTriangle> >;
  151. using LLVolumeOctreeValidateNoOwnership = _LLVolumeOctreeValidate<LLVolumeTriangle*>;
  152. class LLVolumeOctreeRebound
  153. : public LLOctreeTravelerDepthFirstNoOwnership<LLVolumeTriangle>
  154. {
  155. protected:
  156. LOG_CLASS(LLVolumeOctreeRebound);
  157. public:
  158. LLVolumeOctreeRebound() = default;
  159. void visit(const LLOctreeNodeNoOwnership<LLVolumeTriangle>* branch) override
  160. {
  161. if (!branch) return; // Paranoia ?
  162. // This is a depth first traversal, so it's safe to assume all children
  163. // have complete bounding data
  164. LLVolumeOctreeListenerNoOwnership* node =
  165. (LLVolumeOctreeListenerNoOwnership*)branch->getListener(0);
  166. if (!node) return; // Paranoia ?
  167. LLVector4a& min = node->mExtents[0];
  168. LLVector4a& max = node->mExtents[1];
  169. if (!branch->isEmpty())
  170. {
  171. // Node has data, find AABB that binds data set
  172. const LLVolumeTriangle* tri = *(branch->getDataBegin());
  173. if (!tri)
  174. {
  175. llwarns << "NULL volume triangle found." << llendl;
  176. return;
  177. }
  178. // Initialize min/max to first available vertex
  179. min = *(tri->mV[0]);
  180. max = *(tri->mV[0]);
  181. // For each triangle in node stretch by triangles in node
  182. for (LLOctreeNodeNoOwnership<LLVolumeTriangle>::const_element_iter
  183. iter = branch->getDataBegin();
  184. iter != branch->getDataEnd(); ++iter)
  185. {
  186. tri = *iter;
  187. min.setMin(min, *tri->mV[0]);
  188. min.setMin(min, *tri->mV[1]);
  189. min.setMin(min, *tri->mV[2]);
  190. max.setMax(max, *tri->mV[0]);
  191. max.setMax(max, *tri->mV[1]);
  192. max.setMax(max, *tri->mV[2]);
  193. }
  194. }
  195. else if (branch->getChildCount())
  196. {
  197. // No data, but child nodes exist
  198. LLVolumeOctreeListenerNoOwnership* child =
  199. (LLVolumeOctreeListenerNoOwnership*)branch->getChild(0)->getListener(0);
  200. // Initialize min/max to extents of first child
  201. min = child->mExtents[0];
  202. max = child->mExtents[1];
  203. }
  204. else if (branch->isLeaf())
  205. {
  206. llwarns << "Empty leaf" << llendl;
  207. return;
  208. }
  209. for (S32 i = 0, count = branch->getChildCount(); i < count; ++i)
  210. {
  211. // Stretch by child extents
  212. LLVolumeOctreeListenerNoOwnership* child =
  213. (LLVolumeOctreeListenerNoOwnership*)branch->getChild(i)->getListener(0);
  214. min.setMin(min, child->mExtents[0]);
  215. max.setMax(max, child->mExtents[1]);
  216. }
  217. node->mBounds[0].setAdd(min, max);
  218. node->mBounds[0].mul(0.5f);
  219. node->mBounds[1].setSub(max, min);
  220. node->mBounds[1].mul(0.5f);
  221. }
  222. };
  223. class LLVolumeOctree : public LLOctreeRootNoOwnership<LLVolumeTriangle>,
  224. public LLRefCount
  225. {
  226. public:
  227. LL_INLINE LLVolumeOctree(const LLVector4a& center, const LLVector4a& size)
  228. : LLOctreeRootNoOwnership<LLVolumeTriangle>(center, size, NULL)
  229. {
  230. new LLVolumeOctreeListenerNoOwnership(this);
  231. }
  232. LL_INLINE LLVolumeOctree()
  233. : LLOctreeRootNoOwnership<LLVolumeTriangle>(LLVector4a::getZero(),
  234. LLVector4a(1.f, 1.f, 1.f),
  235. NULL)
  236. {
  237. new LLVolumeOctreeListenerNoOwnership(this);
  238. }
  239. };
  240. #endif