#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.
//