Camera.cpp 9.2 KB

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