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

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