Camera.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "Camera.h"
  2. //======================================================================================================================
  3. // setAll =
  4. //======================================================================================================================
  5. void Camera::setAll(float fovx_, float fovy_, float znear_, float zfar_)
  6. {
  7. fovX = fovx_;
  8. fovY = fovy_;
  9. zNear = znear_;
  10. zFar = zfar_;
  11. calcProjectionMatrix();
  12. calcLSpaceFrustumPlanes();
  13. }
  14. //======================================================================================================================
  15. // lookAtPoint =
  16. //======================================================================================================================
  17. void Camera::lookAtPoint(const Vec3& point)
  18. {
  19. const Vec3& j = Vec3(0.0, 1.0, 0.0);
  20. Vec3 vdir = (point - getLocalTransform().origin).getNormalized();
  21. Vec3 vup = j - vdir * j.dot(vdir);
  22. Vec3 vside = vdir.cross(vup);
  23. getLocalTransform().rotation.setColumns(vside, vup, -vdir);
  24. }
  25. //======================================================================================================================
  26. // calcLSpaceFrustumPlanes =
  27. //======================================================================================================================
  28. void Camera::calcLSpaceFrustumPlanes()
  29. {
  30. float c, s; // cos & sine
  31. sinCos(PI + fovX / 2, s, c);
  32. // right
  33. lspaceFrustumPlanes[FP_RIGHT] = Plane(Vec3(c, 0.0, s), 0.0);
  34. // left
  35. lspaceFrustumPlanes[FP_LEFT] = Plane(Vec3(-c, 0.0, s), 0.0);
  36. sinCos((3 * PI - fovY) * 0.5, s, c);
  37. // top
  38. lspaceFrustumPlanes[FP_TOP] = Plane(Vec3(0.0, s, c), 0.0);
  39. // bottom
  40. lspaceFrustumPlanes[FP_BOTTOM] = Plane(Vec3(0.0, -s, c), 0.0);
  41. // near
  42. lspaceFrustumPlanes[FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), zNear);
  43. // far
  44. lspaceFrustumPlanes[FP_FAR] = Plane(Vec3(0.0, 0.0, 1.0), -zFar);
  45. }
  46. //======================================================================================================================
  47. // updateWSpaceFrustumPlanes =
  48. //======================================================================================================================
  49. void Camera::updateWSpaceFrustumPlanes()
  50. {
  51. for(uint i=0; i<6; i++)
  52. {
  53. wspaceFrustumPlanes[i] = lspaceFrustumPlanes[i].getTransformed(getWorldTransform().origin,
  54. getWorldTransform().rotation,
  55. getWorldTransform().scale);
  56. }
  57. }
  58. //======================================================================================================================
  59. // insideFrustum =
  60. //======================================================================================================================
  61. /// Check if the volume is inside the frustum cliping planes
  62. bool Camera::insideFrustum(const CollisionShape& bvol) const
  63. {
  64. for(uint i=0; i<6; i++)
  65. {
  66. if(bvol.testPlane(wspaceFrustumPlanes[i]) < 0.0)
  67. {
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. //======================================================================================================================
  74. // insideFrustum =
  75. //======================================================================================================================
  76. bool Camera::insideFrustum(const Camera& cam) const
  77. {
  78. // get five points. These points are the tips of the given camera
  79. Vec3 points[5];
  80. // get 3 sample floats
  81. float x = cam.getZFar() / tan((PI - cam.getFovX())/2);
  82. float y = tan(cam.getFovY() / 2) * cam.getZFar();
  83. float z = -cam.getZFar();
  84. // the actual points in local space
  85. points[0] = Vec3(x, y, z); // top right
  86. points[1] = Vec3(-x, y, z); // top left
  87. points[2] = Vec3(-x, -y, z); // bottom left
  88. points[3] = Vec3(x, -y, z); // bottom right
  89. points[4] = Vec3(cam.getWorldTransform().origin); // eye (already in world space)
  90. // transform them to the given camera's world space (exept the eye)
  91. for(uint i=0; i<4; i++)
  92. {
  93. points[i].transform(getWorldTransform());
  94. }
  95. // the collision code
  96. for(uint i=0; i<6; i++) // for the 6 planes
  97. {
  98. int failed = 0;
  99. for(uint j=0; j<5; j++) // for the 5 points
  100. {
  101. if(wspaceFrustumPlanes[i].test(points[j]) < 0.0)
  102. {
  103. ++failed;
  104. }
  105. }
  106. if(failed == 5)
  107. {
  108. return false; // if all points are behind the plane then the cam is not in frustum
  109. }
  110. }
  111. return true;
  112. }
  113. //======================================================================================================================
  114. // calcProjectionMatrix =
  115. //======================================================================================================================
  116. void Camera::calcProjectionMatrix()
  117. {
  118. float f = 1.0 / tan(fovY * 0.5); // f = cot(fovY/2)
  119. projectionMat(0, 0) = f * fovY / fovX; // = f/aspectRatio;
  120. projectionMat(0, 1) = 0.0;
  121. projectionMat(0, 2) = 0.0;
  122. projectionMat(0, 3) = 0.0;
  123. projectionMat(1, 0) = 0.0;
  124. projectionMat(1, 1) = f;
  125. projectionMat(1, 2) = 0.0;
  126. projectionMat(1, 3) = 0.0;
  127. projectionMat(2, 0) = 0.0;
  128. projectionMat(2, 1) = 0.0;
  129. projectionMat(2, 2) = (zFar + zNear) / ( zNear - zFar);
  130. projectionMat(2, 3) = (2.0f * zFar * zNear) / (zNear - zFar);
  131. projectionMat(3, 0) = 0.0;
  132. projectionMat(3, 1) = 0.0;
  133. projectionMat(3, 2) = -1.0;
  134. projectionMat(3, 3) = 0.0;
  135. invProjectionMat = projectionMat.getInverse();
  136. }
  137. //======================================================================================================================
  138. // updateViewMatrix =
  139. //======================================================================================================================
  140. void Camera::updateViewMatrix()
  141. {
  142. /*
  143. * The point at which the camera looks:
  144. * Vec3 viewpoint = translationLspace + z_axis;
  145. * as we know the up vector, we can easily use gluLookAt:
  146. * gluLookAt(translationLspace.x, translationLspace.x, translationLspace.z, z_axis.x, z_axis.y, z_axis.z, y_axis.x,
  147. * y_axis.y, y_axis.z);
  148. */
  149. // The view matrix is: Mview = camera.world_transform.Inverted(). Bus instead of inverting we do the following:
  150. Mat3 camInvertedRot = getWorldTransform().rotation.getTransposed();
  151. Vec3 camInvertedTsl = -(camInvertedRot * getWorldTransform().origin);
  152. viewMat = Mat4(camInvertedTsl, camInvertedRot);
  153. }
  154. //======================================================================================================================
  155. // updateTrf =
  156. //======================================================================================================================
  157. void Camera::updateTrf()
  158. {
  159. updateViewMatrix();
  160. updateWSpaceFrustumPlanes();
  161. }