#include "CCamera.h" /** This is the class constructor*/ CCamera::CCamera() { Point3<float> vZero = Point3<float>(0.0, 0.0, 0.0); // Init a vVector to 0 0 0 for our position Point3<float> vView = Point3<float>(1.0, 0, 0); // Init a starting view vVector (looking up and out the screen) Point3<float> vUp = Point3<float>(0.0, 0.0, 1.0); // Init a standard up vVector (Rarely ever changes) //determina il centro di rotazione della camera posizionato nel centro della mappa,serve per fare ruotare la mappa Point3<float> centro_di_rotazione = Point3<float>(25.0, 70.0, 25.0); m_vcentrorotazione = centro_di_rotazione; m_vPosition = vZero; // Init the position to zero m_vView = vView; // Init the view to a std starting view m_vUpVector = vUp; // Init the UpVector } /** This function sets the camera's position and view and up vVector.*/ void CCamera::PositionCamera(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ) { Point3<float> vPosition = Point3<float>(positionX, positionY, positionZ); Point3<float> vView = Point3<float>(viewX, viewY, viewZ); Point3<float> vUpVector = Point3<float>(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. m_vPosition = vPosition; // Assign the position m_vView = vView; // Assign the view m_vUpVector = vUpVector; // Assign the up vector } /** This rotates the view around the position using an axis-angle rotation */ void CCamera::RotateView(float angle, float x, float y, float z) { // Point3<float> vNewView; // Get the view vector (The direction we are facing) Point3<float> vView = m_vView -m_vPosition; // Calculate the sine and cosine of the angle once float cosTheta = (float)cos(angle); float sinTheta = (float)sin(angle); float newX,newY,newZ; // Find the new x position for the new rotated point newX = (cosTheta + (1 -cosTheta) * x * x) * vView.x() ; newX += ((1 -cosTheta) * x * y -z * sinTheta) * vView.y(); newX += ((1 -cosTheta) * x * z + y * sinTheta) * vView.z(); // Find the new y position for the new rotated point newY = ((1 -cosTheta) * x * y + z * sinTheta) * vView.x(); newY += (cosTheta + (1 -cosTheta) * y * y) * vView.y(); newY += ((1 -cosTheta) * y * z -x * sinTheta) * vView.z(); // Find the new z position for the new rotated point newZ = ((1 -cosTheta) * x * z -y * sinTheta) * vView.x(); newZ += ((1 -cosTheta) * y * z + x * sinTheta) * vView.y(); newZ += (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. Point3<float> vNewView = Point3<float>(newX,newY,newZ); m_vView = m_vPosition + vNewView; } /** This will move the camera forward or backward depending on the speed */ void CCamera::MoveCamera(float speed) { // Get our view vector (The direciton we are facing) Point3<float> vVector = m_vView -m_vPosition; m_vPosition += vVector * speed; // Add our acceleration to our position's X //m_vPosition += vVector * speed; // Add our acceleration to our position's Z m_vView += vVector * speed; // Add our acceleration to our view's X //m_vView += vVector * speed; // Add our acceleration to our view's Z } /** Posizione la camera dell'ambiente OpenGl */ void CCamera::Draw() { // Give openGL our camera position, then camera view, then camera up vector gluLookAt(m_vPosition.x(), m_vPosition.y(), m_vPosition.z(), m_vView.x(), m_vView.y(), m_vView.z(), m_vUpVector.x(), m_vUpVector.y(), m_vUpVector.z()); } /** This rotates the position around a given point */ void CCamera::RotateAroundPoint(Point3<float> vCenter, float angle, float x, float y, float z) { //Point3<float> 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 Point3<float> vPos = m_vPosition -vCenter; float newX,newY,newZ; // 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 newX = (cosTheta + (1 -cosTheta) * x * x) * vPos.x(); newX += ((1 -cosTheta) * x * y -z * sinTheta) * vPos.y(); newX += ((1 -cosTheta) * x * z + y * sinTheta) * vPos.z(); // Find the new y position for the new rotated point newY = ((1 -cosTheta) * x * y + z * sinTheta) * vPos.x(); newY += (cosTheta + (1 -cosTheta) * y * y) * vPos.y(); newY += ((1 -cosTheta) * y * z -x * sinTheta) * vPos.z(); // Find the new z position for the new rotated point newZ = ((1 -cosTheta) * x * z -y * sinTheta) * vPos.x(); newZ += ((1 -cosTheta) * y * z + x * sinTheta) * vPos.y(); newZ += (cosTheta + (1 -cosTheta) * z * z) * vPos.z(); Point3<float> vNewPosition = Point3<float>(newX,newY,newZ); // Now we just add the newly rotated vector to our position to set // our new rotated position of our camera. m_vPosition = vCenter + vNewPosition; } ///////////////////////////////////////////////////////////////////////////////// // // * QUICK NOTES * // // Now we have the ability to look around our world with the mouse! It's a great // addition to our camera class isn't it? Not much code either. // // Let me further explain what makes this work. What we are doing is continuously // putting the cursor in the middle of the screen every time we move the mouse, but // before we do this, we get the new position that it moved. Now that we have the // position it moved from the center, we can do some simple math to find out which // way we need to move/rotate the camera. Lets do an example: // // Lets say we changed our SCREEN_WIDTH and SCREEN_HEIGHT to 640 480. // That would make our middle point at (320, 240). THe '*' is the cursor position. // We will call it P1 (Point 1) // // ----------------------------------- // | | // | | // | | // | | // | | // | * P1 (320, 240) | // | | // | | // | | // | | // | | // | | // ----------------------------------- // // Now, when we move the mouse, we store that position of where we moved. // Let's say we moved the mouse diagonally up and left a little bit. Our new // point would be, let's say P2 (319, 239) // // ----------------------------------- // | | // | | // | | // | | // | * P2 (319, 239) | (Figure is not pixel perfect :) ) // | \ | // | * (320, 240) | // | | // | | // | | // | | // | | // | | // ----------------------------------- // // Well, logic tells us that we need to rotate the camera to the left a bit, // and move the camera up a bit as well right??? Of course right. // // Well, the math is simple to find that out. We just subtract P1 - P2. // That will give us a new x and y. That is called the vector. // // What will the vector of those 2 points be then? // // (320 - 319, 240 - 239) = (1, 1) // // Now we have a vector of (1, 1). In our case, those numbers are too high // when we are dealing with radians, not degrees. To remedy this, we need to // make the number a bit smaller, I just divide by a number like 1000. Now // we have a vector of (0.001, 0.001). We want to pass the X value in as our // Y-axis rotation, BUT we need to negate it. Because if we rotate by a positive number // it will move the camera to the RIGHT, and we want to go to the left. This will take care // of when we move the mouse right too. If the vector is negative, it will make it positive. // // You'll notice we added some math functions at the top of this file. These help us // determine the axis that we need to rotate around for up and down. By grabbing // a 90 degree penpendicular vector to the side of the camera, we can then use // that as our axis to rotate around. This took a bit to figure out at first. // It wasn't as simple as just rotating around the x-axis, because we are walking // around the x and z axis all the time, so the rotations need to change axises. // // Notice that with the new Point3<float> additions, we can't say: // // Point3<float> vVector = {0, 0, 0}; // // It must be: // // Point3<float> vVector = CVector(0, 0, 0); // // This is because we have a default constructor, so there is no more {}'s. // We can now create a Point3<float> on the fly, without having to directory assing // a variable name to it. The default copy constructor does all the work. //