llvolumeoctree.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /**
  2. * @file llvolumeoctree.cpp
  3. *
  4. * $LicenseInfo:firstyear=2002&license=viewergpl$
  5. *
  6. * Copyright (c) 2002-2010, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #include "linden_common.h"
  32. #include "llvolumeoctree.h"
  33. bool LLLineSegmentBoxIntersect(const LLVector4a& start,
  34. const LLVector4a& end,
  35. const LLVector4a& center,
  36. const LLVector4a& size)
  37. {
  38. LLVector4a fAWdU;
  39. LLVector4a dir;
  40. LLVector4a diff;
  41. dir.setSub(end, start);
  42. dir.mul(0.5f);
  43. diff.setAdd(end,start);
  44. diff.mul(0.5f);
  45. diff.sub(center);
  46. fAWdU.setAbs(dir);
  47. LLVector4a rhs;
  48. rhs.setAdd(size, fAWdU);
  49. LLVector4a lhs;
  50. lhs.setAbs(diff);
  51. U32 grt = lhs.greaterThan(rhs).getGatheredBits();
  52. if (grt & 0x7)
  53. {
  54. return false;
  55. }
  56. LLVector4a f;
  57. f.setCross3(dir, diff);
  58. f.setAbs(f);
  59. LLVector4a v0, v1;
  60. v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3, 0, 0, 1));
  61. v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3, 1, 2, 2));
  62. lhs.setMul(v0, v1);
  63. v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3, 1, 2, 2));
  64. v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3, 0, 0, 1));
  65. rhs.setMul(v0, v1);
  66. rhs.add(lhs);
  67. grt = f.greaterThan(rhs).getGatheredBits();
  68. return (grt & 0x7) == 0;
  69. }
  70. template<typename T_PTR>
  71. _LLVolumeOctreeListener<T_PTR>::_LLVolumeOctreeListener(_LLOctreeNode<LLVolumeTriangle,
  72. T_PTR>* nodep)
  73. {
  74. if (nodep)
  75. {
  76. nodep->addListener(this);
  77. }
  78. }
  79. template<typename T_PTR>
  80. _LLVolumeOctreeListener<T_PTR>::~_LLVolumeOctreeListener()
  81. {
  82. }
  83. template<typename T_PTR>
  84. void _LLVolumeOctreeListener<T_PTR>::handleChildAddition(const _LLOctreeNode<LLVolumeTriangle,
  85. T_PTR>* parentp,
  86. _LLOctreeNode<LLVolumeTriangle,
  87. T_PTR>* childp)
  88. {
  89. new _LLVolumeOctreeListener<T_PTR>(childp);
  90. }
  91. template class _LLVolumeOctreeListener<LLVolumeTriangle*>;
  92. template class _LLVolumeOctreeListener<LLPointer<LLVolumeTriangle> >;
  93. template<typename T_PTR>
  94. _LLOctreeTriangleRayIntersect<T_PTR>::_LLOctreeTriangleRayIntersect(const LLVector4a& start,
  95. const LLVector4a& dir,
  96. LLVolumeFace* facep,
  97. F32* closest_tp,
  98. LLVector4a* intersectp,
  99. LLVector2* tcoordp,
  100. LLVector4a* normalp,
  101. LLVector4a* tangentp)
  102. : mFace(facep),
  103. mStart(start),
  104. mDir(dir),
  105. mIntersection(intersectp),
  106. mTexCoord(tcoordp),
  107. mNormal(normalp),
  108. mTangent(tangentp),
  109. mClosestT(closest_tp),
  110. mHitTriangle(NULL),
  111. mHitFace(false)
  112. {
  113. mEnd.setAdd(mStart, mDir);
  114. }
  115. template<typename T_PTR>
  116. void _LLOctreeTriangleRayIntersect<T_PTR>::traverse(const _LLOctreeNode<LLVolumeTriangle,
  117. T_PTR>* nodep)
  118. {
  119. if (!nodep) return;
  120. _LLVolumeOctreeListener<T_PTR>* vl =
  121. (_LLVolumeOctreeListener<T_PTR>*)nodep->getListener(0);
  122. if (vl && LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0],
  123. vl->mBounds[1]))
  124. {
  125. nodep->accept(this);
  126. for (U32 i = 0; i < nodep->getChildCount(); ++i)
  127. {
  128. traverse(nodep->getChild(i));
  129. }
  130. }
  131. }
  132. template<typename T_PTR>
  133. void _LLOctreeTriangleRayIntersect<T_PTR>::visit(const _LLOctreeNode<LLVolumeTriangle,
  134. T_PTR>* nodep)
  135. {
  136. if (!nodep) return;
  137. for (typename _LLOctreeNode<LLVolumeTriangle, T_PTR>::const_element_iter
  138. iter = nodep->getDataBegin();
  139. iter != nodep->getDataEnd(); ++iter)
  140. {
  141. const LLVolumeTriangle* trip = *iter;
  142. if (!trip) continue; // Paranoia ?
  143. F32 a, b, t;
  144. if (LLTriangleRayIntersect(*trip->mV[0], *trip->mV[1], *trip->mV[2],
  145. mStart, mDir, a, b, t))
  146. {
  147. if (t >= 0.f && // if hit is after start
  148. t <= 1.f && // and before end
  149. t < *mClosestT) // and this hit is closer
  150. {
  151. *mClosestT = t;
  152. mHitFace = true;
  153. mHitTriangle = trip;
  154. if (mIntersection)
  155. {
  156. LLVector4a intersect = mDir;
  157. intersect.mul(*mClosestT);
  158. intersect.add(mStart);
  159. *mIntersection = intersect;
  160. }
  161. U32 idx0 = trip->mIndex[0];
  162. U32 idx1 = trip->mIndex[1];
  163. U32 idx2 = trip->mIndex[2];
  164. if (mTexCoord && mFace->mTexCoords)
  165. {
  166. LLVector2* tc = (LLVector2*)mFace->mTexCoords;
  167. *mTexCoord = (1.f - a - b) * tc[idx0] + a * tc[idx1] +
  168. b * tc[idx2];
  169. }
  170. if (mNormal && mFace->mNormals)
  171. {
  172. LLVector4a* norm = mFace->mNormals;
  173. LLVector4a n1 = norm[idx0];
  174. n1.mul(1.f - a - b);
  175. LLVector4a n2 = norm[idx1];
  176. n2.mul(a);
  177. LLVector4a n3 = norm[idx2];
  178. n3.mul(b);
  179. n1.add(n2);
  180. n1.add(n3);
  181. *mNormal = n1;
  182. }
  183. if (mTangent && mFace->mTangents)
  184. {
  185. LLVector4a* tangents = mFace->mTangents;
  186. LLVector4a t1 = tangents[idx0];
  187. t1.mul(1.f - a - b);
  188. LLVector4a t2 = tangents[idx1];
  189. t2.mul(a);
  190. LLVector4a t3 = tangents[idx2];
  191. t3.mul(b);
  192. t1.add(t2);
  193. t1.add(t3);
  194. *mTangent = t1;
  195. }
  196. }
  197. }
  198. }
  199. }
  200. template class _LLOctreeTriangleRayIntersect<LLVolumeTriangle*>;
  201. template class _LLOctreeTriangleRayIntersect<LLPointer<LLVolumeTriangle> >;
  202. const LLVector4a& LLVolumeTriangle::getPositionGroup() const
  203. {
  204. return mPositionGroup;
  205. }
  206. const F32& LLVolumeTriangle::getBinRadius() const
  207. {
  208. return mRadius;
  209. }
  210. // TEST CODE
  211. template<typename T_PTR>
  212. void _LLVolumeOctreeValidate<T_PTR>::visit(const _LLOctreeNode<LLVolumeTriangle,
  213. T_PTR>* branchp)
  214. {
  215. if (!branchp) return;
  216. _LLVolumeOctreeListener<T_PTR>* nodep =
  217. (_LLVolumeOctreeListener<T_PTR>*)branchp->getListener(0);
  218. if (!nodep) return;
  219. // Make sure bounds matches extents
  220. LLVector4a& min = nodep->mExtents[0];
  221. LLVector4a& max = nodep->mExtents[1];
  222. LLVector4a& center = nodep->mBounds[0];
  223. LLVector4a& size = nodep->mBounds[1];
  224. LLVector4a test_min, test_max;
  225. test_min.setSub(center, size);
  226. test_max.setAdd(center, size);
  227. if (!test_min.equals3(min, 0.001f) || !test_max.equals3(max, 0.001f))
  228. {
  229. llerrs << "Bad bounding box data found." << llendl;
  230. }
  231. test_min.sub(LLVector4a(0.001f));
  232. test_max.add(LLVector4a(0.001f));
  233. for (U32 i = 0; i < branchp->getChildCount(); ++i)
  234. {
  235. _LLVolumeOctreeListener<T_PTR>* childp =
  236. (_LLVolumeOctreeListener<T_PTR>*)branchp->getChild(i)->getListener(0);
  237. if (!childp) continue;
  238. // Make sure all children fit inside this node
  239. if (childp->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) ||
  240. childp->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ))
  241. {
  242. llerrs << "Child protrudes from bounding box." << llendl;
  243. }
  244. }
  245. // Children fit, check data
  246. for (typename _LLOctreeNode<LLVolumeTriangle, T_PTR>::const_element_iter
  247. iter = branchp->getDataBegin();
  248. iter != branchp->getDataEnd(); ++iter)
  249. {
  250. const LLVolumeTriangle* trip = *iter;
  251. if (!trip) continue;
  252. // Validate triangle
  253. for (U32 i = 0; i < 3; i++)
  254. {
  255. if (trip->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) ||
  256. trip->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ))
  257. {
  258. llerrs << "Triangle protrudes from node." << llendl;
  259. }
  260. }
  261. }
  262. }
  263. template class _LLVolumeOctreeValidate<LLPointer<LLVolumeTriangle> >;
  264. template class _LLVolumeOctreeValidate<LLVolumeTriangle*>;