mBox.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. #include "math/mMatrix.h"
  23. #include "math/mSphere.h"
  24. const Box3F Box3F::Invalid( F32_MAX, F32_MAX, F32_MAX, -F32_MAX, -F32_MAX, -F32_MAX );
  25. const Box3F Box3F::Max( -F32_MAX, -F32_MAX, -F32_MAX, F32_MAX, F32_MAX, F32_MAX );
  26. const Box3F Box3F::Zero( 0, 0, 0, 0, 0, 0 );
  27. //-----------------------------------------------------------------------------
  28. bool Box3F::isOverlapped( const SphereF& sphere ) const
  29. {
  30. // Algorithm: Real-Time Rendering, Ed. 1, p323, 10.10.1 Sphere/Box Intersection
  31. F32 d = 0;
  32. for( U32 i = 0; i < 3; ++ i )
  33. if( sphere.center[ i ] < minExtents[ i ] )
  34. d = d + mSquared( sphere.center[ i ] - minExtents[ i ] );
  35. else if( sphere.center[ i ] > maxExtents[ i ] )
  36. d = d + mSquared( sphere.center[ i ] - maxExtents[ i ] );
  37. return !( d > mSquared( sphere.radius ) );
  38. }
  39. //-----------------------------------------------------------------------------
  40. bool Box3F::collideLine(const Point3F& start, const Point3F& end, F32* t, Point3F* n) const
  41. {
  42. // Collide against bounding box. Need at least this for the editor.
  43. F32 st,et;
  44. F32 fst = 0;
  45. F32 fet = 1;
  46. const F32* bmin = &minExtents.x;
  47. const F32* bmax = &maxExtents.x;
  48. const F32* si = &start.x;
  49. const F32* ei = &end.x;
  50. static const Point3F na[3] = { Point3F(1.0f, 0.0f, 0.0f), Point3F(0.0f, 1.0f, 0.0f), Point3F(0.0f, 0.0f, 1.0f) };
  51. Point3F finalNormal(0.0f, 0.0f, 0.0f);
  52. for (S32 i = 0; i < 3; i++) {
  53. bool n_neg = false;
  54. if (si[i] < ei[i]) {
  55. if (si[i] > bmax[i] || ei[i] < bmin[i])
  56. return false;
  57. F32 di = ei[i] - si[i];
  58. st = (si[i] < bmin[i]) ? (bmin[i] - si[i]) / di : 0.0f;
  59. et = (ei[i] > bmax[i]) ? (bmax[i] - si[i]) / di : 1.0f;
  60. n_neg = true;
  61. }
  62. else {
  63. if (ei[i] > bmax[i] || si[i] < bmin[i])
  64. return false;
  65. F32 di = ei[i] - si[i];
  66. st = (si[i] > bmax[i]) ? (bmax[i] - si[i]) / di : 0.0f;
  67. et = (ei[i] < bmin[i]) ? (bmin[i] - si[i]) / di : 1.0f;
  68. }
  69. if (st > fst) {
  70. fst = st;
  71. finalNormal = na[i];
  72. if ( n_neg )
  73. finalNormal.neg();
  74. }
  75. if (et < fet)
  76. fet = et;
  77. if (fet < fst)
  78. return false;
  79. }
  80. *t = fst;
  81. *n = finalNormal;
  82. return true;
  83. }
  84. //-----------------------------------------------------------------------------
  85. bool Box3F::collideLine(const Point3F& start, const Point3F& end) const
  86. {
  87. F32 t;
  88. Point3F normal;
  89. return collideLine(start, end, &t, &normal);
  90. }
  91. //-----------------------------------------------------------------------------
  92. bool Box3F::collideOrientedBox(const Point3F & bRadii, const MatrixF & toA) const
  93. {
  94. Point3F p;
  95. toA.getColumn(3,&p);
  96. Point3F aCenter = minExtents + maxExtents;
  97. aCenter *= 0.5f;
  98. p -= aCenter; // this essentially puts origin of toA target space on the center of the current box
  99. Point3F aRadii = maxExtents - minExtents;
  100. aRadii *= 0.5f;
  101. F32 absXX,absXY,absXZ;
  102. F32 absYX,absYY,absYZ;
  103. F32 absZX,absZY,absZZ;
  104. const F32 * f = toA;
  105. absXX = mFabs(f[0]);
  106. absYX = mFabs(f[1]);
  107. absZX = mFabs(f[2]);
  108. if (aRadii.x + bRadii.x * absXX + bRadii.y * absYX + bRadii.z * absZX - mFabs(p.x)<0.0f)
  109. return false;
  110. absXY = mFabs(f[4]);
  111. absYY = mFabs(f[5]);
  112. absZY = mFabs(f[6]);
  113. if (aRadii.y + bRadii.x * absXY + bRadii.y * absYY + bRadii.z * absZY - mFabs(p.y)<0.0f)
  114. return false;
  115. absXZ = mFabs(f[8]);
  116. absYZ = mFabs(f[9]);
  117. absZZ = mFabs(f[10]);
  118. if (aRadii.z + bRadii.x * absXZ + bRadii.y * absYZ + bRadii.z * absZZ - mFabs(p.z)<0.0f)
  119. return false;
  120. if (aRadii.x*absXX + aRadii.y*absXY + aRadii.z*absXZ + bRadii.x - mFabs(p.x*f[0] + p.y*f[4] + p.z*f[8])<0.0f)
  121. return false;
  122. if (aRadii.x*absYX + aRadii.y*absYY + aRadii.z*absYZ + bRadii.y - mFabs(p.x*f[1] + p.y*f[5] + p.z*f[9])<0.0f)
  123. return false;
  124. if (aRadii.x*absZX + aRadii.y*absZY + aRadii.z*absZZ + bRadii.z - mFabs(p.x*f[2] + p.y*f[6] + p.z*f[10])<0.0f)
  125. return false;
  126. if (mFabs(p.z*f[4] - p.y*f[8]) >
  127. aRadii.y * absXZ + aRadii.z * absXY +
  128. bRadii.y * absZX + bRadii.z * absYX)
  129. return false;
  130. if (mFabs(p.z*f[5] - p.y*f[9]) >
  131. aRadii.y * absYZ + aRadii.z * absYY +
  132. bRadii.x * absZX + bRadii.z * absXX)
  133. return false;
  134. if (mFabs(p.z*f[6] - p.y*f[10]) >
  135. aRadii.y * absZZ + aRadii.z * absZY +
  136. bRadii.x * absYX + bRadii.y * absXX)
  137. return false;
  138. if (mFabs(p.x*f[8] - p.z*f[0]) >
  139. aRadii.x * absXZ + aRadii.z * absXX +
  140. bRadii.y * absZY + bRadii.z * absYY)
  141. return false;
  142. if (mFabs(p.x*f[9] - p.z*f[1]) >
  143. aRadii.x * absYZ + aRadii.z * absYX +
  144. bRadii.x * absZY + bRadii.z * absXY)
  145. return false;
  146. if (mFabs(p.x*f[10] - p.z*f[2]) >
  147. aRadii.x * absZZ + aRadii.z * absZX +
  148. bRadii.x * absYY + bRadii.y * absXY)
  149. return false;
  150. if (mFabs(p.y*f[0] - p.x*f[4]) >
  151. aRadii.x * absXY + aRadii.y * absXX +
  152. bRadii.y * absZZ + bRadii.z * absYZ)
  153. return false;
  154. if (mFabs(p.y*f[1] - p.x*f[5]) >
  155. aRadii.x * absYY + aRadii.y * absYX +
  156. bRadii.x * absZZ + bRadii.z * absXZ)
  157. return false;
  158. if (mFabs(p.y*f[2] - p.x*f[6]) >
  159. aRadii.x * absZY + aRadii.y * absZX +
  160. bRadii.x * absYZ + bRadii.y * absXZ)
  161. return false;
  162. return true;
  163. }
  164. //-----------------------------------------------------------------------------
  165. Box3F Box3F::aroundPoints( const Point3F* points, U32 numPoints )
  166. {
  167. AssertFatal( points != NULL, "Box3F::aroundPoints - Receive a NULL pointer" );
  168. AssertFatal( numPoints >= 1, "Box3F::aroundPoints - Must have at least one point" );
  169. Box3F box;
  170. Point3F minPoint = points[ 0 ];
  171. Point3F maxPoint = points[ 0 ];
  172. for( U32 i = 1; i < numPoints; ++ i )
  173. for( U32 n = 0; n < 3; ++ n )
  174. {
  175. minPoint[ n ] = getMin( minPoint[ n ], points[ i ][ n ] );
  176. maxPoint[ n ] = getMax( maxPoint[ n ], points[ i ][ n ] );
  177. }
  178. return Box3F( minPoint, maxPoint );
  179. }
  180. //-----------------------------------------------------------------------------
  181. Point3F Box3F::computeVertex( U32 corner ) const
  182. {
  183. AssertFatal( corner < NUM_POINTS, "Box3F::computeVertex - Index out of range" );
  184. switch( corner )
  185. {
  186. case NearBottomLeft: return Point3F( minExtents.x, minExtents.y, minExtents.z );
  187. case NearTopLeft: return Point3F( minExtents.x, minExtents.y, maxExtents.z );
  188. case NearTopRight: return Point3F( maxExtents.x, minExtents.y, maxExtents.z );
  189. case NearBottomRight: return Point3F( maxExtents.x, minExtents.y, minExtents.z );
  190. case FarBottomLeft: return Point3F( minExtents.x, maxExtents.y, minExtents.z );
  191. case FarTopLeft: return Point3F( minExtents.x, maxExtents.y, maxExtents.z );
  192. case FarTopRight: return Point3F( maxExtents.x, maxExtents.y, maxExtents.z );
  193. case FarBottomRight: return Point3F( maxExtents.x, maxExtents.y, minExtents.z );
  194. }
  195. // Not reached.
  196. return Point3F( 0.f, 0.f, 0.f );
  197. }
  198. //-----------------------------------------------------------------------------
  199. F32 Box3F::getGreatestDiagonalLength() const
  200. {
  201. F32 maxDiagonalsLen = ( computeVertex( FarTopRight ) - computeVertex( NearBottomLeft ) ).len();
  202. maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarTopLeft ) - computeVertex( NearBottomRight ) ).len() );
  203. maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarBottomLeft ) - computeVertex( NearTopRight ) ).len() );
  204. maxDiagonalsLen = getMax( maxDiagonalsLen, ( computeVertex( FarBottomRight ) - computeVertex( NearTopLeft ) ).len() );
  205. return maxDiagonalsLen;
  206. }
  207. //-----------------------------------------------------------------------------
  208. SphereF Box3F::getBoundingSphere() const
  209. {
  210. return SphereF( getCenter(), getGreatestDiagonalLength() / 2.f );
  211. }