Camera3D.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include <cmath>
  2. #include "client/math/Camera3D.h"
  3. #include "client/engine/Wrapper.h"
  4. #include "client/engine/Utils.h"
  5. Camera3D::Camera3D()
  6. {
  7. }
  8. Camera3D::~Camera3D()
  9. {
  10. }
  11. const Vector3D& Camera3D::getFlatFront() const
  12. {
  13. return flatFront;
  14. }
  15. const Vector3D& Camera3D::getFlatBack() const
  16. {
  17. return flatBack;
  18. }
  19. const Vector3D& Camera3D::getFlatRight() const
  20. {
  21. return flatRight;
  22. }
  23. const Vector3D& Camera3D::getFlatLeft() const
  24. {
  25. return flatLeft;
  26. }
  27. const Vector3D& Camera3D::getFlatUp() const
  28. {
  29. return flatUp;
  30. }
  31. const Vector3D& Camera3D::getFlatDown() const
  32. {
  33. return flatDown;
  34. }
  35. void Camera3D::addToOldLengthAngle(float f)
  36. {
  37. oldLengthAngle += f;
  38. }
  39. void Camera3D::storePosition()
  40. {
  41. oldCamera.set(camera);
  42. oldLengthAngle = lengthAngle;
  43. oldWidthAngle = widthAngle;
  44. }
  45. void Camera3D::setPosition(float x, float y, float z, float length, float width)
  46. {
  47. camera.set(x, y, z);
  48. lengthAngle = length;
  49. widthAngle = width;
  50. }
  51. float old = 0;
  52. float current = 0;
  53. void Camera3D::update(float lag)
  54. {
  55. // -------------------------------------------------------------------------
  56. // calculate vectors for the view matrix
  57. // -------------------------------------------------------------------------
  58. // front
  59. front.setAngles(interpolate(lag, oldLengthAngle, lengthAngle), interpolate(lag, oldWidthAngle, widthAngle));
  60. // back
  61. back.setInverse(front);
  62. // right
  63. right.set(front);
  64. right.cross(0.0f, 1.0f, 0.0f);
  65. right.normalize();
  66. // left
  67. left.setInverse(right);
  68. // up
  69. up.set(front);
  70. up.cross(left);
  71. up.normalize();
  72. // down
  73. down.setInverse(up);
  74. Vector3D interCamera = oldCamera;
  75. interCamera.addMul(camera, lag);
  76. interCamera.addMul(oldCamera, -lag);
  77. view.set(0, 0, right.getX());
  78. view.set(0, 1, right.getY());
  79. view.set(0, 2, right.getZ());
  80. view.set(0, 3, right.dotInverse(interCamera));
  81. view.set(1, 0, up.getX());
  82. view.set(1, 1, up.getY());
  83. view.set(1, 2, up.getZ());
  84. view.set(1, 3, up.dotInverse(interCamera));
  85. view.set(2, 0, back.getX());
  86. view.set(2, 1, back.getY());
  87. view.set(2, 2, back.getZ());
  88. view.set(2, 3, back.dotInverse(interCamera));
  89. view.set(3, 0, 0.0f);
  90. view.set(3, 1, 0.0f);
  91. view.set(3, 0, 0.0f);
  92. view.set(3, 3, 1.0f);
  93. // -------------------------------------------------------------------------
  94. // calculate flat vectors for movement
  95. // -------------------------------------------------------------------------
  96. // front
  97. flatFront.set(front);
  98. flatFront.setY(0.0f);
  99. flatFront.normalize();
  100. // back
  101. flatBack.setInverse(flatFront);
  102. // right
  103. flatRight.set(flatFront);
  104. flatRight.cross(0.0f, 1.0f, 0.0f);
  105. flatRight.normalize();
  106. // left
  107. flatLeft.setInverse(flatRight);
  108. // up
  109. flatUp.set(0.0f, 1.0f, 0.0f);
  110. // down
  111. flatDown.setInverse(flatUp);
  112. // -------------------------------------------------------------------------
  113. // update frustum planes
  114. // -------------------------------------------------------------------------
  115. // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
  116. float tan = tanf((0.5f * Engine::getFieldOfView()) * M_PI / 180.0f);
  117. float aspect = (float) Engine::getWidth() / Engine::getHeight();
  118. float nearHigh = tan * Engine::getNearClip();
  119. float nearWidth = nearHigh * aspect;
  120. float farHigh = tan * Engine::getFarClip();
  121. float farWidth = farHigh * aspect;
  122. Vector3D fc = interCamera;
  123. fc.addMul(front, Engine::getFarClip());
  124. Vector3D ftl = fc;
  125. ftl.addMul(left, farWidth);
  126. ftl.addMul(up, farHigh);
  127. Vector3D fbl = fc;
  128. fbl.addMul(left, farWidth);
  129. fbl.addMul(down, farHigh);
  130. Vector3D fbr = fc;
  131. fbr.addMul(right, farWidth);
  132. fbr.addMul(down, farHigh);
  133. Vector3D nc = interCamera;
  134. nc.addMul(front, Engine::getNearClip());
  135. Vector3D ntl = nc;
  136. ntl.addMul(left, nearWidth);
  137. ntl.addMul(down, nearHigh);
  138. Vector3D ntr = nc;
  139. ntr.addMul(right, nearWidth);
  140. ntr.addMul(up, nearHigh);
  141. Vector3D nbr = nc;
  142. nbr.addMul(right, nearWidth);
  143. nbr.addMul(down, nearHigh);
  144. // generating planes with counter clockwise vector order
  145. frustumPlanes[0].set(fbl, ftl, fbr); // far
  146. frustumPlanes[1].set(ntl, ftl, fbl); // left
  147. frustumPlanes[2].set(fbr, ntr, nbr); // right
  148. frustumPlanes[3].set(fbl, fbr, nbr); // bottom
  149. frustumPlanes[4].set(ntr, ftl, ntl); // top
  150. frustumPlanes[5].set(nbr, ntr, ntl); // near
  151. }
  152. const float* Camera3D::getViewMatrix()
  153. {
  154. return view.getValues();
  155. }
  156. bool Camera3D::isInFrustum(float x, float y, float z, float x2, float y2, float z2) const
  157. {
  158. // some tolerance
  159. x -= 1;
  160. y -= 1;
  161. z -= 1;
  162. x2 += 1;
  163. y2 += 1;
  164. z2 += 1;
  165. //return true;
  166. // http://cgvr.informatik.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html
  167. // for each plane do ...
  168. for(int fp = 0; fp < 6; fp++)
  169. {
  170. // reset counters for corners in and out
  171. int out = 0;
  172. int in = 0;
  173. // for each corner of the box do ...
  174. // get out of the cycle as soon as a box as corners
  175. // both inside and out of the frustum
  176. for(int i = 0; i < 8 && (in == 0 || out == 0); i++)
  177. {
  178. // is the corner outside or inside
  179. if(frustumPlanes[fp].getSignedDistance(((i >> 2) & 1) ? x : x2, ((i >> 1) & 1) ? y : y2, (i & 1) ? z : z2) > 0)
  180. {
  181. out++;
  182. }
  183. else
  184. {
  185. in++;
  186. }
  187. }
  188. //if all corners are out
  189. if(in == 0)
  190. {
  191. return false;
  192. }
  193. }
  194. return true;
  195. }