Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ViewVolume.cpp 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*!
  2. * \file include/ViewVolume.h
  3. * \brief Viewing Volume for culling use
  4. *
  5. * Thanks Mark Morley for the article I used to get several algorithms.
  6. *
  7. * \author Mongoose
  8. */
  9. #include <math.h>
  10. #include "ViewVolume.h"
  11. ViewVolume::ViewVolume() {
  12. mFrustum[0][0] = mFrustum[0][1] = mFrustum[0][2] = mFrustum[0][3] = 0.0f;
  13. mFrustum[1][0] = mFrustum[1][1] = mFrustum[1][2] = mFrustum[1][3] = 0.0f;
  14. mFrustum[2][0] = mFrustum[2][1] = mFrustum[2][2] = mFrustum[2][3] = 0.0f;
  15. mFrustum[3][0] = mFrustum[3][1] = mFrustum[3][2] = mFrustum[3][3] = 0.0f;
  16. mFrustum[4][0] = mFrustum[4][1] = mFrustum[4][2] = mFrustum[4][3] = 0.0f;
  17. mFrustum[5][0] = mFrustum[5][1] = mFrustum[5][2] = mFrustum[5][3] = 0.0f;
  18. }
  19. bool ViewVolume::isBoundingVolumeInFrustum(BoundingVolume bvol) {
  20. return (isBoundingSphereInFrustum(bvol.mSphere) &&
  21. isBoundingBoxInFrustum(bvol.mBox));
  22. }
  23. bool ViewVolume::isBoundingSphereInFrustum(BoundingSphere bvol) {
  24. return (isSphereInFrustum(bvol.mCenter[0],
  25. bvol.mCenter[1],
  26. bvol.mCenter[2],
  27. bvol.mRadius));
  28. }
  29. bool ViewVolume::isBoundingBoxInFrustum(BoundingBox bvol) {
  30. return (isBboxInFrustum(bvol.mMin, bvol.mMax));
  31. }
  32. bool ViewVolume::isPointInFrustum(vec_t x, vec_t y, vec_t z) {
  33. for (unsigned int p = 0; p < 6; ++p) {
  34. if (mFrustum[p][0] * x + mFrustum[p][1] * y + mFrustum[p][2] * z +
  35. mFrustum[p][3] <= 0) {
  36. return false;
  37. }
  38. }
  39. return true;
  40. }
  41. bool ViewVolume::isSphereInFrustum(vec_t x, vec_t y, vec_t z, vec_t radius) {
  42. vec_t d;
  43. for (unsigned int p = 0; p < 6; ++p) {
  44. d = mFrustum[p][0] * x + mFrustum[p][1] * y + mFrustum[p][2] * z + mFrustum[p][3];
  45. if (d <= -radius)
  46. return false;
  47. }
  48. return true;
  49. }
  50. bool ViewVolume::isBboxInFrustum(vec3_t min, vec3_t max) {
  51. for (unsigned int p = 0; p < 6; ++p) {
  52. if (mFrustum[p][0] * min[0] +
  53. mFrustum[p][1] * min[1] +
  54. mFrustum[p][2] * min[2] + mFrustum[p][3] > 0)
  55. continue;
  56. if (mFrustum[p][0] * max[0] +
  57. mFrustum[p][1] * max[1] +
  58. mFrustum[p][2] * max[2] + mFrustum[p][3] > 0)
  59. continue;
  60. if (mFrustum[p][0] * min[0] +
  61. mFrustum[p][1] * max[1] +
  62. mFrustum[p][2] * max[2] + mFrustum[p][3] > 0)
  63. continue;
  64. if (mFrustum[p][0] * min[0] +
  65. mFrustum[p][1] * min[1] +
  66. mFrustum[p][2] * max[2] + mFrustum[p][3] > 0)
  67. continue;
  68. if (mFrustum[p][0] * min[0] +
  69. mFrustum[p][1] * max[1] +
  70. mFrustum[p][2] * min[2] + mFrustum[p][3] > 0)
  71. continue;
  72. if (mFrustum[p][0] * max[0] +
  73. mFrustum[p][1] * min[1] +
  74. mFrustum[p][2] * min[2] + mFrustum[p][3] > 0)
  75. continue;
  76. if (mFrustum[p][0] * max[0] +
  77. mFrustum[p][1] * max[1] +
  78. mFrustum[p][2] * min[2] + mFrustum[p][3] > 0)
  79. continue;
  80. if (mFrustum[p][0] * max[0] +
  81. mFrustum[p][1] * min[1] +
  82. mFrustum[p][2] * max[2] + mFrustum[p][3] > 0)
  83. continue;
  84. return false;
  85. }
  86. return true;
  87. }
  88. vec_t ViewVolume::getDistToSphereFromNear(vec_t x, vec_t y, vec_t z, vec_t radius) {
  89. vec_t d = 0.0;
  90. for (unsigned int p = 0; p < 6; ++p) {
  91. d = mFrustum[p][0] * x + mFrustum[p][1] * y + mFrustum[p][2] * z + mFrustum[p][3];
  92. if (d <= -radius)
  93. return 0;
  94. }
  95. return d + radius;
  96. }
  97. vec_t ViewVolume::getDistToBboxFromNear(vec3_t min, vec3_t max) {
  98. vec3_t center;
  99. vec_t d, radius;
  100. helMidpoint3v(min, max, center);
  101. // 5 should be near plane
  102. d = (mFrustum[5][0] * center[0] +
  103. mFrustum[5][1] * center[1] +
  104. mFrustum[5][2] * center[2] +
  105. mFrustum[5][3]);
  106. radius = helDist3v(max, center);
  107. if (d <= -radius)
  108. return 0;
  109. return d + radius;
  110. }
  111. void ViewVolume::getFrustum(vec_t frustum[6][4]) {
  112. for (unsigned int p = 0; p < 6; ++p) {
  113. for (unsigned int i = 0; i < 4; ++i) {
  114. frustum[p][i] = mFrustum[p][i];
  115. }
  116. }
  117. }
  118. void ViewVolume::getPlane(ViewVolumeSide p, vec4_t plane) {
  119. for (unsigned int i = 0; i < 4; ++i) {
  120. plane[i] = mFrustum[p][i];
  121. }
  122. }
  123. void ViewVolume::updateFrame(matrix_t proj, matrix_t mdl) {
  124. setModel(mdl);
  125. setProjection(proj);
  126. updateClip();
  127. updateFrustum();
  128. }
  129. void ViewVolume::updateFrame() {
  130. updateClip();
  131. updateFrustum();
  132. }
  133. void ViewVolume::setModel(matrix_t mdl) {
  134. mModel.setMatrix(mdl);
  135. }
  136. void ViewVolume::setProjection(matrix_t proj) {
  137. mProjection.setMatrix(proj);
  138. }
  139. void ViewVolume::updateClip() {
  140. mClip = mProjection * mModel;
  141. }
  142. void ViewVolume::updateFrustum() {
  143. matrix_t clip;
  144. vec_t t;
  145. mClip.getMatrix(clip);
  146. /* Extract the numbers for the RIGHT plane */
  147. mFrustum[0][0] = clip[ 3] - clip[ 0];
  148. mFrustum[0][1] = clip[ 7] - clip[ 4];
  149. mFrustum[0][2] = clip[11] - clip[ 8];
  150. mFrustum[0][3] = clip[15] - clip[12];
  151. /* Normalize the result */
  152. t = sqrtf(mFrustum[0][0] * mFrustum[0][0] +
  153. mFrustum[0][1] * mFrustum[0][1] +
  154. mFrustum[0][2] * mFrustum[0][2]);
  155. mFrustum[0][0] /= t;
  156. mFrustum[0][1] /= t;
  157. mFrustum[0][2] /= t;
  158. mFrustum[0][3] /= t;
  159. /* Extract the numbers for the LEFT plane */
  160. mFrustum[1][0] = clip[ 3] + clip[ 0];
  161. mFrustum[1][1] = clip[ 7] + clip[ 4];
  162. mFrustum[1][2] = clip[11] + clip[ 8];
  163. mFrustum[1][3] = clip[15] + clip[12];
  164. /* Normalize the result */
  165. t = sqrtf(mFrustum[1][0] * mFrustum[1][0] +
  166. mFrustum[1][1] * mFrustum[1][1] +
  167. mFrustum[1][2] * mFrustum[1][2]);
  168. mFrustum[1][0] /= t;
  169. mFrustum[1][1] /= t;
  170. mFrustum[1][2] /= t;
  171. mFrustum[1][3] /= t;
  172. /* Extract the BOTTOM plane */
  173. mFrustum[2][0] = clip[ 3] + clip[ 1];
  174. mFrustum[2][1] = clip[ 7] + clip[ 5];
  175. mFrustum[2][2] = clip[11] + clip[ 9];
  176. mFrustum[2][3] = clip[15] + clip[13];
  177. /* Normalize the result */
  178. t = sqrtf(mFrustum[2][0] * mFrustum[2][0] +
  179. mFrustum[2][1] * mFrustum[2][1] +
  180. mFrustum[2][2] * mFrustum[2][2]);
  181. mFrustum[2][0] /= t;
  182. mFrustum[2][1] /= t;
  183. mFrustum[2][2] /= t;
  184. mFrustum[2][3] /= t;
  185. /* Extract the TOP plane */
  186. mFrustum[3][0] = clip[ 3] - clip[ 1];
  187. mFrustum[3][1] = clip[ 7] - clip[ 5];
  188. mFrustum[3][2] = clip[11] - clip[ 9];
  189. mFrustum[3][3] = clip[15] - clip[13];
  190. /* Normalize the result */
  191. t = sqrtf(mFrustum[3][0] * mFrustum[3][0] +
  192. mFrustum[3][1] * mFrustum[3][1] +
  193. mFrustum[3][2] * mFrustum[3][2]);
  194. mFrustum[3][0] /= t;
  195. mFrustum[3][1] /= t;
  196. mFrustum[3][2] /= t;
  197. mFrustum[3][3] /= t;
  198. /* Extract the FAR plane */
  199. mFrustum[4][0] = clip[ 3] - clip[ 2];
  200. mFrustum[4][1] = clip[ 7] - clip[ 6];
  201. mFrustum[4][2] = clip[11] - clip[10];
  202. mFrustum[4][3] = clip[15] - clip[14];
  203. /* Normalize the result */
  204. t = sqrtf(mFrustum[4][0] * mFrustum[4][0] +
  205. mFrustum[4][1] * mFrustum[4][1] +
  206. mFrustum[4][2] * mFrustum[4][2]);
  207. mFrustum[4][0] /= t;
  208. mFrustum[4][1] /= t;
  209. mFrustum[4][2] /= t;
  210. mFrustum[4][3] /= t;
  211. /* Extract the NEAR plane */
  212. mFrustum[5][0] = clip[ 3] + clip[ 2];
  213. mFrustum[5][1] = clip[ 7] + clip[ 6];
  214. mFrustum[5][2] = clip[11] + clip[10];
  215. mFrustum[5][3] = clip[15] + clip[14];
  216. /* Normalize the result */
  217. t = sqrtf(mFrustum[5][0] * mFrustum[5][0] +
  218. mFrustum[5][1] * mFrustum[5][1] +
  219. mFrustum[5][2] * mFrustum[5][2]);
  220. mFrustum[5][0] /= t;
  221. mFrustum[5][1] /= t;
  222. mFrustum[5][2] /= t;
  223. mFrustum[5][3] /= t;
  224. }