triBoxCheck.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //-----------------------------------------------------------------------------
  23. // AABB-triangle overlap test code originally by Tomas Akenine-Möller
  24. // Assisted by Pierre Terdiman and David Hunt
  25. // http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/
  26. // Ported to TSE by BJG, 2005-4-14
  27. // Modified to avoid a lot of copying by ASM, 2007-9-28
  28. //-----------------------------------------------------------------------------
  29. #include "util/triBoxCheck.h"
  30. #define FINDMINMAX(x0,x1,x2,theMin,theMax) \
  31. theMin = theMax = x0; \
  32. if(x1<theMin) theMin=x1;\
  33. if(x1>theMax) theMax=x1;\
  34. if(x2<theMin) theMin=x2;\
  35. if(x2>theMax) theMax=x2;
  36. static bool planeBoxOverlap(const Point3F &normal, const Point3F &vert, const Point3F &maxbox)
  37. {
  38. S32 q;
  39. F32 v;
  40. Point3F vmin, vmax;
  41. for(q=0;q<=2;q++)
  42. {
  43. v=vert[q];
  44. if(normal[q]>0.0f)
  45. {
  46. vmin[q]=-maxbox[q] - v;
  47. vmax[q]= maxbox[q] - v;
  48. }
  49. else
  50. {
  51. vmin[q]= maxbox[q] - v;
  52. vmax[q]=-maxbox[q] - v;
  53. }
  54. }
  55. if(mDot(normal, vmin) > 0.f)
  56. return false;
  57. if(mDot(normal, vmax) >= 0.f)
  58. return true;
  59. return false;
  60. }
  61. /*======================== X-tests ========================*/
  62. #define AXISTEST_X01(a, b, fa, fb) \
  63. p0 = a*v0.y - b*v0.z; \
  64. p2 = a*v2.y - b*v2.z; \
  65. if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
  66. rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
  67. if(min>rad || max<-rad) return false;
  68. #define AXISTEST_X2(a, b, fa, fb) \
  69. p0 = a*v0.y - b*v0.z; \
  70. p1 = a*v1.y - b*v1.z; \
  71. if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
  72. rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \
  73. if(min>rad || max<-rad) return false;
  74. /*======================== Y-tests ========================*/
  75. #define AXISTEST_Y02(a, b, fa, fb) \
  76. p0 = -a*v0.x + b*v0.z; \
  77. p2 = -a*v2.x + b*v2.z; \
  78. if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
  79. rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
  80. if(min>rad || max<-rad) return false;
  81. #define AXISTEST_Y1(a, b, fa, fb) \
  82. p0 = -a*v0.x + b*v0.z; \
  83. p1 = -a*v1.x + b*v1.z; \
  84. if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
  85. rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \
  86. if(min>rad || max<-rad) return false;
  87. /*======================== Z-tests ========================*/
  88. #define AXISTEST_Z12(a, b, fa, fb) \
  89. p1 = a*v1.x - b*v1.y; \
  90. p2 = a*v2.x - b*v2.y; \
  91. if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
  92. rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
  93. if(min>rad || max<-rad) return false;
  94. #define AXISTEST_Z0(a, b, fa, fb) \
  95. p0 = a*v0.x - b*v0.y; \
  96. p1 = a*v1.x - b*v1.y; \
  97. if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
  98. rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \
  99. if(min>rad || max<-rad) return false;
  100. bool triBoxOverlap(const Point3F &boxcenter, const Point3F &boxhalfsize, const Point3F triverts[3])
  101. {
  102. /* use separating axis theorem to test overlap between triangle and box */
  103. /* need to test for overlap in these directions: */
  104. /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
  105. /* we do not even need to test these) */
  106. /* 2) normal of the triangle */
  107. /* 3) crossproduct(edge from tri, {x,y,z}-directin) */
  108. /* this gives 3x3=9 more tests */
  109. Point3F v0,v1,v2;
  110. F32 min,max,p0,p1,p2,rad,fex,fey,fez; // -NJMP- "d" local variable removed
  111. Point3F normal,e0,e1,e2;
  112. /* This is the fastest branch on Sun */
  113. /* move everything so that the boxcenter is in (0,0,0) */
  114. v0 = triverts[0] - boxcenter;
  115. v1 = triverts[1] - boxcenter;
  116. v2 = triverts[2] - boxcenter;
  117. /* compute triangle edges */
  118. e0 = v1 - v0; /* tri edge 0 */
  119. e1 = v2 - v1; /* tri edge 1 */
  120. e2 = v0 - v2; /* tri edge 2 */
  121. /* Bullet 3: */
  122. /* test the 9 tests first (this was faster) */
  123. fex = mFabs(e0.x);
  124. fey = mFabs(e0.y);
  125. fez = mFabs(e0.z);
  126. AXISTEST_X01(e0.z, e0.y, fez, fey);
  127. AXISTEST_Y02(e0.z, e0.x, fez, fex);
  128. AXISTEST_Z12(e0.y, e0.x, fey, fex);
  129. fex = mFabs(e1.x);
  130. fey = mFabs(e1.y);
  131. fez = mFabs(e1.z);
  132. AXISTEST_X01(e1.z, e1.y, fez, fey);
  133. AXISTEST_Y02(e1.z, e1.x, fez, fex);
  134. AXISTEST_Z0(e1.y, e1.x, fey, fex);
  135. fex = mFabs(e2.x);
  136. fey = mFabs(e2.y);
  137. fez = mFabs(e2.z);
  138. AXISTEST_X2(e2.z, e2.y, fez, fey);
  139. AXISTEST_Y1(e2.z, e2.x, fez, fex);
  140. AXISTEST_Z12(e2.y, e2.x, fey, fex);
  141. /* Bullet 1: */
  142. /* first test overlap in the {x,y,z}-directions */
  143. /* find min, max of the triangle each direction, and test for overlap in */
  144. /* that direction -- this is equivalent to testing a minimal AABB around */
  145. /* the triangle against the AABB */
  146. /* test in X-direction */
  147. FINDMINMAX(v0.x,v1.x,v2.x,min,max);
  148. if(min>boxhalfsize.x || max<-boxhalfsize.x) return false;
  149. /* test in Y-direction */
  150. FINDMINMAX(v0.y,v1.y,v2.y,min,max);
  151. if(min>boxhalfsize.y || max<-boxhalfsize.y) return false;
  152. /* test in Z-direction */
  153. FINDMINMAX(v0.z,v1.z,v2.z,min,max);
  154. if(min>boxhalfsize.z || max<-boxhalfsize.z) return false;
  155. /* Bullet 2: */
  156. /* test if the box intersects the plane of the triangle */
  157. /* compute plane equation of triangle: normal*x+d=0 */
  158. normal = mCross(e0, e1);
  159. if(!planeBoxOverlap(normal,v0,boxhalfsize)) return false;
  160. return true; /* box and triangle overlaps */
  161. }