CmAABox.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "CmAABox.h"
  2. namespace CamelotFramework
  3. {
  4. const AABox AABox::BOX_EMPTY;
  5. AABox::AABox()
  6. :mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
  7. {
  8. // Default to a null box
  9. setMin(Vector3(-0.5f, -0.5f, -0.5f));
  10. setMax(Vector3(0.5f, 0.5f, 0.5f));
  11. }
  12. AABox::AABox(const AABox & rkBox)
  13. :mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
  14. {
  15. setExtents( rkBox.mMinimum, rkBox.mMaximum );
  16. }
  17. AABox::AABox(const Vector3& min, const Vector3& max)
  18. :mMinimum(Vector3::ZERO), mMaximum(Vector3::UNIT_SCALE)
  19. {
  20. setExtents( min, max );
  21. }
  22. AABox& AABox::operator=(const AABox& rhs)
  23. {
  24. setExtents(rhs.mMinimum, rhs.mMaximum);
  25. return *this;
  26. }
  27. void AABox::setExtents( const Vector3& min, const Vector3& max )
  28. {
  29. assert( (min.x <= max.x && min.y <= max.y && min.z <= max.z) &&
  30. "The minimum corner of the box must be less than or equal to maximum corner" );
  31. mMinimum = min;
  32. mMaximum = max;
  33. }
  34. Vector3 AABox::getCorner(CornerEnum cornerToGet) const
  35. {
  36. switch(cornerToGet)
  37. {
  38. case FAR_LEFT_BOTTOM:
  39. return mMinimum;
  40. case FAR_LEFT_TOP:
  41. return Vector3(mMinimum.x, mMaximum.y, mMinimum.z);
  42. case FAR_RIGHT_TOP:
  43. return Vector3(mMaximum.x, mMaximum.y, mMinimum.z);
  44. case FAR_RIGHT_BOTTOM:
  45. return Vector3(mMaximum.x, mMinimum.y, mMinimum.z);
  46. case NEAR_RIGHT_BOTTOM:
  47. return Vector3(mMaximum.x, mMinimum.y, mMaximum.z);
  48. case NEAR_LEFT_BOTTOM:
  49. return Vector3(mMinimum.x, mMinimum.y, mMaximum.z);
  50. case NEAR_LEFT_TOP:
  51. return Vector3(mMinimum.x, mMaximum.y, mMaximum.z);
  52. case NEAR_RIGHT_TOP:
  53. return mMaximum;
  54. default:
  55. return Vector3();
  56. }
  57. }
  58. void AABox::merge( const AABox& rhs )
  59. {
  60. Vector3 min = mMinimum;
  61. Vector3 max = mMaximum;
  62. max.makeCeil(rhs.mMaximum);
  63. min.makeFloor(rhs.mMinimum);
  64. setExtents(min, max);
  65. }
  66. void AABox::merge( const Vector3& point )
  67. {
  68. mMaximum.makeCeil(point);
  69. mMinimum.makeFloor(point);
  70. }
  71. void AABox::transform( const Matrix4& matrix )
  72. {
  73. Vector3 oldMin, oldMax, currentCorner;
  74. // Getting the old values so that we can use the existing merge method.
  75. oldMin = mMinimum;
  76. oldMax = mMaximum;
  77. // We sequentially compute the corners in the following order :
  78. // 0, 6, 5, 1, 2, 4 ,7 , 3
  79. // This sequence allows us to only change one member at a time to get at all corners.
  80. // For each one, we transform it using the matrix
  81. // Which gives the resulting point and merge the resulting point.
  82. // First corner
  83. // min min min
  84. currentCorner = oldMin;
  85. merge( matrix * currentCorner );
  86. // min,min,max
  87. currentCorner.z = oldMax.z;
  88. merge( matrix * currentCorner );
  89. // min max max
  90. currentCorner.y = oldMax.y;
  91. merge( matrix * currentCorner );
  92. // min max min
  93. currentCorner.z = oldMin.z;
  94. merge( matrix * currentCorner );
  95. // max max min
  96. currentCorner.x = oldMax.x;
  97. merge( matrix * currentCorner );
  98. // max max max
  99. currentCorner.z = oldMax.z;
  100. merge( matrix * currentCorner );
  101. // max min max
  102. currentCorner.y = oldMin.y;
  103. merge( matrix * currentCorner );
  104. // max min min
  105. currentCorner.z = oldMin.z;
  106. merge( matrix * currentCorner );
  107. }
  108. void AABox::transformAffine(const Matrix4& m)
  109. {
  110. assert(m.isAffine());
  111. Vector3 centre = getCenter();
  112. Vector3 halfSize = getHalfSize();
  113. Vector3 newCentre = m.transformAffine(centre);
  114. Vector3 newHalfSize(
  115. Math::Abs(m[0][0]) * halfSize.x + Math::Abs(m[0][1]) * halfSize.y + Math::Abs(m[0][2]) * halfSize.z,
  116. Math::Abs(m[1][0]) * halfSize.x + Math::Abs(m[1][1]) * halfSize.y + Math::Abs(m[1][2]) * halfSize.z,
  117. Math::Abs(m[2][0]) * halfSize.x + Math::Abs(m[2][1]) * halfSize.y + Math::Abs(m[2][2]) * halfSize.z);
  118. setExtents(newCentre - newHalfSize, newCentre + newHalfSize);
  119. }
  120. bool AABox::intersects(const AABox& b2) const
  121. {
  122. // Use up to 6 separating planes
  123. if (mMaximum.x < b2.mMinimum.x)
  124. return false;
  125. if (mMaximum.y < b2.mMinimum.y)
  126. return false;
  127. if (mMaximum.z < b2.mMinimum.z)
  128. return false;
  129. if (mMinimum.x > b2.mMaximum.x)
  130. return false;
  131. if (mMinimum.y > b2.mMaximum.y)
  132. return false;
  133. if (mMinimum.z > b2.mMaximum.z)
  134. return false;
  135. // otherwise, must be intersecting
  136. return true;
  137. }
  138. AABox AABox::intersection(const AABox& b2) const
  139. {
  140. Vector3 intMin = mMinimum;
  141. Vector3 intMax = mMaximum;
  142. intMin.makeCeil(b2.getMin());
  143. intMax.makeFloor(b2.getMax());
  144. // Check intersection isn't null
  145. if (intMin.x < intMax.x &&
  146. intMin.y < intMax.y &&
  147. intMin.z < intMax.z)
  148. {
  149. return AABox(intMin, intMax);
  150. }
  151. return AABox();
  152. }
  153. float AABox::volume(void) const
  154. {
  155. Vector3 diff = mMaximum - mMinimum;
  156. return diff.x * diff.y * diff.z;
  157. }
  158. void AABox::scale(const Vector3& s)
  159. {
  160. // NB assumes centered on origin
  161. Vector3 min = mMinimum * s;
  162. Vector3 max = mMaximum * s;
  163. setExtents(min, max);
  164. }
  165. bool AABox::intersects(const Sphere& s) const
  166. {
  167. return Math::intersects(s, *this);
  168. }
  169. bool AABox::intersects(const Plane& p) const
  170. {
  171. return Math::intersects(p, *this);
  172. }
  173. bool AABox::intersects(const Vector3& v) const
  174. {
  175. return(v.x >= mMinimum.x && v.x <= mMaximum.x &&
  176. v.y >= mMinimum.y && v.y <= mMaximum.y &&
  177. v.z >= mMinimum.z && v.z <= mMaximum.z);
  178. }
  179. Vector3 AABox::getCenter(void) const
  180. {
  181. return Vector3(
  182. (mMaximum.x + mMinimum.x) * 0.5f,
  183. (mMaximum.y + mMinimum.y) * 0.5f,
  184. (mMaximum.z + mMinimum.z) * 0.5f);
  185. }
  186. Vector3 AABox::getSize(void) const
  187. {
  188. return mMaximum - mMinimum;
  189. }
  190. Vector3 AABox::getHalfSize(void) const
  191. {
  192. return (mMaximum - mMinimum) * 0.5;
  193. }
  194. bool AABox::contains(const Vector3& v) const
  195. {
  196. return mMinimum.x <= v.x && v.x <= mMaximum.x &&
  197. mMinimum.y <= v.y && v.y <= mMaximum.y &&
  198. mMinimum.z <= v.z && v.z <= mMaximum.z;
  199. }
  200. bool AABox::contains(const AABox& other) const
  201. {
  202. return this->mMinimum.x <= other.mMinimum.x &&
  203. this->mMinimum.y <= other.mMinimum.y &&
  204. this->mMinimum.z <= other.mMinimum.z &&
  205. other.mMaximum.x <= this->mMaximum.x &&
  206. other.mMaximum.y <= this->mMaximum.y &&
  207. other.mMaximum.z <= this->mMaximum.z;
  208. }
  209. bool AABox::operator== (const AABox& rhs) const
  210. {
  211. return this->mMinimum == rhs.mMinimum &&
  212. this->mMaximum == rhs.mMaximum;
  213. }
  214. bool AABox::operator!= (const AABox& rhs) const
  215. {
  216. return !(*this == rhs);
  217. }
  218. }