
//I did not write any of the code in the included files
#include <Gl/glut.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
//#include "Vec.h"

//declare methods
void set_initial_state(void);//initialise world
void for_rendering(void); //rendering function
void display_world_axes(void);
void glutKeyboardFunc(void);
void drawSun(void);
void drawTank(void);
void drawFloor(void);
void drawWorld(void);
void drawTree(int xCoordinate,int zCoordinate);
void myIdleFunction(void);
void keyboard(unsigned char key,int x, int y);
void drawHouse(int xCoordinate,int zCoordinate);
void drawCubeHouse(int xCoordinate,int zCoordinate);
float tankdirection=0.0,tankspeed=0.0;

//global variables
float camx=100,camy=100,a,at=0.01,xshift=0,zshift=0,dt=0.01,PI=3.1415,t = 0,r;

//Camera motion, boolean. 1=enabled, 0= disabled
bool cameramotion = 0,drawBall=0;

/////////////////////////////////////////////////////////////////////////////
//Main Method. Invoked when program is ran
void main(int argc, char** argv)
{	//initalise openGL with c main () parameters
	glutInit(&argc,argv);

	//Set display mode, request double buffering with RGB color scheme
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	
	// Set initial window size
	glutInitWindowSize(800,600);
	
	//Set initial window position
	glutInitWindowPosition(0,0);
	
	//Draw window
	glutCreateWindow("Press p to rotate camera, + - to zoom in and out");
	
	//Set rendering function
	glutDisplayFunc(for_rendering);

	//Set idle function
	glutIdleFunc(myIdleFunction);

	//Set Keyboard listener
	glutKeyboardFunc(keyboard);

	//initialise world
	set_initial_state();

	//enter processing loop
	glutMainLoop();

	//Set function to run when idle
	glutIdleFunc(myIdleFunction); 
}

///////////////////////////////////////////////////////////////////////////////
//method to animate variables
void myIdleFunction(void)
{	//if camera is set to move
	if (cameramotion==1)
	{	
		//t loops from -50 to 50 in steps of 0.01 if the camera is set to move
		t=t+dt;
		if (t>50) { t = 1; dt = -0.01; };
		if (t<-50) { t = 0; dt = 0.01; };
	};

	//a loops from -360 to 360 in steps of 0.01
	a=a+at;
	if (a>360)  at = -0.01;
	if (a<-360) at = 0.01 ;

	//move tank
	xshift=xshift+tankspeed*cos(tankdirection);
	zshift=zshift+tankspeed*sin(tankdirection);

	glutPostRedisplay();}

/////////////////////////////////////////////////////////////////////////////
//Keyboard listener
void keyboard(unsigned char key,int x, int y)
{	
	switch(key)
	{
		case '8': //speed increases
		tankspeed++;
		break;
		case '2': //speed decreases
		tankspeed--;
		break;
		case '6': //turn left
		tankdirection=tankdirection+0.1;
		break;
		case '4': //turn right
		tankdirection=tankdirection-0.1;
		break;
		case '5':  //stops the object
		tankspeed=0;
		break;
		case '+'://zoom in
		r=r-5;
		break;
		case '-'://zoom out
		r=r+5;
		break;
		case ' '://Fire
		drawBall=1;
		break;
		case 'p'://stop camera moving
		if (cameramotion==0) 
			cameramotion=1;	
		else cameramotion=0;
		break;
		case 'r'://Reset
		set_initial_state();
		default : break;
	}
}
/////////////////////////////////////////////////////////////////////////////////
//initialise world
void set_initial_state(void)
{   
	glClearColor(1.0,1.0,1.0,0.0);

	//enable depth testing
	glEnable(GL_DEPTH_TEST); 

	//set depth sorting algorythm
	glDepthFunc(GL_LEQUAL);

	glClearDepth(1.0f);
	glEnable(GL_CULL_FACE);

	glColor3f(0.0,0.0,0.0);          
	r=200,tankdirection=0,tankspeed=0;
	//float xshift=0,zshift=0,dt=0.01,PI=3.1415,t = 0,r=300;
	
	//default, camera is moving
	cameramotion = 1;
	glCullFace(GL_BACK);

	//perspective view to make distant objects smaller
	glMatrixMode(GL_PROJECTION);
	
	//load identity matrix
	glLoadIdentity(); 
	//perspective projection, field of view = 100 degrees
	gluPerspective(100,800/600,0,800);
	
}
//////////////////////////////////////////////////////////////////////////////////
//rendering function - refreshes the display with new values
void for_rendering(void)      
{
	
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	
	
	//set camera position
	gluLookAt(r*cos(t),r,r*sin(t),0,0,0,0,1,0);

//	display_world_axes();
 
	drawWorld();
	drawTank();	
//	if (drawBall=1) drawBullet();
//	drawText("Hi");

	glutSwapBuffers();

}
//////////////////////////////////////////////////////////////////////////////////
//draw world method (draws all objects
void drawWorld (void)
{	

	drawFloor();
	drawCubeHouse(-400,-300);
	drawCubeHouse(-400,300);
	drawCubeHouse(-400,00);
	drawHouse(200,200);
	drawHouse(400,200);
	drawHouse(000,200);
	
	//DRAW A NEATLY ALLIGNED WOODS
	drawTree(250,-300);
	drawTree(150,-300);
	drawTree(50,-300);
	drawTree(-50,-300);
	drawTree(250,-400);
	drawTree(150,-400);
	drawTree(50,-400);
	drawTree(-50,-400);
	drawTree(250,-500);
	drawTree(150,-500);
	drawTree(50,-500);
	drawTree(-50,-500);
	drawTree(250,-200);
	drawTree(150,-200);
	drawTree(50,-200);
	drawTree(-50,-200);
	
	drawSun();
}


///////////////////////////////////////////////////////////////////////////////////
//draw world axis
void display_world_axes(void)
{
	glPushAttrib(GL_CURRENT_BIT);
	glColor3f(0.0,0.0,1.0); 
	glBegin(GL_LINES);
	  glVertex3f(-1000.0,0.0,0.0);  glVertex3f(+300.0,0.0,0.0); // the x-axis 
	  glVertex3f(0.0,-1000.0,0.0);  glVertex3f(0.0,+300.0,0.0); // the y-axis 
	  glVertex3f(0.0,0.0,-1000.0);  glVertex3f(0.0,0.0,+300.0); // the z-axis 
	glEnd();
	glPopAttrib();
}
////////////////////////////////////////////////////////////////////////////////////
//draw floor
void drawFloor()
{
	glPushMatrix();// A House Base
		glPushMatrix();// The Floor
		glColor3f(51/255,0.1,0.1);
		glTranslatef(0,-1,0);
		glScalef(50,0.1,50);
		glutSolidCube(20);
	glPopMatrix();
}

//////////////////////////////////////////////////////////////////////////////////////
//method to draw a house with individual points
void drawHouse(int xCoordinate,int zCoordinate)
{
	glPushMatrix();
		glTranslatef(xCoordinate,00,zCoordinate);
		glScalef(10,10,10);
		glBegin(GL_QUADS); // 

		//front pane
			glColor3f(0.0, 0.0, 1.0);//blue
			glVertex3f(10, 0,0);
			glVertex3f(10, 10,0);
		//	glVertex3f(5, 15,0);
 			glVertex3f(0, 10,0); 
			glVertex3f(0, 0,0);

		//left pane
			glColor3f(1.0, 0.0, 0.0); //red
			glVertex3f(0, 0,0); 
 			glVertex3f(0, 0,10);
			glVertex3f(0, 10,10); 
			glVertex3f(0, 10,0);		

		//Back pane
			glColor3f(1.0, 1.0, 0.0); //yellow
			glVertex3f(10, 0,10); 
 			glVertex3f(10, 10,10);
		//	glVertex3f(5, 15,0);
			glVertex3f(0, 10,10); 
 			glVertex3f(0, 0,10);		

		//right pane
			glColor3f(0.0, 1.0, 0.0); //green
			glVertex3f(10, 0,0); 
 			glVertex3f(10, 0,10); 
 			glVertex3f(10, 10,10); 
 			glVertex3f(10, 10,0);		

		//roof left
			glColor3f(0.1, 0.1, 0.1); //Black
			glVertex3f(-2,8,-2);
 			glVertex3f(-2, 8,12); 
 			glVertex3f(5, 15,12); 
 			glVertex3f(5, 15,-2);	

		//roof Right
			glColor3f(0.1, 0.1, 0.1); //green
			glVertex3f(12,8,-2);
 			glVertex3f(12, 8,12); 
 			glVertex3f(5, 15,12); 
 			glVertex3f(5, 15,-2);
		glEnd();

	glPopMatrix();
}

////////////////////////////////////////////////////////////////////////////////
// draw house method. takes x and z coordinate
void drawCubeHouse(int xCoordinate,int zCoordinate)
{
	glPushMatrix();// A House Base
		glColor3f(0.8,0.3,0.3);
		glTranslatef(xCoordinate,00,zCoordinate);
		glScalef(1,1.5,1);
		glutSolidCube(200);
		glPushMatrix();// A Roof
		 	glColor3f(0.1,1,1);
			glTranslatef(0,100,0);
			glScalef(220,30,220);
			glutSolidCube(1);
		glPopMatrix();
	glPopMatrix();
}
////////////////////////////////////////////////////////////////////////////////
// draw tree method. takes x and z coordinate
void drawTree(int xCoordinate,int zCoordinate)
{
	glPushMatrix();// Trunk
		
		glTranslatef(xCoordinate,0,zCoordinate);
		glScalef(1,10,1);
		glColor3f(128,64,0);//brown
		glutSolidCube(30);
		glPushMatrix();// Leaves
		 	glColor3f(00,1,0);
			glTranslatef(0,10,0);
			glScalef(5,1,5);
			glutSolidSphere(10,10,10);
		glPopMatrix();
	glPopMatrix();
}

/////////////////////////////////////////////////////////////////////////////////////
//method to draw sun
void drawSun(void)
{	if (360*sin(a)>0){
	glPushMatrix();// The Sun
		
	//Move sun around world
		glRotatef(a,0,0,1);
		glTranslatef(500*cos(a),500*sin(a),500*cos(a));
		glColor3f(0.8,0.8,0.4);

	//draw sun as a sphere
		glutSolidSphere(20,20,20);

		//make the sun a light source
		float amb[4] = { 0.1, 0.1, 0.1, 1.0 };      // The background color of the light.
		float dif[4] = { 0.8, 0.8, 0.6, 1.0 };      // The foreground color of the light.  
		float pos[4] = { 300*cos(a), 300*sin(a), 0, 0 };            // Position of the light.
		
		glClearColor(0.2,0.2,0.7,1);
		glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);     // Registers the light's ambient color
		glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);     // Registers the light's diffuse color
		glLightfv(GL_LIGHT0, GL_POSITION, pos);     // Registers the light's position
		glEnable(GL_LIGHT0);                        // Enable light zero
		glEnable(GL_COLOR_MATERIAL);                // Apply glColor() to lighting calculations
		glEnable(GL_LIGHTING);                      // Enable lighting in general
		glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS, 1);

	glPopMatrix();};
}

/////////////////////////////////////////////////////////////////////////////////////////
//method to draw tank
void drawTank(void)
{
	glPushMatrix();	//The Tank
		glTranslatef(xshift,0,zshift);
		glRotatef(-1*60*tankdirection,0,1,0);
		glPushMatrix();//TANK WHEELS
			glScalef(10,2,8);
			glColor3f(1,1,1);
			glutSolidCube(10); 
		glPopMatrix();

 		glPushMatrix();//TANK BODY
			glTranslatef(1,20,1);
			glScalef(8,2,6);
			glColor3f(0,1,0);
			glutSolidCube(10); 
		glPopMatrix();

 		glPushMatrix();//TANK HUMP
			glTranslatef(3,20,2);
			glScalef(2,2,2);
			glColor3f(0,1,0);
			glutSolidSphere(10,20,5); 
		glPopMatrix(); 	
		
		glPushMatrix();//TANK GUN
			glTranslatef(50,20,0);
			glScalef(6,1,1);
			glColor3f(0,2,0);
			glutSolidCube(10); 
		glPopMatrix();
	glPopMatrix();
}

