Camera.cpp
上传用户:sz83729876
上传日期:2013-03-07
资源大小:4140k
文件大小:14k
源码类别:

OpenGL

开发平台:

Windows_Unix

  1. //***********************************************************************//
  2. //  //
  3. //***********************************************************************//
  4. #include "../main.h"
  5. #pragma warning (disable: 4305) // truncation from 'const double' to 'float'
  6. extern int w_height;
  7. extern int  w_width;
  8. // This is how fast our camera moves (Sped up a bit due to normalizing our vectors)
  9. #define kSpeed 0.1f
  10. /////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\*
  11. /////
  12. ///// This returns a perpendicular vector from 2 given vectors by taking the cross product.
  13. /////
  14. /////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\*
  15. CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
  16. {
  17. CVector3 vNormal;
  18. // Calculate the cross product with the non communitive equation
  19. vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
  20. vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
  21. vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));
  22. // Return the cross product
  23. return vNormal;  
  24. }
  25. /////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\*
  26. /////
  27. ///// This returns the magnitude of a vector
  28. /////
  29. /////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\*
  30. float Magnitude(CVector3 vNormal)
  31. {
  32. // Here is the equation:  magnitude = sqrt(V.x^2 + V.y^2 + V.z^2) : Where V is the vector
  33. return (float)sqrt( (vNormal.x * vNormal.x) + 
  34. (vNormal.y * vNormal.y) + 
  35. (vNormal.z * vNormal.z) );
  36. }
  37. /////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\*
  38. /////
  39. ///// This returns a normalize vector (A vector exactly of length 1)
  40. /////
  41. /////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\*
  42. CVector3 Normalize(CVector3 vVector)
  43. {
  44. // Get the magnitude of our normal
  45. float magnitude = Magnitude(vVector);
  46. // Now that we have the magnitude, we can divide our vector by that magnitude.
  47. // That will make our vector a total length of 1.  
  48. vVector = vVector / magnitude;
  49. // Finally, return our normalized vector
  50. return vVector;
  51. }
  52. ///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\*
  53. /////
  54. ///// This is the class constructor
  55. /////
  56. ///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\*
  57. CCamera::CCamera()
  58. {
  59. CVector3 vZero = CVector3(0.0, 0.0, 0.0); // Init a vVector to 0 0 0 for our position
  60. CVector3 vView = CVector3(0.0, 1.0, 0.5); // Init a starting view vVector (looking up and out the screen) 
  61. CVector3 vUp   = CVector3(0.0, 0.0, 1.0); // Init a standard up vVector (Rarely ever changes)
  62. mPos = vZero; // Init the position to zero
  63. mView = vView; // Init the view to a std starting view
  64. mUp = vUp; // Init the UpVector
  65. }
  66. ///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*
  67. /////
  68. ///// This function sets the camera's position and view and up vVector.
  69. /////
  70. ///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*
  71. void CCamera::PositionCamera(float positionX, float positionY, float positionZ,
  72.         float viewX,     float viewY,     float viewZ,
  73.  float upVectorX, float upVectorY, float upVectorZ)
  74. {
  75. CVector3 vPosition = CVector3(positionX, positionY, positionZ);
  76. CVector3 vView = CVector3(viewX, viewY, viewZ);
  77. CVector3 vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);
  78. // The code above just makes it cleaner to set the variables.
  79. // Otherwise we would have to set each variable x y and z.
  80. mPos = vPosition; // Assign the position
  81. mView     = vView; // Assign the view
  82. mUp = vUpVector; // Assign the up vector
  83. }
  84. ///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\*
  85. /////
  86. ///// This allows us to look around using the mouse, like in most first person games.
  87. /////
  88. ///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\*
  89. void CCamera::MouseMove()
  90. {
  91. POINT mousePos; // This is a window structure that holds an X and Y
  92. int middleX = w_width  >> 1; // This is a binary shift to get half the width
  93. int middleY = w_height >> 1; // This is a binary shift to get half the height
  94. float angleY = 0.0f; // This is the direction for looking up or down
  95. float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
  96. static float currentRotX = 0.0f;
  97. // Get the mouse's current X,Y position
  98. GetCursorPos(&mousePos);
  99. // If our cursor is still in the middle, we never moved... so don't update the screen
  100. if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;
  101. // Set the mouse position to the middle of our window
  102. SetCursorPos(middleX, middleY);
  103. // Get the direction the mouse moved in, but bring the number down to a reasonable amount
  104. angleY = (float)( (middleX - mousePos.x) ) / 1000.0f;
  105. angleZ = (float)( (middleY - mousePos.y) ) / 1000.0f;
  106. // Here we keep track of the current rotation (for up and down) so that
  107. // we can restrict the camera from doing a full 360 loop.
  108. currentRotX -= angleZ;  
  109. // If the current rotation (in radians) is greater than 1.0, we want to cap it.
  110. if(currentRotX > 1.0f)
  111. currentRotX = 1.0f;
  112. // Check if the rotation is below -1.0, if so we want to make sure it doesn't continue
  113. else if(currentRotX < -1.0f)
  114. currentRotX = -1.0f;
  115. // Otherwise, we can rotate the view around our position
  116. else
  117. {
  118. // To find the axis we need to rotate around for up and down
  119. // movements, we need to get a perpendicular vector from the
  120. // camera's view vector and up vector.  This will be the axis.
  121. CVector3 vAxis = Cross(mView - mPos, mUp);
  122. vAxis = Normalize(vAxis);
  123. // Rotate around our perpendicular axis and along the y-axis
  124. RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
  125. RotateView(angleY, 0, 1, 0);
  126. }
  127. }
  128. void CCamera::RotateAroundPoint(CVector3 vCenter, float angle, float x, float y, float z)
  129. {
  130. CVector3 vNewPosition;
  131. // To rotate our position around a point, what we need to do is find
  132. // a vector from our position to the center point we will be rotating around.
  133. // Once we get this vector, then we rotate it along the specified axis with
  134. // the specified degree.  Finally the new vector is added center point that we
  135. // rotated around (vCenter) to become our new position.  That's all it takes.
  136. // Get the vVector from our position to the center we are rotating around
  137. CVector3 vPos = mPos - vCenter;
  138. // Calculate the sine and cosine of the angle once
  139. float cosTheta = (float)cos(angle);
  140. float sinTheta = (float)sin(angle);
  141. // Find the new x position for the new rotated point
  142. vNewPosition.x  = (cosTheta + (1 - cosTheta) * x * x) * vPos.x;
  143. vNewPosition.x += ((1 - cosTheta) * x * y - z * sinTheta) * vPos.y;
  144. vNewPosition.x += ((1 - cosTheta) * x * z + y * sinTheta) * vPos.z;
  145. // Find the new y position for the new rotated point
  146. vNewPosition.y  = ((1 - cosTheta) * x * y + z * sinTheta) * vPos.x;
  147. vNewPosition.y += (cosTheta + (1 - cosTheta) * y * y) * vPos.y;
  148. vNewPosition.y += ((1 - cosTheta) * y * z - x * sinTheta) * vPos.z;
  149. // Find the new z position for the new rotated point
  150. vNewPosition.z  = ((1 - cosTheta) * x * z - y * sinTheta) * vPos.x;
  151. vNewPosition.z += ((1 - cosTheta) * y * z + x * sinTheta) * vPos.y;
  152. vNewPosition.z += (cosTheta + (1 - cosTheta) * z * z) * vPos.z;
  153. // Now we just add the newly rotated vector to our position to set
  154. // our new rotated position of our camera.
  155. mPos = vCenter + vNewPosition;
  156. }
  157. ///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\*
  158. /////
  159. ///// This rotates the view around the position using an axis-angle rotation
  160. /////
  161. ///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\*
  162. void CCamera::RotateView(float angle, float x, float y, float z)
  163. {
  164. CVector3 vNewView;
  165. // Get the view vector (The direction we are facing)
  166. CVector3 vView = mView - mPos;
  167. // Calculate the sine and cosine of the angle once
  168. float cosTheta = (float)cos(angle);
  169. float sinTheta = (float)sin(angle);
  170. // Find the new x position for the new rotated point
  171. vNewView.x  = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
  172. vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
  173. vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
  174. // Find the new y position for the new rotated point
  175. vNewView.y  = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
  176. vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
  177. vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
  178. // Find the new z position for the new rotated point
  179. vNewView.z  = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
  180. vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
  181. vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
  182. // Now we just add the newly rotated vector to our position to set
  183. // our new rotated view of our camera.
  184. mView = mPos + vNewView;
  185. }
  186. ///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\*
  187. /////
  188. ///// This strafes the camera left and right depending on the speed (-/+)
  189. /////
  190. ///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\*
  191. void CCamera::StrafeCamera(float speed)
  192. {
  193. // Strafing is quite simple if you understand what the cross product is.
  194. // If you have 2 vectors (say the up vVector and the view vVector) you can
  195. // use the cross product formula to get a vVector that is 90 degrees from the 2 vectors.
  196. // For a better explanation on how this works, check out the OpenGL "Normals" tutorial at our site.
  197. // In our new Update() function, we set the strafing vector (m_vStrafe).  Due
  198. // to the fact that we need this vector for many things including the strafing
  199. // movement and camera rotation (up and down), we just calculate it once.
  200. //
  201. // Like our MoveCamera() function, we add the strafing vector to our current position 
  202. // and view.  It's as simple as that.  It has already been calculated in Update().
  203. // Add the strafe vector to our position
  204. mPos.x += m_vStrafe.x * speed;
  205. mPos.z += m_vStrafe.z * speed;
  206. // Add the strafe vector to our view
  207. mView.x += m_vStrafe.x * speed;
  208. mView.z += m_vStrafe.z * speed;
  209. }
  210. ///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*
  211. /////
  212. ///// This will move the camera forward or backward depending on the speed
  213. /////
  214. ///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*
  215. void CCamera::MoveCamera(float speed)
  216. {
  217. // Get the current view vector (the direction we are looking)
  218. CVector3 vVector = mView - mPos;
  219. // I snuck this change in here!  We now normalize our view vector when
  220. // moving throughout the world.  This is a MUST that needs to be done.
  221. // That way you don't move faster than you strafe, since the strafe vector
  222. // is normalized too.
  223. vVector = Normalize(vVector);
  224. mPos.x += vVector.x * speed; // Add our acceleration to our position's X
  225. mPos.z += vVector.z * speed; // Add our acceleration to our position's Z
  226. mView.x += vVector.x * speed; // Add our acceleration to our view's X
  227. mView.z += vVector.z * speed; // Add our acceleration to our view's Z
  228. }
  229. // The next 3 functions were added to our camera class.  The less code in 
  230. // Main.cpp the better.
  231. //////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\*
  232. /////
  233. ///// This function handles the input faster than in the WinProc()
  234. /////
  235. //////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\*
  236. void CCamera::CheckForMovement()
  237. {
  238. // Check if we hit the Up arrow or the 'w' key
  239. if(GetKeyState(VK_UP) & 0x80) {
  240. // Move our camera forward by a positive SPEED
  241. MoveCamera(kSpeed);
  242. }
  243. // Check if we hit the Down arrow or the 's' key
  244. if(GetKeyState(VK_DOWN) & 0x80) {
  245. // Move our camera backward by a negative SPEED
  246. MoveCamera(-kSpeed);
  247. }
  248. // Check if we hit the Left arrow or the 'a' key
  249. if(GetKeyState(VK_LEFT) & 0x80) {
  250. // Strafe the camera left
  251. //StrafeCamera(-kSpeed);
  252. RotateAroundPoint(mView, kSpeed, 0, 1, 0);
  253. //RotateView(0.1, 0, 0.5,0);
  254. }
  255. // Check if we hit the Right arrow or the 'd' key
  256. // if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80) {
  257. if(GetKeyState(VK_RIGHT) & 0x80) {
  258. // Strafe the camera right
  259. //StrafeCamera(kSpeed);
  260. RotateAroundPoint(mView, -kSpeed, 0, 1, 0);
  261. //RotateView(0.1, 0, -0.5,0);
  262. }
  263. }
  264. ///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\*
  265. /////
  266. ///// This updates the camera's view and strafe vector
  267. /////
  268. ///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\*
  269. void CCamera::Update() 
  270. {
  271. // Below we calculate the strafe vector every time we update
  272. // the camera.  This is because many functions use it so we might
  273. // as well calculate it only once.  
  274. // Initialize a variable for the cross product result
  275. CVector3 vCross = Cross(mView - mPos, mUp);
  276. // Normalize the strafe vector
  277. m_vStrafe = Normalize(vCross);
  278. CheckForMovement();
  279. }
  280. ///////////////////////////////// LOOK \\\\\\\\\\\\\\\\*
  281. /////
  282. ///// This updates the camera according to the 
  283. /////
  284. ///////////////////////////////// LOOK \\\\\\\\\\\\\\\\*
  285. void CCamera::Look()
  286. {
  287. // Give openGL our camera position, then camera view, then camera up vector
  288. gluLookAt(mPos.x, mPos.y, mPos.z,
  289.   mView.x,  mView.y,     mView.z,
  290.   mUp.x, mUp.y, mUp.z);
  291. }