PageRenderTime 62ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmath/llvolumeoctree.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 256 lines | 171 code | 50 blank | 35 comment | 24 complexity | 445b2a5470c559fd5afcd02590f697c0 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvolumeoctree.cpp
  3. *
  4. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  5. * Second Life Viewer Source Code
  6. * Copyright (C) 2010, Linden Research, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation;
  11. * version 2.1 of the License only.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  23. * $/LicenseInfo$
  24. */
  25. #include "llvolumeoctree.h"
  26. #include "llvector4a.h"
  27. BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size)
  28. {
  29. LLVector4a fAWdU;
  30. LLVector4a dir;
  31. LLVector4a diff;
  32. dir.setSub(end, start);
  33. dir.mul(0.5f);
  34. diff.setAdd(end,start);
  35. diff.mul(0.5f);
  36. diff.sub(center);
  37. fAWdU.setAbs(dir);
  38. LLVector4a rhs;
  39. rhs.setAdd(size, fAWdU);
  40. LLVector4a lhs;
  41. lhs.setAbs(diff);
  42. U32 grt = lhs.greaterThan(rhs).getGatheredBits();
  43. if (grt & 0x7)
  44. {
  45. return false;
  46. }
  47. LLVector4a f;
  48. f.setCross3(dir, diff);
  49. f.setAbs(f);
  50. LLVector4a v0, v1;
  51. v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1));
  52. v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2));
  53. lhs.setMul(v0, v1);
  54. v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2));
  55. v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1));
  56. rhs.setMul(v0, v1);
  57. rhs.add(lhs);
  58. grt = f.greaterThan(rhs).getGatheredBits();
  59. return (grt & 0x7) ? false : true;
  60. }
  61. LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node)
  62. {
  63. node->addListener(this);
  64. }
  65. LLVolumeOctreeListener::~LLVolumeOctreeListener()
  66. {
  67. }
  68. void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTriangle>* parent,
  69. LLOctreeNode<LLVolumeTriangle>* child)
  70. {
  71. new LLVolumeOctreeListener(child);
  72. }
  73. LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
  74. const LLVolumeFace* face, F32* closest_t,
  75. LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
  76. : mFace(face),
  77. mStart(start),
  78. mDir(dir),
  79. mIntersection(intersection),
  80. mTexCoord(tex_coord),
  81. mNormal(normal),
  82. mBinormal(bi_normal),
  83. mClosestT(closest_t),
  84. mHitFace(false)
  85. {
  86. mEnd.setAdd(mStart, mDir);
  87. }
  88. void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>* node)
  89. {
  90. LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0);
  91. /*const F32* start = mStart.getF32();
  92. const F32* end = mEnd.getF32();
  93. const F32* center = vl->mBounds[0].getF32();
  94. const F32* size = vl->mBounds[1].getF32();*/
  95. //if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1]))
  96. if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr()))
  97. {
  98. node->accept(this);
  99. for (S32 i = 0; i < node->getChildCount(); ++i)
  100. {
  101. traverse(node->getChild(i));
  102. }
  103. }
  104. }
  105. void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle>* node)
  106. {
  107. for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter =
  108. node->getData().begin(); iter != node->getData().end(); ++iter)
  109. {
  110. const LLVolumeTriangle* tri = *iter;
  111. F32 a, b, t;
  112. if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2],
  113. mStart, mDir, a, b, t))
  114. {
  115. if ((t >= 0.f) && // if hit is after start
  116. (t <= 1.f) && // and before end
  117. (t < *mClosestT)) // and this hit is closer
  118. {
  119. *mClosestT = t;
  120. mHitFace = true;
  121. if (mIntersection != NULL)
  122. {
  123. LLVector4a intersect = mDir;
  124. intersect.mul(*mClosestT);
  125. intersect.add(mStart);
  126. mIntersection->set(intersect.getF32ptr());
  127. }
  128. if (mTexCoord != NULL)
  129. {
  130. LLVector2* tc = (LLVector2*) mFace->mTexCoords;
  131. *mTexCoord = ((1.f - a - b) * tc[tri->mIndex[0]] +
  132. a * tc[tri->mIndex[1]] +
  133. b * tc[tri->mIndex[2]]);
  134. }
  135. if (mNormal != NULL)
  136. {
  137. LLVector4* norm = (LLVector4*) mFace->mNormals;
  138. *mNormal = ((1.f - a - b) * LLVector3(norm[tri->mIndex[0]]) +
  139. a * LLVector3(norm[tri->mIndex[1]]) +
  140. b * LLVector3(norm[tri->mIndex[2]]));
  141. }
  142. if (mBinormal != NULL)
  143. {
  144. LLVector4* binormal = (LLVector4*) mFace->mBinormals;
  145. *mBinormal = ((1.f - a - b) * LLVector3(binormal[tri->mIndex[0]]) +
  146. a * LLVector3(binormal[tri->mIndex[1]]) +
  147. b * LLVector3(binormal[tri->mIndex[2]]));
  148. }
  149. }
  150. }
  151. }
  152. }
  153. const LLVector4a& LLVolumeTriangle::getPositionGroup() const
  154. {
  155. return mPositionGroup;
  156. }
  157. const F32& LLVolumeTriangle::getBinRadius() const
  158. {
  159. return mRadius;
  160. }
  161. //TEST CODE
  162. void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch)
  163. {
  164. LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0);
  165. //make sure bounds matches extents
  166. LLVector4a& min = node->mExtents[0];
  167. LLVector4a& max = node->mExtents[1];
  168. LLVector4a& center = node->mBounds[0];
  169. LLVector4a& size = node->mBounds[1];
  170. LLVector4a test_min, test_max;
  171. test_min.setSub(center, size);
  172. test_max.setAdd(center, size);
  173. if (!test_min.equals3(min, 0.001f) ||
  174. !test_max.equals3(max, 0.001f))
  175. {
  176. llerrs << "Bad bounding box data found." << llendl;
  177. }
  178. test_min.sub(LLVector4a(0.001f));
  179. test_max.add(LLVector4a(0.001f));
  180. for (U32 i = 0; i < branch->getChildCount(); ++i)
  181. {
  182. LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0);
  183. //make sure all children fit inside this node
  184. if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) ||
  185. child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ))
  186. {
  187. llerrs << "Child protrudes from bounding box." << llendl;
  188. }
  189. }
  190. //children fit, check data
  191. for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getData().begin();
  192. iter != branch->getData().end(); ++iter)
  193. {
  194. const LLVolumeTriangle* tri = *iter;
  195. //validate triangle
  196. for (U32 i = 0; i < 3; i++)
  197. {
  198. if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) ||
  199. tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ))
  200. {
  201. llerrs << "Triangle protrudes from node." << llendl;
  202. }
  203. }
  204. }
  205. }