#include <stdlib.h>
#include <stdio.h>
#include <gl/glut.h>
#include <math.h>
#include <sys\timeb.h>

#define XWINSIZE 600 
#define YWINSIZE 600 
#define XWINPOS 100
#define YWINPOS 100

#define SPEED 0.05f
/*these must be constants for the mass to work, change at will*/

#define radius1 1.5
#define radius2 3.0

double q=20.0; /*size of cube, multiple of 4 please*/

double mass=3.0*radius1*radius1*radius1;
double mass2=3.0*radius2*radius2*radius2;



/*all of the initial conditions, some will change during program*/

double tint=5.0;
double dt;
double xi=4.0;
double yi=16.0;
double zi=6.0;
double vxi=-15.0;
double vyi=11.0;
double vzi=-14.0;
double vy, vx, vz;
double yaccel=-10;
double xaccel=0;
double zaccel=0;
double dampy=.96;
double dampx=.96;
double dampz=.96;

double tint2=5.0;
double dt2;
double xi2=14.0;
double yi2=16.0;
double zi2=14.0;
double vxi2=16.0;
double vyi2=12.0;
double vzi2=13.0;
double vy2, vx2, vz2;
double yaccel2=-10;
double xaccel2=0;
double zaccel2=0;

double temp; /*used to swap velocities*/



double pos[3];
double pos2[3];
double prevpos[3]; /*this was the fix for collisions*/
double prevpos2[3];
double floorpos[3];
double floorpos2[3];

double unit[3];
double unit2[3];
double dotprod;
double dotprod2;


typedef struct
{
	float x;
	float y;
	float z;
} vector;

struct camera
{
	vector pos;
	vector view;
	vector up;
};

struct camera Camera;
int frame = 0, time, timebase = 0;

struct camera setcamposition(struct camera Cam,
		float posx, float posy, float posz,
		float viewx, float viewy, float viewz,
		float upx, float upy, float upz)
{
	Cam.pos.x = posx;
	Cam.pos.y = posy;
	Cam.pos.z = posz;
	
	Cam.view.x = viewx;
	Cam.view.y = viewy;
	Cam.view.z = viewz;

	Cam.up.x = upx;
	Cam.up.y = upy;
	Cam.up.z = upz;

	return Cam;
}

struct camera movecamera(struct camera Cam, float speed)
{
	vector vpvec;
	vpvec.x = Cam.view.x - Cam.pos.x;
	vpvec.y = Cam.view.y - Cam.pos.y;
	vpvec.z = Cam.view.z - Cam.pos.z;

	Cam.pos.x = Cam.pos.x + vpvec.x * speed;
	Cam.pos.z = Cam.pos.z + vpvec.z * speed;
	
	Cam.view.x = Cam.view.x + vpvec.x * speed;
	Cam.view.z = Cam.view.z + vpvec.z * speed;

	return Cam;
}

struct camera strafecamera(struct camera Cam, float speed)
{
	vector vpvec;
	vpvec.x = Cam.view.x - Cam.pos.x;
	vpvec.y = Cam.view.y - Cam.pos.y;
	vpvec.z = Cam.view.z - Cam.pos.z;

	Cam.pos.x = Cam.pos.x - vpvec.z * speed;
	Cam.pos.z = Cam.pos.z + vpvec.x * speed;

	Cam.view.x = Cam.view.x - vpvec.z * speed;
	Cam.view.z = Cam.view.z + vpvec.x * speed;

	return Cam;
}

struct camera rotatecamera(struct camera Cam, float speed)
{
	vector vpvec;
	vpvec.x = Cam.view.x - Cam.pos.x;
	vpvec.y = Cam.view.y - Cam.pos.y;
	vpvec.z = Cam.view.z - Cam.pos.z;

	Cam.view.z = (float) (Cam.pos.z + sin(speed) * vpvec.x + cos(speed) * vpvec.z);
	Cam.view.x = (float) (Cam.pos.x + cos(speed) * vpvec.x - sin(speed) * vpvec.z);

	return Cam;
}

struct camera upcamera(struct camera Cam, float speed)
{
	Cam.view.y = Cam.view.y + 2 * speed; 

	if((Cam.view.y - Cam.pos.y) > 22) Cam.view.y = Cam.pos.y + 22;
	if((Cam.view.y - Cam.pos.y) < -22) Cam.view.y = Cam.pos.y - 22;
	
	return Cam;
}

struct camera flycamera(struct camera Cam, float speed)
{
	Cam.view.y = Cam.view.y + speed;
	Cam.pos.y = Cam.pos.y + speed;

	return Cam;
}

void init()
{
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, XWINSIZE/YWINSIZE, 0.1f, 100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	Camera = setcamposition(Camera, q/2.0, q/2.0f, 2*q, q/2.0, q/2.0f, 0, 0, 1, 0);

}


void reshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//gluPerspective(45.0f, XWINSIZE/YWINSIZE, 0.1f, 100.0f); 
	gluPerspective(45.0f, w/h, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z,
		  Camera.view.x, Camera.view.y, Camera.view.z,
		  Camera.up.x, Camera.up.y, Camera.up.z);
}

void drawgrid()
{
	float i;

	glBegin(GL_LINES);
	for(i = 0; i <= q; i += 4)
	{
		glColor3f(0.1f, 0.1f, 0.1f);
		glVertex3f(0, q, i);
		glVertex3f(q, q, i);
		glVertex3f(i, q, 0);
		glVertex3f(i, q, q);
		glVertex3f(0, i, 0);
		glVertex3f(q, i, 0);
		glVertex3f(i, 0, 0);
		glVertex3f(i, q, 0);
		glVertex3f(0, i, q);
		glVertex3f(q, i, q);
		glVertex3f(i, 0, q);
		glVertex3f(i, q, q);
		glVertex3f(0, 0, i);
		glVertex3f(0, q, i);
		glVertex3f(0, i, 0);
		glVertex3f(0, i, q);
		glVertex3f(q, 0, i);
		glVertex3f(q, q, i);
		glVertex3f(q, i, 0);
		glVertex3f(q, i, q);
	}

	glEnd();
}


void drawfunc()
{
	float x;
	float z;

	glColor3f(0.4f, 0.4f, 0.4f);
	glBegin(GL_LINES);
    
	for(x = 0; x < q; x += .5)
    for(z = 0; z < q; z += .5)
    {
    glVertex3f(x, (x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2)), z);
    glVertex3f(x+0.5, (x+0.5-q/2)*pow(1.05, -pow(x+0.5-q/2,2)-pow(z+0.5-q/2,2)), z+0.5);
    glVertex3f(x+0.5, (x+0.5-q/2)*pow(1.05, -pow(x+0.5-q/2,2)-pow(z-q/2,2)), z);
    glVertex3f(x, (x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z+0.5-q/2,2)), z+0.5);
    
    }
    glEnd();
    }


void indicator(void)
{
glBegin(GL_LINES);
	glColor3f(0.0f, 0.1f, .5f);
	glVertex3f(pos[0],pos[1],q);
	glVertex3f(pos[0],pos[1],0.0);

	glVertex3f(0.0,pos[1],pos[2]);
	glVertex3f(q,pos[1],pos[2]);

	glVertex3f(pos[0],q,pos[2]);
	glVertex3f(pos[0],0.0,pos[2]);
	
	glColor3f(0.38f,0.0f,0.5f);
	glVertex3f(pos2[0],pos2[1],q);
	glVertex3f(pos2[0],pos2[1],0.0);

	glVertex3f(0.0,pos2[1],pos2[2]);
	glVertex3f(q,pos2[1],pos2[2]);

	glVertex3f(pos2[0],q,pos2[2]);
	glVertex3f(pos2[0],0.0,pos2[2]);
	glEnd(); 
}

void cube(void)
{
	glColor3f(0.3f, 0.3f, 1.0f);
	glBegin(GL_LINES);
	glVertex3f(0,0,0);
	glVertex3f(0,q,0);
	glVertex3f(0,q,0);
	glVertex3f(0,q,q);
	glVertex3f(0,q,q);
	glVertex3f(0,0,q);
	glVertex3f(0,0,q);
	glVertex3f(0,0,0);
	glVertex3f(q,0,0);
	glVertex3f(q,q,0);
	glVertex3f(q,q,0);
	glVertex3f(q,q,q);
	glVertex3f(q,q,q);
	glVertex3f(q,0,q);
	glVertex3f(q,0,q);
	glVertex3f(q,0,0);
	glVertex3f(0,0,0);
	glVertex3f(q,0,0);
	glVertex3f(0,0,q);
	glVertex3f(q,0,q);
	glVertex3f(0,q,q);
	glVertex3f(q,q,q);
	glVertex3f(0,q,0);
	glVertex3f(q,q,0);
	glEnd();
}

void drawSphere(double radius)
{
int th, ta, dth, dta;
dth = (int)((350*10-10)/200);  
dta = (int)((350-10)/200);
for(th=10, ta=-90; th < 350*10, ta < 90; th=th+dth, ta=ta+dta)
{
glBegin(GL_LINE_STRIP);
glVertex3f
(
cos(th*.01745 )*cos(ta*.01745)*radius, /* unit sphere radius vector */  
sin(th*.01745)*cos(ta*.01745)*radius,
sin(ta*.01745)*radius
);
glColor3f
(
cos(th*.01745 )*cos(ta*.01745)+.5, /* unit sphere radius vector */  
sin(th*.01745)*cos(ta*.01745)+.5,
sin(ta*.01745)+.5
);
}
glEnd();
}

int floortest()
{
double r;
double theta;
double x;
double z;

for(r=0, theta=0; r<radius1, theta<360.0*30.0; r=r+radius1/400.0, theta=theta+360*30.0/400.0)
{
x=pos[0]+r*cos(theta*.01745);
z=pos[2]+r*sin(theta*.01745);
glBegin(GL_POINTS);
glColor3f(0.3f, 0.3f, 1.0f);
glVertex3f(x,(x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2)),z);
glEnd();

if((sqrt((pos[0]-x)*(pos[0]-x)+(pos[1]-((x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2))))*(pos[1]-((x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2))))+(pos[2]-z)*(pos[2]-z)))<=radius1)
{
floorpos[0]=x;
floorpos[1]=(x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2));
floorpos[2]=z;
return 1;
}
}
return 0;
}

int floortest2()
{
double r;
double theta;
double x;
double z;

for(r=0, theta=0; r<radius2, theta<360.0*30.0; r=r+radius2/400.0, theta=theta+360*30.0/400.0)
{
x=pos2[0]+r*cos(theta*.01745);
z=pos2[2]+r*sin(theta*.01745);
glBegin(GL_POINTS);
glColor3f(0.3f, 0.3f, 1.0f);
glVertex3f(x,(x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2)),z);
glEnd();

if((sqrt((pos2[0]-x)*(pos2[0]-x)+(pos2[1]-((x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2))))*(pos2[1]-((x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2))))+(pos2[2]-z)*(pos2[2]-z)))<=radius2)
{
floorpos2[0]=x;
floorpos2[1]=(x-q/2)*pow(1.05, -pow(x-q/2,2)-pow(z-q/2,2));
floorpos2[2]=z;
return 1;
}
}
return 0;
}

void drawballs(double a, double b, double c, double d, double e, double f)
{
	
	glPushMatrix();
	glColor3f(0.0f, 0.2f, 1.0f);
	glTranslatef(a,b,c);
	drawSphere(radius1);
	glFlush();
	glPopMatrix();

	glPushMatrix();
	glColor3f(0.750f, 0.0f, 1.0f);
	glTranslatef(d,e,f);
	drawSphere(radius2);
	glFlush();
	glPopMatrix();
}

void balls(void)
{

double magic;
double k[3];

struct timeb a;
struct timeb c;
double tchange;


struct timeb a2;
struct timeb c2;
double tchange2;

/*time initializer and changer*/
if ((tint==5.0))
{
	ftime(& a);
	tint=a.time+a.millitm/1000.0;
	tchange=tint+.01;
}
else
{
	ftime(& c);
	tchange=c.time+c.millitm/1000.0;
}

if ((tint2==5.0))
{
	ftime(& a2);
	tint2=a2.time+a2.millitm/1000.0;
	tchange2=tint2+.01;
}
else
{
	ftime(& c2);
	tchange2=c2.time+c2.millitm/1000.0;
}

dt=(tchange-tint);
dt2=(tchange2-tint2);
/*kinematics for motion*/
pos[0]=xi;
pos[1]=yi;
pos[2]=zi;
pos[0]=pos[0]+(vxi*(dt)+xaccel*(dt)*(dt)/2.0);
pos[1]=pos[1]+(vyi*(dt)+yaccel*(dt)*(dt)/2.0);
pos[2]=pos[2]+(vzi*(dt)+zaccel*(dt)*(dt)/2.0);

pos2[0]=xi2;
pos2[1]=yi2;
pos2[2]=zi2;
pos2[0]=pos2[0]+(vxi2*(dt2)+xaccel2*(dt2)*(dt2)/2.0);
pos2[1]=pos2[1]+(vyi2*(dt2)+yaccel2*(dt2)*(dt2)/2.0);
pos2[2]=pos2[2]+(vzi2*(dt2)+zaccel2*(dt2)*(dt2)/2.0);


/*collision and kinematics for bounce*/
/*notice the prevpos fix for the new position*/
if(floortest()==1)
{
vz=vzi+zaccel*(dt);
vzi=vz;
vy=vyi+yaccel*(dt);
vyi=vy;
vx=vxi+xaccel*(dt);
vxi=vx;

unit[0]=(-pos[0]+floorpos[0])/sqrt((pos[0]-floorpos[0])*(pos[0]-floorpos[0])+(pos[1]-floorpos[1])*(pos[1]-floorpos[1])+(pos[2]-floorpos[2])*(pos[2]-floorpos[2]));
unit[1]=(-pos[1]+floorpos[1])/sqrt((pos[0]-floorpos[0])*(pos[0]-floorpos[0])+(pos[1]-floorpos[1])*(pos[1]-floorpos[1])+(pos[2]-floorpos[2])*(pos[2]-floorpos[2]));
unit[2]=(-pos[2]+floorpos[2])/sqrt((pos[0]-floorpos[0])*(pos[0]-floorpos[0])+(pos[1]-floorpos[1])*(pos[1]-floorpos[1])+(pos[2]-floorpos[2])*(pos[2]-floorpos[2]));

dotprod=(unit[0]*(vx)+unit[1]*(vy)+unit[2]*(vz));

vxi=-(dampx*(dotprod*unit[0]+dotprod*unit[0])-vxi);
vyi=-(dampy*(dotprod*unit[1]+dotprod*unit[1])-vyi);
vzi=-(dampz*(dotprod*unit[2]+dotprod*unit[2])-vzi);

tint=5.0;

zi=floorpos[2]-1.0005*unit[2]*radius1;
yi=floorpos[1]-1.0005*unit[1]*radius1;
xi=floorpos[0]-1.0005*unit[0]*radius1;

pos[0]=xi;//prevpos[0];
pos[1]=yi;//prevpos[1];
pos[2]=zi;//prevpos[2];
}



if(floortest2()==1)
{
vz2=vzi2+zaccel2*(dt2);
vzi2=vz2;
vy2=vyi2+yaccel2*(dt2);
vyi2=vy2;
vx2=vxi2+xaccel2*(dt2);
vxi2=vx2;

unit2[0]=(-pos2[0]+floorpos2[0])/sqrt((pos2[0]-floorpos2[0])*(pos2[0]-floorpos2[0])+(pos2[1]-floorpos2[1])*(pos2[1]-floorpos2[1])+(pos2[2]-floorpos2[2])*(pos2[2]-floorpos2[2]));
unit2[1]=(-pos2[1]+floorpos2[1])/sqrt((pos2[0]-floorpos2[0])*(pos2[0]-floorpos2[0])+(pos2[1]-floorpos2[1])*(pos2[1]-floorpos2[1])+(pos2[2]-floorpos2[2])*(pos2[2]-floorpos2[2]));
unit2[2]=(-pos2[2]+floorpos2[2])/sqrt((pos2[0]-floorpos2[0])*(pos2[0]-floorpos2[0])+(pos2[1]-floorpos2[1])*(pos2[1]-floorpos2[1])+(pos2[2]-floorpos2[2])*(pos2[2]-floorpos2[2]));

dotprod2=(unit2[0]*(vx2)+unit2[1]*(vy2)+unit2[2]*(vz2));

vxi2=-(dampx*(dotprod2*unit2[0]+dotprod2*unit2[0])-vxi2);
vyi2=-(dampy*(dotprod2*unit2[1]+dotprod2*unit2[1])-vyi2);
vzi2=-(dampz*(dotprod2*unit2[2]+dotprod2*unit2[2])-vzi2);

tint2=5.0;

zi2=floorpos2[2]-1.0005*unit2[2]*radius2;
yi2=floorpos2[1]-1.0005*unit2[1]*radius2;
xi2=floorpos2[0]-1.0005*unit2[0]*radius2;

pos2[0]=xi2;//prevpos2[0];
pos2[1]=yi2;//prevpos2[1];
pos2[2]=zi2;//prevpos2[2];
}


if((pos[2]<(0.0+radius1)) || pos[2]>(q-radius1))
{
vz=vzi+zaccel*(dt);
vzi=-dampz*vz;
vy=vyi+yaccel*(dt);
vyi=vy;
vx=vxi+xaccel*(dt);
vxi=vx;
tint=5.0;



zi=prevpos[2];
yi=prevpos[1];
xi=prevpos[0];

pos[0]=prevpos[0];
pos[1]=prevpos[1];
pos[2]=prevpos[2];
}

if(pos2[2]<(0.0+radius2) || pos2[2]>(q-radius2))
{
vz2=vzi2+zaccel2*(dt2);
vzi2=-dampz*vz2;
vy2=vyi2+yaccel2*(dt2);
vyi2=vy2;
vx2=vxi2+xaccel2*(dt2);
vxi2=vx2;
tint2=5.0;


zi2=prevpos2[2];
yi2=prevpos2[1];
xi2=prevpos2[0];

pos2[0]=prevpos2[0];
pos2[1]=prevpos2[1];
pos2[2]=prevpos2[2];

}

if(/*pos[1]<(0.0+radius1) || */pos[1]>(q-radius1))
{
vz=vzi+zaccel*(dt);
vzi=vz;
vy=vyi+yaccel*(dt);
vyi=-dampy*vy;
vx=vxi+xaccel*(dt);
vxi=vx;
tint=5.0;


zi=prevpos[2];
yi=prevpos[1];
xi=prevpos[0];

pos[0]=prevpos[0];
pos[1]=prevpos[1];
pos[2]=prevpos[2];
}

if(/*pos2[1]<(0.0+radius2) || */pos2[1]>(q-radius2))
{
vz2=vzi2+zaccel2*(dt2);
vzi2=vz2;
vy2=vyi2+yaccel2*(dt2);
vyi2=-dampy*vy2;
vx2=vxi2+xaccel2*(dt2);
vxi2=vx2;
tint2=5.0;

zi2=prevpos2[2];
yi2=prevpos2[1];
xi2=prevpos2[0];

pos2[0]=prevpos2[0];
pos2[1]=prevpos2[1];
pos2[2]=prevpos2[2];

}

if(pos[0]<(0.0+radius1) || pos[0]>(q-radius1))
{
vz=vzi+zaccel*(dt);
vzi=vz;
vy=vyi+yaccel*(dt);
vyi=vy;
vx=vxi+xaccel*(dt);
vxi=-dampx*vx;
tint=5.0;

zi=prevpos[2];
yi=prevpos[1];
xi=prevpos[0];

pos[0]=prevpos[0];
pos[1]=prevpos[1];
pos[2]=prevpos[2];
}

if(pos2[0]<(0.0+radius2) || pos2[0]>(q-radius2))
{
vz2=vzi2+zaccel2*(dt2);
vzi2=vz2;
vy2=vyi2+yaccel2*(dt2);
vyi2=vy2;
vx2=vxi2+xaccel2*(dt2);
vxi2=-dampx*vx2;
tint2=5.0;
zi2=prevpos2[2];
yi2=prevpos2[1];
xi2=prevpos2[0];

pos2[0]=prevpos2[0];
pos2[1]=prevpos2[1];
pos2[2]=prevpos2[2];

}

/*ball collision*/

if(sqrt((pos[0]-pos2[0])*(pos[0]-pos2[0])+(pos[1]-pos2[1])*(pos[1]-pos2[1])+(pos[2]-pos2[2])*(pos[2]-pos2[2]))<=(radius1+radius2))
{
vz2=vzi2+zaccel2*(dt2);
vzi2=vz2;
vz=vzi+zaccel*(dt);
vzi=vz;
vy2=vyi2+yaccel2*(dt2);
vyi2=vy2;
vy=vyi+yaccel*(dt);
vyi=vy;
vx=vxi+xaccel*(dt);
vxi=vx;
vx2=vxi2+xaccel2*(dt2);
vxi2=vx2;
\
k[0]=(pos[0]-pos2[0])/(radius1+radius2);
k[1]=(pos[1]-pos2[1])/(radius1+radius2);
k[2]=(pos[2]-pos2[2])/(radius1+radius2);

magic=2*(k[0]*(vx-vx2)+k[1]*(vy-vy2)+k[2]*(vz-vz2))/(1/mass+1/mass2);

vxi=-(magic*k[0]/mass-vxi);
vyi=-(magic*k[1]/mass-vyi);
vzi=-(magic*k[2]/mass-vzi);

vxi2=-(magic*k[0]/(-mass2)-vxi2);
vyi2=-(magic*k[1]/(-mass2)-vyi2);
vzi2=-(magic*k[2]/(-mass2)-vzi2);

xi=prevpos[0];
yi=prevpos[1];
xi2=prevpos2[0];
yi2=prevpos2[1];
zi=prevpos[2];
zi2=prevpos2[2];

pos[0]=prevpos[0];
pos[1]=prevpos[1];
pos[2]=prevpos[2];

pos2[0]=prevpos2[0];
pos2[1]=prevpos2[1];
pos2[2]=prevpos2[2];

tint=5.0;
tint2=5.0;
}

prevpos[0]=pos[0];
prevpos[1]=pos[1];
prevpos[2]=pos[2];
prevpos2[0]=pos2[0];
prevpos2[1]=pos2[1];
prevpos2[2]=pos2[2];



}



void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	gluLookAt(Camera.pos.x, Camera.pos.y, Camera.pos.z,
		  Camera.view.x, Camera.view.y, Camera.view.z,
		  Camera.up.x, Camera.up.y, Camera.up.z);
		
	balls(); /*math, but does draw some reference points, can be removed*/
	
	
	/*graphics*/
	drawballs(pos[0], pos[1], pos[2], pos2[0], pos2[1], pos2[2]);
	drawgrid();
	cube();
	drawballs(pos[0], pos[1], pos[2], pos2[0], pos2[1], pos2[2]);
	//indicator();
	drawfunc();	
	glFlush();
	glutSwapBuffers();
}

void idle(void)
{
	glutPostRedisplay();
}


void keyboard(unsigned char key, int x, int y)
{
	switch(key)
	{
		case 'i':
			Camera = upcamera(Camera, +4*SPEED);
			break;
		case 'k':
			Camera = upcamera(Camera, -4*SPEED);
			break;
		case 'l':
			Camera = rotatecamera(Camera, +SPEED);
			break;
		case 'j': 
			Camera = rotatecamera(Camera, -SPEED);	
			break;
		case 'w':
			Camera = movecamera(Camera, +SPEED);
			break;
		case 's':
			Camera = movecamera(Camera, -SPEED);
			break;
		case 'a':
			Camera = strafecamera(Camera, -SPEED);
			break;
		case 'd':
			Camera = strafecamera(Camera, +SPEED);
			break;
		case 'r':
			Camera = flycamera(Camera, +4*SPEED);
			break;
		case 'f':
			Camera = flycamera(Camera, -4*SPEED);
			break;
		case 27:
			exit(0);
			break;
		case 'q':
			exit(0);
			break;
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(XWINSIZE, YWINSIZE);
	glutInitWindowPosition(XWINPOS, YWINPOS);
	glutCreateWindow("Curtis and Jeff Project");

	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	//glutMotionFunc(motion);
	glutIdleFunc(idle);
	//glutMouseFunc(mouse);
	glutKeyboardFunc(keyboard);
	glutMainLoop();

	return 0;
}
