Camera3D.cpp 5.5 KB

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