```// include file for 'Camera.h'

#include << GL/glut.h>
#include << math.h>
#include << iostream.h>

//  << Support Classes for Camera >>
//@@@@@@@@@@@@@@@@@@ Point3 class @@@@@@@@@@@@@@@@@
class Point3{
public:
float x,y,z;
void set(float dx, float dy, float dz){x = dx; y = dy; z = dz;}
void set(Point3& p){x = p.x; y = p.y; z = p.z;}
Point3(float xx, float yy, float zz){x = xx; y = yy; z = zz;}
Point3(){x = y = z = 0;}
void build4tuple(float v[])
{// load 4-tuple with this point: v[3] = 1 for homogeneous
v[0] = x; v[1] = y; v[2] = z; v[3] = 1.0f;
}
};

//@@@@@@@@@@@@@@@@@@ Vector3 class @@@@@@@@@@@@@@@@
class Vector3{
public:
float x,y,z;
void set(float dx, float dy, float dz){ x = dx; y = dy; z = dz;}
void set(Vector3& v){ x = v.x; y = v.y; z = v.z;}
void flip(){x = -x; y = -y; z = -z;} // reverse this vector
void setDiff(Point3& a, Point3& b)//set to difference a - b
{ x = a.x - b.x; y = a.y - b.y; z = a.z - b.z;}
void normalize()//adjust this vector to unit length
{
double sizeSq = x * x + y * y + z * z;
if(sizeSq < 0.0000001)
{
cerr << "\nnormalize() sees vector (0,0,0)!";
return; // does nothing to zero vectors;
}
float scaleFactor = 1.0/(float)sqrt(sizeSq);
x *= scaleFactor; y *= scaleFactor; z *= scaleFactor;
}
Vector3(float xx, float yy, float zz){x = xx; y = yy; z = zz;}
Vector3(Vector3& v){x = v.x; y = v.y; z = v.z;}
Vector3(){x = y = z = 0;} //default constructor
Vector3 cross(Vector3 b) //return this cross b
{
Vector3 c(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x);
return c;
}
float dot(Vector3 b) // return this dotted with b
{return x * b.x + y * b.y + z * b.z;}
};

class Camera{
private:
Point3 eye;
Vector3 u,v,n;
double viewAngle, aspect, nearDist, farDist; // view volume shape
void setModelViewMatrix(); // tell OpenGL where the Camera is

public:
Camera(){};
//Camera(){u.set(1, 0, 0); v.set(0, 1, 0); n.set(0, 0, 1);};
// default constructor
void set(Point3 eye, Point3 look, Vector3 up); // like gluLookAt()
void roll(float angle); // roll it
void pitch(float angle); // increase pitch
void yaw(float angle); // yaw it
void slide(float delU, float delV, float delN); // slide it
void setShape(float vAng, float asp, float nearD, float farD);
};

void Camera :: setModelViewMatrix(void)
{ // load modelview matrix with existing Camera values
float m[16];
Vector3 eVec(eye.x, eye.y, eye.z); // a vector version of eye
m[0] =  u.x; m[4] =  u.y; m[8]  =  u.z;  m[12] = -eVec.dot(u);
m[1] =  v.x; m[5] =  v.y; m[9]  =  v.z;  m[13] = -eVec.dot(v);
m[2] =  n.x; m[6] =  n.y; m[10] =  n.z;  m[14] = -eVec.dot(n);
m[3] =  0;   m[7] =  0;   m[11] =  0;    m[15] = 1.0;
glMatrixMode(GL_MODELVIEW);
}

void Camera :: set(Point3 Eye, Point3 look, Vector3 up)
{	// create a modelview matrix and send it to OpenGL
Vector3 t;
eye.set(Eye); // store the given eye position
n.set(eye.x - look.x, eye.y - look.y, eye.z - look.z); // make n
//t.set(up.y*n.z - up.z*n.y, up.z*n.x - up.x*n.z, up.x*n.y - up.y*n.x);
u.set(up.y*n.z - up.z*n.y, up.z*n.x - up.x*n.z, up.x*n.y - up.y*n.x);
//Vector3 t(up.cross(n));
//u.set(t);                     // make u = up X n
//u.set(up.cross(n));           // make u = up X n
n.normalize(); u.normalize(); // make them unit length
v.set(n.y*u.z - n.z*u.y, n.z*u.x - n.x*u.z, n.x*u.y - n.y*u.x);
//t = up.cross(n);
//v.set(t);                     // make v =  n X u
//v.set(n.cross(u));            // make v =  n X u
setModelViewMatrix();         // tell OpenGL
}

void Camera :: setShape(float vAng, float asp, float nearD, float farD)
{ // set shape of the view volume and set up the projection matrix
viewAngle = vAng; aspect = asp; nearDist = nearD; farDist = farD;
glMatrixMode(GL_PROJECTION);
gluPerspective(viewAngle, aspect, nearDist, farDist);
}

void Camera :: slide(float delU, float delV, float delN)
{
eye.x += delU * u.x + delV * v.x + delN * n.x;
eye.y += delU * u.y + delV * v.y + delN * n.y;
eye.z += delU * u.z + delV * v.z + delN * n.z;
setModelViewMatrix();
}

void Camera :: roll(float angle)
{ // roll the camera through angle degrees
float cs = cos( angle / 180 * 3.14159265 );
float sn = sin( angle / 180 * 3.14159265 );
Vector3 t = u;   // remember old u
u.set(cs*t.x - sn*v.x, cs*t.y - sn*v.y, cs*t.z - sn*v.z );
v.set(sn*t.x + cs*v.x, sn*t.y + cs*v.y, sn*t.z + cs*v.z );
setModelViewMatrix();
}

void Camera :: pitch(float angle)
{ // pitch the camera through angle degrees
float cs = cos( angle / 180 * 3.14159265 );
float sn = sin( angle / 180 * 3.14159265 );
Vector3 t = n;   // remember old n
n.set(cs*t.x + sn*v.x, cs*t.y + sn*v.y, cs*t.z + sn*v.z );
v.set(-sn*t.x + cs*v.x, -sn*t.y + cs*v.y, -sn*t.z + cs*v.z );
setModelViewMatrix();
}

void Camera :: yaw(float angle)
{ // yaw the camera through angle degrees
float cs = cos( angle / 180 * 3.14159265 );
float sn = sin( angle / 180 * 3.14159265 );
Vector3 t = u;   // remember old n
u.set(cs*t.x + sn*n.x, cs*t.y + sn*n.y, cs*t.z + sn*n.z );
n.set(-sn*t.x + cs*n.x, -sn*t.y + cs*n.y, -sn*t.z + cs*n.z );
setModelViewMatrix();
}
```