Box.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #ifndef __BV_BOX_H__
  21. #define __BV_BOX_H__
  22. /*
  23. ===============================================================================
  24. Oriented Bounding Box
  25. ===============================================================================
  26. */
  27. class idBox {
  28. public:
  29. idBox( void );
  30. explicit idBox( const idVec3 &center, const idVec3 &extents, const idMat3 &axis );
  31. explicit idBox( const idVec3 &point );
  32. explicit idBox( const idBounds &bounds );
  33. explicit idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis );
  34. idBox operator+( const idVec3 &t ) const; // returns translated box
  35. idBox & operator+=( const idVec3 &t ); // translate the box
  36. idBox operator*( const idMat3 &r ) const; // returns rotated box
  37. idBox & operator*=( const idMat3 &r ); // rotate the box
  38. idBox operator+( const idBox &a ) const;
  39. idBox & operator+=( const idBox &a );
  40. idBox operator-( const idBox &a ) const;
  41. idBox & operator-=( const idBox &a );
  42. bool Compare( const idBox &a ) const; // exact compare, no epsilon
  43. bool Compare( const idBox &a, const float epsilon ) const; // compare with epsilon
  44. bool operator==( const idBox &a ) const; // exact compare, no epsilon
  45. bool operator!=( const idBox &a ) const; // exact compare, no epsilon
  46. void Clear( void ); // inside out box
  47. void Zero( void ); // single point at origin
  48. const idVec3 & GetCenter( void ) const; // returns center of the box
  49. const idVec3 & GetExtents( void ) const; // returns extents of the box
  50. const idMat3 & GetAxis( void ) const; // returns the axis of the box
  51. float GetVolume( void ) const; // returns the volume of the box
  52. bool IsCleared( void ) const; // returns true if box are inside out
  53. bool AddPoint( const idVec3 &v ); // add the point, returns true if the box expanded
  54. bool AddBox( const idBox &a ); // add the box, returns true if the box expanded
  55. idBox Expand( const float d ) const; // return box expanded in all directions with the given value
  56. idBox & ExpandSelf( const float d ); // expand box in all directions with the given value
  57. idBox Translate( const idVec3 &translation ) const; // return translated box
  58. idBox & TranslateSelf( const idVec3 &translation ); // translate this box
  59. idBox Rotate( const idMat3 &rotation ) const; // return rotated box
  60. idBox & RotateSelf( const idMat3 &rotation ); // rotate this box
  61. float PlaneDistance( const idPlane &plane ) const;
  62. int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
  63. bool ContainsPoint( const idVec3 &p ) const; // includes touching
  64. bool IntersectsBox( const idBox &a ) const; // includes touching
  65. bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
  66. // intersection points are (start + dir * scale1) and (start + dir * scale2)
  67. bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
  68. // tight box for a collection of points
  69. void FromPoints( const idVec3 *points, const int numPoints );
  70. // most tight box for a translation
  71. void FromPointTranslation( const idVec3 &point, const idVec3 &translation );
  72. void FromBoxTranslation( const idBox &box, const idVec3 &translation );
  73. // most tight box for a rotation
  74. void FromPointRotation( const idVec3 &point, const idRotation &rotation );
  75. void FromBoxRotation( const idBox &box, const idRotation &rotation );
  76. void ToPoints( idVec3 points[8] ) const;
  77. idSphere ToSphere( void ) const;
  78. // calculates the projection of this box onto the given axis
  79. void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
  80. void AxisProjection( const idMat3 &ax, idBounds &bounds ) const;
  81. // calculates the silhouette of the box
  82. int GetProjectionSilhouetteVerts( const idVec3 &projectionOrigin, idVec3 silVerts[6] ) const;
  83. int GetParallelProjectionSilhouetteVerts( const idVec3 &projectionDir, idVec3 silVerts[6] ) const;
  84. private:
  85. idVec3 center;
  86. idVec3 extents;
  87. idMat3 axis;
  88. };
  89. extern idBox box_zero;
  90. ID_INLINE idBox::idBox( void ) {
  91. }
  92. ID_INLINE idBox::idBox( const idVec3 &center, const idVec3 &extents, const idMat3 &axis ) {
  93. this->center = center;
  94. this->extents = extents;
  95. this->axis = axis;
  96. }
  97. ID_INLINE idBox::idBox( const idVec3 &point ) {
  98. this->center = point;
  99. this->extents.Zero();
  100. this->axis.Identity();
  101. }
  102. ID_INLINE idBox::idBox( const idBounds &bounds ) {
  103. this->center = ( bounds[0] + bounds[1] ) * 0.5f;
  104. this->extents = bounds[1] - this->center;
  105. this->axis.Identity();
  106. }
  107. ID_INLINE idBox::idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis ) {
  108. this->center = ( bounds[0] + bounds[1] ) * 0.5f;
  109. this->extents = bounds[1] - this->center;
  110. this->center = origin + this->center * axis;
  111. this->axis = axis;
  112. }
  113. ID_INLINE idBox idBox::operator+( const idVec3 &t ) const {
  114. return idBox( center + t, extents, axis );
  115. }
  116. ID_INLINE idBox &idBox::operator+=( const idVec3 &t ) {
  117. center += t;
  118. return *this;
  119. }
  120. ID_INLINE idBox idBox::operator*( const idMat3 &r ) const {
  121. return idBox( center * r, extents, axis * r );
  122. }
  123. ID_INLINE idBox &idBox::operator*=( const idMat3 &r ) {
  124. center *= r;
  125. axis *= r;
  126. return *this;
  127. }
  128. ID_INLINE idBox idBox::operator+( const idBox &a ) const {
  129. idBox newBox;
  130. newBox = *this;
  131. newBox.AddBox( a );
  132. return newBox;
  133. }
  134. ID_INLINE idBox &idBox::operator+=( const idBox &a ) {
  135. idBox::AddBox( a );
  136. return *this;
  137. }
  138. ID_INLINE idBox idBox::operator-( const idBox &a ) const {
  139. return idBox( center, extents - a.extents, axis );
  140. }
  141. ID_INLINE idBox &idBox::operator-=( const idBox &a ) {
  142. extents -= a.extents;
  143. return *this;
  144. }
  145. ID_INLINE bool idBox::Compare( const idBox &a ) const {
  146. return ( center.Compare( a.center ) && extents.Compare( a.extents ) && axis.Compare( a.axis ) );
  147. }
  148. ID_INLINE bool idBox::Compare( const idBox &a, const float epsilon ) const {
  149. return ( center.Compare( a.center, epsilon ) && extents.Compare( a.extents, epsilon ) && axis.Compare( a.axis, epsilon ) );
  150. }
  151. ID_INLINE bool idBox::operator==( const idBox &a ) const {
  152. return Compare( a );
  153. }
  154. ID_INLINE bool idBox::operator!=( const idBox &a ) const {
  155. return !Compare( a );
  156. }
  157. ID_INLINE void idBox::Clear( void ) {
  158. center.Zero();
  159. extents[0] = extents[1] = extents[2] = -idMath::INFINITY;
  160. axis.Identity();
  161. }
  162. ID_INLINE void idBox::Zero( void ) {
  163. center.Zero();
  164. extents.Zero();
  165. axis.Identity();
  166. }
  167. ID_INLINE const idVec3 &idBox::GetCenter( void ) const {
  168. return center;
  169. }
  170. ID_INLINE const idVec3 &idBox::GetExtents( void ) const {
  171. return extents;
  172. }
  173. ID_INLINE const idMat3 &idBox::GetAxis( void ) const {
  174. return axis;
  175. }
  176. ID_INLINE float idBox::GetVolume( void ) const {
  177. return ( extents * 2.0f ).LengthSqr();
  178. }
  179. ID_INLINE bool idBox::IsCleared( void ) const {
  180. return extents[0] < 0.0f;
  181. }
  182. ID_INLINE idBox idBox::Expand( const float d ) const {
  183. return idBox( center, extents + idVec3( d, d, d ), axis );
  184. }
  185. ID_INLINE idBox &idBox::ExpandSelf( const float d ) {
  186. extents[0] += d;
  187. extents[1] += d;
  188. extents[2] += d;
  189. return *this;
  190. }
  191. ID_INLINE idBox idBox::Translate( const idVec3 &translation ) const {
  192. return idBox( center + translation, extents, axis );
  193. }
  194. ID_INLINE idBox &idBox::TranslateSelf( const idVec3 &translation ) {
  195. center += translation;
  196. return *this;
  197. }
  198. ID_INLINE idBox idBox::Rotate( const idMat3 &rotation ) const {
  199. return idBox( center * rotation, extents, axis * rotation );
  200. }
  201. ID_INLINE idBox &idBox::RotateSelf( const idMat3 &rotation ) {
  202. center *= rotation;
  203. axis *= rotation;
  204. return *this;
  205. }
  206. ID_INLINE bool idBox::ContainsPoint( const idVec3 &p ) const {
  207. idVec3 lp = p - center;
  208. if ( idMath::Fabs( lp * axis[0] ) > extents[0] ||
  209. idMath::Fabs( lp * axis[1] ) > extents[1] ||
  210. idMath::Fabs( lp * axis[2] ) > extents[2] ) {
  211. return false;
  212. }
  213. return true;
  214. }
  215. ID_INLINE idSphere idBox::ToSphere( void ) const {
  216. return idSphere( center, extents.Length() );
  217. }
  218. ID_INLINE void idBox::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
  219. float d1 = dir * center;
  220. float d2 = idMath::Fabs( extents[0] * ( dir * axis[0] ) ) +
  221. idMath::Fabs( extents[1] * ( dir * axis[1] ) ) +
  222. idMath::Fabs( extents[2] * ( dir * axis[2] ) );
  223. min = d1 - d2;
  224. max = d1 + d2;
  225. }
  226. ID_INLINE void idBox::AxisProjection( const idMat3 &ax, idBounds &bounds ) const {
  227. for ( int i = 0; i < 3; i++ ) {
  228. float d1 = ax[i] * center;
  229. float d2 = idMath::Fabs( extents[0] * ( ax[i] * axis[0] ) ) +
  230. idMath::Fabs( extents[1] * ( ax[i] * axis[1] ) ) +
  231. idMath::Fabs( extents[2] * ( ax[i] * axis[2] ) );
  232. bounds[0][i] = d1 - d2;
  233. bounds[1][i] = d1 + d2;
  234. }
  235. }
  236. #endif /* !__BV_BOX_H__ */