Camera.cpp
上传用户:sz83729876
上传日期:2013-03-07
资源大小:4140k
文件大小:14k
- //***********************************************************************//
- // //
- //***********************************************************************//
- #include "../main.h"
- #pragma warning (disable: 4305) // truncation from 'const double' to 'float'
- extern int w_height;
- extern int w_width;
- // This is how fast our camera moves (Sped up a bit due to normalizing our vectors)
- #define kSpeed 0.1f
- /////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This returns a perpendicular vector from 2 given vectors by taking the cross product.
- /////
- /////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\*
-
- CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
- {
- CVector3 vNormal;
- // Calculate the cross product with the non communitive equation
- vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
- vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
- vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));
- // Return the cross product
- return vNormal;
- }
- /////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This returns the magnitude of a vector
- /////
- /////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\*
- float Magnitude(CVector3 vNormal)
- {
- // Here is the equation: magnitude = sqrt(V.x^2 + V.y^2 + V.z^2) : Where V is the vector
- return (float)sqrt( (vNormal.x * vNormal.x) +
- (vNormal.y * vNormal.y) +
- (vNormal.z * vNormal.z) );
- }
- /////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This returns a normalize vector (A vector exactly of length 1)
- /////
- /////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\*
- CVector3 Normalize(CVector3 vVector)
- {
- // Get the magnitude of our normal
- float magnitude = Magnitude(vVector);
- // Now that we have the magnitude, we can divide our vector by that magnitude.
- // That will make our vector a total length of 1.
- vVector = vVector / magnitude;
-
- // Finally, return our normalized vector
- return vVector;
- }
- ///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\*
- /////
- ///// This is the class constructor
- /////
- ///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\*
- CCamera::CCamera()
- {
- CVector3 vZero = CVector3(0.0, 0.0, 0.0); // Init a vVector to 0 0 0 for our position
- CVector3 vView = CVector3(0.0, 1.0, 0.5); // Init a starting view vVector (looking up and out the screen)
- CVector3 vUp = CVector3(0.0, 0.0, 1.0); // Init a standard up vVector (Rarely ever changes)
- mPos = vZero; // Init the position to zero
- mView = vView; // Init the view to a std starting view
- mUp = vUp; // Init the UpVector
- }
- ///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*
- /////
- ///// This function sets the camera's position and view and up vVector.
- /////
- ///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\*
- void CCamera::PositionCamera(float positionX, float positionY, float positionZ,
- float viewX, float viewY, float viewZ,
- float upVectorX, float upVectorY, float upVectorZ)
- {
- CVector3 vPosition = CVector3(positionX, positionY, positionZ);
- CVector3 vView = CVector3(viewX, viewY, viewZ);
- CVector3 vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);
- // The code above just makes it cleaner to set the variables.
- // Otherwise we would have to set each variable x y and z.
- mPos = vPosition; // Assign the position
- mView = vView; // Assign the view
- mUp = vUpVector; // Assign the up vector
- }
- ///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\*
- /////
- ///// This allows us to look around using the mouse, like in most first person games.
- /////
- ///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\*
- void CCamera::MouseMove()
- {
- POINT mousePos; // This is a window structure that holds an X and Y
- int middleX = w_width >> 1; // This is a binary shift to get half the width
- int middleY = w_height >> 1; // This is a binary shift to get half the height
- float angleY = 0.0f; // This is the direction for looking up or down
- float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
- static float currentRotX = 0.0f;
-
- // Get the mouse's current X,Y position
- GetCursorPos(&mousePos);
-
- // If our cursor is still in the middle, we never moved... so don't update the screen
- if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;
- // Set the mouse position to the middle of our window
- SetCursorPos(middleX, middleY);
- // Get the direction the mouse moved in, but bring the number down to a reasonable amount
- angleY = (float)( (middleX - mousePos.x) ) / 1000.0f;
- angleZ = (float)( (middleY - mousePos.y) ) / 1000.0f;
- // Here we keep track of the current rotation (for up and down) so that
- // we can restrict the camera from doing a full 360 loop.
- currentRotX -= angleZ;
- // If the current rotation (in radians) is greater than 1.0, we want to cap it.
- if(currentRotX > 1.0f)
- currentRotX = 1.0f;
- // Check if the rotation is below -1.0, if so we want to make sure it doesn't continue
- else if(currentRotX < -1.0f)
- currentRotX = -1.0f;
- // Otherwise, we can rotate the view around our position
- else
- {
-
- // To find the axis we need to rotate around for up and down
- // movements, we need to get a perpendicular vector from the
- // camera's view vector and up vector. This will be the axis.
- CVector3 vAxis = Cross(mView - mPos, mUp);
- vAxis = Normalize(vAxis);
- // Rotate around our perpendicular axis and along the y-axis
- RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
- RotateView(angleY, 0, 1, 0);
- }
- }
- void CCamera::RotateAroundPoint(CVector3 vCenter, float angle, float x, float y, float z)
- {
- CVector3 vNewPosition;
- // To rotate our position around a point, what we need to do is find
- // a vector from our position to the center point we will be rotating around.
- // Once we get this vector, then we rotate it along the specified axis with
- // the specified degree. Finally the new vector is added center point that we
- // rotated around (vCenter) to become our new position. That's all it takes.
- // Get the vVector from our position to the center we are rotating around
- CVector3 vPos = mPos - vCenter;
- // Calculate the sine and cosine of the angle once
- float cosTheta = (float)cos(angle);
- float sinTheta = (float)sin(angle);
- // Find the new x position for the new rotated point
- vNewPosition.x = (cosTheta + (1 - cosTheta) * x * x) * vPos.x;
- vNewPosition.x += ((1 - cosTheta) * x * y - z * sinTheta) * vPos.y;
- vNewPosition.x += ((1 - cosTheta) * x * z + y * sinTheta) * vPos.z;
- // Find the new y position for the new rotated point
- vNewPosition.y = ((1 - cosTheta) * x * y + z * sinTheta) * vPos.x;
- vNewPosition.y += (cosTheta + (1 - cosTheta) * y * y) * vPos.y;
- vNewPosition.y += ((1 - cosTheta) * y * z - x * sinTheta) * vPos.z;
- // Find the new z position for the new rotated point
- vNewPosition.z = ((1 - cosTheta) * x * z - y * sinTheta) * vPos.x;
- vNewPosition.z += ((1 - cosTheta) * y * z + x * sinTheta) * vPos.y;
- vNewPosition.z += (cosTheta + (1 - cosTheta) * z * z) * vPos.z;
- // Now we just add the newly rotated vector to our position to set
- // our new rotated position of our camera.
- mPos = vCenter + vNewPosition;
- }
- ///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\*
- /////
- ///// This rotates the view around the position using an axis-angle rotation
- /////
- ///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\*
- void CCamera::RotateView(float angle, float x, float y, float z)
- {
- CVector3 vNewView;
- // Get the view vector (The direction we are facing)
- CVector3 vView = mView - mPos;
- // Calculate the sine and cosine of the angle once
- float cosTheta = (float)cos(angle);
- float sinTheta = (float)sin(angle);
- // Find the new x position for the new rotated point
- vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
- vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
- vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
- // Find the new y position for the new rotated point
- vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
- vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
- vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
- // Find the new z position for the new rotated point
- vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
- vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
- vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
- // Now we just add the newly rotated vector to our position to set
- // our new rotated view of our camera.
- mView = mPos + vNewView;
- }
- ///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\*
- /////
- ///// This strafes the camera left and right depending on the speed (-/+)
- /////
- ///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\*
- void CCamera::StrafeCamera(float speed)
- {
- // Strafing is quite simple if you understand what the cross product is.
- // If you have 2 vectors (say the up vVector and the view vVector) you can
- // use the cross product formula to get a vVector that is 90 degrees from the 2 vectors.
- // For a better explanation on how this works, check out the OpenGL "Normals" tutorial at our site.
- // In our new Update() function, we set the strafing vector (m_vStrafe). Due
- // to the fact that we need this vector for many things including the strafing
- // movement and camera rotation (up and down), we just calculate it once.
- //
- // Like our MoveCamera() function, we add the strafing vector to our current position
- // and view. It's as simple as that. It has already been calculated in Update().
-
- // Add the strafe vector to our position
- mPos.x += m_vStrafe.x * speed;
- mPos.z += m_vStrafe.z * speed;
- // Add the strafe vector to our view
- mView.x += m_vStrafe.x * speed;
- mView.z += m_vStrafe.z * speed;
- }
- ///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*
- /////
- ///// This will move the camera forward or backward depending on the speed
- /////
- ///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\*
- void CCamera::MoveCamera(float speed)
- {
- // Get the current view vector (the direction we are looking)
- CVector3 vVector = mView - mPos;
- // I snuck this change in here! We now normalize our view vector when
- // moving throughout the world. This is a MUST that needs to be done.
- // That way you don't move faster than you strafe, since the strafe vector
- // is normalized too.
- vVector = Normalize(vVector);
-
- mPos.x += vVector.x * speed; // Add our acceleration to our position's X
- mPos.z += vVector.z * speed; // Add our acceleration to our position's Z
- mView.x += vVector.x * speed; // Add our acceleration to our view's X
- mView.z += vVector.z * speed; // Add our acceleration to our view's Z
- }
- // The next 3 functions were added to our camera class. The less code in
- // Main.cpp the better.
- //////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\*
- /////
- ///// This function handles the input faster than in the WinProc()
- /////
- //////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\*
- void CCamera::CheckForMovement()
- {
- // Check if we hit the Up arrow or the 'w' key
- if(GetKeyState(VK_UP) & 0x80) {
- // Move our camera forward by a positive SPEED
- MoveCamera(kSpeed);
- }
- // Check if we hit the Down arrow or the 's' key
- if(GetKeyState(VK_DOWN) & 0x80) {
- // Move our camera backward by a negative SPEED
- MoveCamera(-kSpeed);
- }
- // Check if we hit the Left arrow or the 'a' key
- if(GetKeyState(VK_LEFT) & 0x80) {
- // Strafe the camera left
- //StrafeCamera(-kSpeed);
- RotateAroundPoint(mView, kSpeed, 0, 1, 0);
- //RotateView(0.1, 0, 0.5,0);
- }
- // Check if we hit the Right arrow or the 'd' key
- // if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80) {
- if(GetKeyState(VK_RIGHT) & 0x80) {
- // Strafe the camera right
- //StrafeCamera(kSpeed);
- RotateAroundPoint(mView, -kSpeed, 0, 1, 0);
- //RotateView(0.1, 0, -0.5,0);
- }
- }
- ///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\*
- /////
- ///// This updates the camera's view and strafe vector
- /////
- ///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\*
- void CCamera::Update()
- {
- // Below we calculate the strafe vector every time we update
- // the camera. This is because many functions use it so we might
- // as well calculate it only once.
- // Initialize a variable for the cross product result
- CVector3 vCross = Cross(mView - mPos, mUp);
- // Normalize the strafe vector
- m_vStrafe = Normalize(vCross);
-
- CheckForMovement();
- }
- ///////////////////////////////// LOOK \\\\\\\\\\\\\\\\*
- /////
- ///// This updates the camera according to the
- /////
- ///////////////////////////////// LOOK \\\\\\\\\\\\\\\\*
- void CCamera::Look()
- {
- // Give openGL our camera position, then camera view, then camera up vector
- gluLookAt(mPos.x, mPos.y, mPos.z,
- mView.x, mView.y, mView.z,
- mUp.x, mUp.y, mUp.z);
- }