#include <math.h>
#include <stdio.h>
#include <windows.h>
#include <gl/glut.h>
#include "glm.h"
#include "materials.h"
#include "ReadBMP.h" 

typedef float vec3_t[3];
typedef float VertexArray[3];
typedef float NormalArray[3];
typedef float TextureCoordsArray[2];


vec3_t color[] = {
	{1.0f, 0.0f, 0.0f},		//red
	{0.0f, 1.0f, 0.0f},		//green
	{0.0f, 0.0f, 1.0f},		//blue
	{1.0f, 1.0f, 0.0f},		//yellow
	{1.0f, 0.0f, 1.0f},		//magenta
	{0.0f, 1.0f, 1.0f},		//cyan
	{1.0f, 1.0f, 1.0f},		//white
	{.25f, .25f, .25f},		//dark gray
	{.75f, .75f, .75f},		//light gray
	{.60f, .40f, .12f},		//brown
	{.60f, .40f, .70f},		//barney purple
	{.98f, .625f, .12f},	//pumpkin orange
	{.98f, .04f, .70f}		//pastel pink
};

vec3_t rot = {0,0,0};
vec3_t eye = {0,0,0};
vec3_t center = {0,0,0};
vec3_t rotate = {0,0,0};

float	size=3.;
float	theta=.0;
float	thetaDelta=.125;
float	eyeDelta=.125;
float	scale=1.0;
float	scaleDelta=1.125;
float   anitheta=.0;
float   anithetaDelta=.125;
double	PI=atan(1.0)*4.0;

int		mouseX = 0;
int		mouseY = 0;
int		mouseState = 0;
int		mouseButton = 0; 
int		projection = 0;
int		depthtest = 1;
int		frontface = 0;
int		displaymode = 1;
int		displayflag = GLM_SMOOTH;
int		shade = 1;
int		cullface = 1;
int		localviewer = 0;
int		twoside = 0;
int		wireframe = 0;
int		windowWidth;
int		windowHeight;
int		lighting=1;
int		filecount=9;
float	modelX = 0;
float	modelY = 0;
float	modelZ = 0;

MyImageStruct	myImage; 

GLint	aniOn = 0;
GLfloat movtheta=0.0;

GLfloat mat_ambient[] = { 0.91, 0.1, 0.11, 1.0};
GLfloat mat_diffuse[] = { 0.43, 0.37, 0.57, 1.0 };
GLfloat mat_specular[] = { 0.33, 0.33, 0.52, 1.0 };
GLfloat mat_emission[] = { 0.0, 0.0, 0.0, 0.0 };
GLfloat mat_shininess[] = { 10.0 };//밝기


GLfloat light_Kambient[] = { 0.2, 0.2, 0.2, 1.0};
GLfloat light_position[] = { 0.0, 0.0, 50.0, 1.0 };
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0};
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0};
GLfloat light_specular[] ={ 1.0, 1.0, 1.0, 1.0};
GLfloat light_spotDir[] = { -1.0, -1.0, -1.0 };

//Fog Effect
GLfloat fogColor[4] = {0.2, 0.2, 0.2, 1.0};


void new_material(float* material)
{
    mat_ambient[0] = material[0];
    mat_ambient[1] = material[1];
    mat_ambient[2] = material[2];
    mat_ambient[3] = material[3];
    mat_diffuse[0] = material[4];
    mat_diffuse[1] = material[5];
    mat_diffuse[2] = material[6];
    mat_diffuse[3] = material[7];
    mat_specular[0] = material[8];
    mat_specular[1] = material[9];
    mat_specular[2] = material[10];
    mat_specular[3] = material[11];
    mat_shininess[0] = material[12];
	glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
	glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
}

void myInit(void)
{    
	glClearColor(0, 0, 0, 1.0);
	glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,localviewer);
	glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,twoside);
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,light_Kambient);

	glLightfv(GL_LIGHT0,GL_POSITION,light_position);
	glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
	glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);


	glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,light_spotDir);
	glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,180.0f);
	glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,30.0f);	
	glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
	glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
	glMaterialfv(GL_FRONT,GL_EMISSION,mat_emission);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	
	glShadeModel(GL_SMOOTH);

	glEnable(GL_CULL_FACE);		
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_NORMALIZE);

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	glPolygonMode(GL_BACK, GL_LINE);
	glPolygonMode(GL_FRONT, GL_FILL);

	//FOG
	glEnable (GL_FOG);
	glFogfv (GL_FOG_COLOR, fogColor);
 	glFogi (GL_FOG_MODE, GL_LINEAR);
	glFogf(GL_FOG_START, 10);
	glFogf(GL_FOG_END, -10);
 	glFogf (GL_FOG_DENSITY, 0.3);
 	//glHint (GL_FOG_HINT, GL_NICEST);


	ReadBMP("Sun.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 1);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("수성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 2);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("금성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 3);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("지구.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 4);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("화성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 5);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("목성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 6);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("토성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 7);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("천왕성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 8);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("해왕성.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 9);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

	ReadBMP("Belt.bmp", &myImage); 
	glBindTexture(GL_TEXTURE_2D, 10);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, myImage.Width, myImage.Height, 
		0, GL_RGB, GL_UNSIGNED_BYTE, myImage.Pixels);

}

GLMmodel *te = glmReadOBJ("data/111.obj");


void DrawTexturedMesh(VertexArray *vertices, NormalArray *normalVectors, GLint *faces, GLint nFaces, GLint verticesPerFace,TextureCoordsArray *textureCoords, GLint *textureIndexes) { 
	int  j, k, n=0, f; 
	if(wireframe) f = GL_LINE_LOOP;
	else f = GL_POLYGON;
	for (j=0; j<nFaces; j++) { 
		glBegin(f); 
		glNormal3fv(normalVectors[j]); 
		for (k=0; k<verticesPerFace; k++) { 
			glTexCoord2fv(textureCoords[textureIndexes[n]]); 
			glVertex3fv(vertices[faces[n++]]); 
		} 
		glEnd(); 
	} 
}

//-------------------------------------------------------------------
void DrawSphere(float radius, int numberSlices, int numberSides)
{
	GLint                numberVertices;
	GLint                numberFaces;
	VertexArray         *vertices;
	NormalArray         *normals;
	GLint               *faces; 
	TextureCoordsArray  *textureCoordinates; 
	GLint               *textureIndexes;
	int                  j, k, n, m;
	float                x, y, z;
	float                u, v;
	float                uInc, vInc;

	// allocate the needed memory for the data
	numberVertices = (numberSides+1) * (numberSlices+1);
	numberFaces = (numberSides) * (numberSlices);
	vertices = (VertexArray *) malloc( sizeof(VertexArray) * numberVertices);
	normals = (NormalArray *) malloc( sizeof(NormalArray) * numberFaces);
	faces = (GLint *) malloc( sizeof(GLint) * numberFaces * 4);
	textureCoordinates = (TextureCoordsArray *)
	malloc( sizeof(TextureCoordsArray) * numberVertices);
	textureIndexes = (GLint *) malloc( sizeof(GLint) * numberFaces * 4);

	if (vertices != 0 && normals != 0 && faces != 0 && 
		textureCoordinates != 0 && textureIndexes != 0) {
		vInc = 2.*PI/numberSides;
		uInc = PI/numberSlices;
		n = 0;
		for (k=0, u = -0.5*PI; k<=numberSlices; k++, u += uInc) {
			for (j=0, v = 0.0; j<=numberSides; j++, v += vInc) {
				// Generate the vertices and texture coordinates around this slice
				vertices[n][0] = radius*cos(u)*cos(v);
				vertices[n][1] = radius*cos(u)*sin(v);
				vertices[n][2] = radius*sin(u);

				textureCoordinates[n][0] = (float) j / (float) numberSides;
				textureCoordinates[n][1] = (float) k / (float) numberSlices;

				if (n < numberFaces) {
					// Calculate the normal vector for the face using the middle
					//   point on the face
					x = radius*cos(u+uInc*0.5)*cos(v+0.5*vInc);
					y = radius*cos(u+uInc*0.5)*sin(v+0.5*vInc);
					z = radius*sin(u+uInc*0.5);
					normals[n][0] = x / radius;
					normals[n][1] = y / radius;
					normals[n][2] = z / radius;
				}
				n++;
			}
		}

		// Create the faces
		n = 0;
		m = 0;
		for (k=0; k<numberSlices; k++) {
			for (j=0; j<numberSides; j++) {
				// Generate the face and texture indexes for this face
				faces[n] = textureIndexes[n] = m;                n++;
				faces[n] = textureIndexes[n] = m+1;              n++;
				faces[n] = textureIndexes[n] = m+1+numberSides+1;  n++;
				faces[n] = textureIndexes[n] = m+numberSides+1;  n++;
				m++;
			}
			m++;
		}
		DrawTexturedMesh(vertices, normals, faces, numberFaces, 4,
			textureCoordinates, textureIndexes); 
	}

	// Reclaim the allocated memory
	if (vertices != NULL)           free( vertices );
	if (normals != NULL)            free( normals  );
	if (faces != NULL)              free( faces    );
	if (textureCoordinates != NULL) free( textureCoordinates );
	if (textureIndexes != NULL)     free( textureIndexes );
}



void myDisplay (void)
{
	int sunsize = 2.5;


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	if(!projection)
		gluLookAt(eye[0], eye[1]+1, eye[2]+7, center[0], center[1], center[2], 0, 1, 0);
	//gluLookAt(0, 0, 0, 0, 0, 0, 0, 0, 0);
	
    glRotatef(rot[0], 1.0f, 0.0f, 0.0f);
	glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
	glRotatef(rot[2], 0.0f, 0.0f, 1.0f);
	glScalef(scale, scale, scale);
	glRotatef(-90., 1., 0., 0.);
	
	glPushMatrix(); //Object
		glDisable(GL_TEXTURE_2D);
		glTranslatef(0+modelX,-15+modelY,modelZ);	//키보드 입력시 이동 값
		glScalef(0.01,0.01,0.01);
		glRotatef(90,0.,0.,-1.);
		glRotatef(90,1.,0.,0.);
		glRotatef(rotate[2],0.,0.,1.);
		glRotatef(rotate[1],0.,1.,0.);
		glmDraw(te, GLM_WIREFRAME);
		glEnable(GL_TEXTURE_2D);
	glPopMatrix();
	

	//태양
	glPushMatrix(); 
		glTranslatef(0,0,0);
		glRotatef(movtheta/25, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 1);
		DrawSphere(sunsize*2,20,20);
	glPopMatrix();

	//수성
	glPushMatrix();
		glRotatef(movtheta/0.87, 0, 0, 1);
		glTranslatef(0,3+sunsize,0);
		glRotatef(movtheta/58, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 2);
		DrawSphere(0.04,20,20);
	glPopMatrix();

	//금성
	glPushMatrix();
		glRotatef(movtheta/2.24, 0, 0, 1);
		glTranslatef(0,4+sunsize,0);
		glRotatef(movtheta/-243, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 3);
		DrawSphere(0.08,20,20);
	glPopMatrix();

	//지구
	glPushMatrix();
		glRotatef(movtheta/3.65, 0, 0, 1);
		glTranslatef(0,6+sunsize,0);
		glRotatef(movtheta/1, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 4);
		DrawSphere(0.09,20,20);
	glPopMatrix();

	//화성
	glPushMatrix();
		glRotatef(movtheta/6.86, 0, 0, 1);
		glTranslatef(0,8+sunsize,0);
		glRotatef(movtheta/1, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 5);
		DrawSphere(0.05,20,20);
	glPopMatrix();

	//목성
	glPushMatrix();
		glRotatef(movtheta/43, 0, 0, 1);
		glTranslatef(0,12+sunsize,0);
		glRotatef(movtheta/0.4, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 6);
		DrawSphere(1.02,20,20);
	glPopMatrix();

	//토성
	glPushMatrix();

		glRotatef(movtheta/109, 0, 0, 1);
		glTranslatef(0,17+sunsize,0);
		glRotatef(movtheta/0.35, 0, 0, 1);
				
		glPushMatrix();
			glBindTexture(GL_TEXTURE_2D, 7);
			DrawSphere(0.78,20,20);
		glPopMatrix();

	glPopMatrix();

	//천왕성
	glPushMatrix();
		glRotatef(movtheta/306, 0, 0, 1);
		glTranslatef(0,20+sunsize,0);
		glRotatef(movtheta/-0.75, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 8);
		DrawSphere(0.37,20,20);
	glPopMatrix();

	//해왕성
	glPushMatrix();
		glRotatef(movtheta/598, 0, 0, 1);
		glTranslatef(0,25+sunsize,0);
		glRotatef(movtheta/0.67, 0, 0, 1);
		glBindTexture(GL_TEXTURE_2D, 9);
		DrawSphere(0.355,20,20);
	glPopMatrix();

	glFlush();
    glutSwapBuffers();
}

void myIdle(void)
{
	movtheta+=1;
	glutPostRedisplay();
}


void myLookAt(int key)
{
	if(key == GLUT_KEY_UP) {
		modelY +=0.1;
		eye[2]-=0.1;
		center[2]-=0.1;
	}
	else if(key == GLUT_KEY_DOWN) {		
		modelY -=0.1;
		
		eye[2]+=0.1;
		center[2]+=0.1;
	}
	else if(key == GLUT_KEY_LEFT)
	{
		eye[0]-=0.1;
		center[0]-=0.1;
		modelX -=0.1;		
	}
	else if(key == GLUT_KEY_RIGHT)
	{
		eye[0]+=0.1;
		center[0]+=0.1;
		modelX +=0.1;		
	}
}

void myResize (int width, int height)
{
    if (!height) return;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	if(projection) {
		glOrtho(-size, size, -size, size, -size, size); 
		eye[2] = 0.;
	}
    else {
		gluPerspective(60., (float)width/height, .01, 1000.);
		eye[2] = 10.;
		myLookAt(0);
	}
    glEnable(GL_DEPTH_TEST);
	windowWidth=width;
	windowHeight=height;
}

void mySKeyboard (int key, int x, int y)
{
    switch (key) {
		case GLUT_KEY_UP : break;
		case GLUT_KEY_DOWN : break;
		case GLUT_KEY_LEFT : 
			//theta-=thetaDelta; 
			break;
		case GLUT_KEY_RIGHT : 
			//theta+=thetaDelta; 
			break;
		default : return;
    }
	myLookAt(key);
	glutPostRedisplay();
}

void myKeyboard (unsigned char key, int x, int y)
{
	switch (key)
	{
		case 'p':
			projection = !projection;
			myResize(windowWidth, windowHeight);
		break;
		case 'd':
			depthtest = !depthtest;
			if(depthtest) glEnable(GL_DEPTH_TEST);
			else glDisable(GL_DEPTH_TEST);
		break;
		case 'f':
			frontface = !frontface;
			if(frontface) glFrontFace(GL_CW);
			else glFrontFace(GL_CCW);
		break;
		case 'v':
			localviewer = !localviewer;
			glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,localviewer);
		break;
		case 't':
			twoside = !twoside;
			glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,twoside);
		break;
		case 's':
			shade = !shade;
			if(shade) glShadeModel(GL_SMOOTH);
			else glShadeModel(GL_FLAT);
		break;
		case 'c':
			cullface = !cullface;
			if(cullface) glEnable(GL_CULL_FACE);
			else glDisable(GL_CULL_FACE);
		break;
		case 'l':
			lighting = !lighting;
			if(lighting) glEnable(GL_LIGHTING);
			else glDisable(GL_LIGHTING);
		break;
		case 'm':
			displaymode++;
			if(displaymode == 3) displaymode=0;
			if(displaymode == 0) displayflag = GLM_WIREFRAME;
			else if(displaymode == 1) displayflag = GLM_SMOOTH;
			else if(displaymode == 2) displayflag = GLM_SMOOTH | GLM_MATERIAL;
		break;
		case 'z':
			scale*=scaleDelta;
			eye[0]/=scaleDelta;
			eye[1]/=scaleDelta;
			eye[2]/=scaleDelta;
			center[0]/=scaleDelta;
			center[1]/=scaleDelta;
			center[2]/=scaleDelta;			
			/*eye[0]/=scaleDelta*scaleDelta;
			eye[1]/=scaleDelta*scaleDelta;
			eye[2]/=scaleDelta*scaleDelta;
			center[0]/=scaleDelta*scaleDelta;
			center[1]/=scaleDelta*scaleDelta;
			center[2]/=scaleDelta*scaleDelta;*/
			
		break;
		case 'x':
			scale/=scaleDelta;
			
			eye[0]*=scaleDelta;
			eye[1]*=scaleDelta;
			eye[2]*=scaleDelta;
			center[0]*=scaleDelta;
			center[1]*=scaleDelta;
			center[2]*=scaleDelta;			
			/*eye[0]*=scaleDelta*scaleDelta;
			eye[1]*=scaleDelta*scaleDelta;
			eye[2]*=scaleDelta*scaleDelta;
			center[0]*=scaleDelta*scaleDelta;
			center[1]*=scaleDelta*scaleDelta;
			center[2]*=scaleDelta*scaleDelta;*/
			
		break;
		case 'q':
			modelZ-=0.1;
			eye[1]-=0.1;
			center[1]-=0.1;
		break;
		case 'w':
			modelZ+=0.1;
			eye[1]+=0.1;
			center[1]+=0.1;
		break;
		case ' ':
			aniOn = !aniOn;
			if(aniOn) glutIdleFunc(myIdle);
			else glutIdleFunc(NULL);
		break;
		case 'y':
			rotate[2]+=5;
			eye[1]+=.001;
			center[1]-=0.15;
			break;
		case 'h':
			rotate[2]-=5;
			eye[1]-=.001;
			center[1]+=0.15;
			break;
		case 'g':
			rotate[1]+=5;
			eye[0]-=.05;
			center[0]-=0.3;
			break;
		case 'j':
			rotate[1]-=5;
			eye[0]+=0.05;
			center[0]+=0.3;
			break;

	}
	glutPostRedisplay();
}

void myMouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
		mouseState=state;
		mouseButton=btn;
		mouseX=x;
		mouseY=y;
	}
	else if(btn==GLUT_LEFT_BUTTON && state == GLUT_UP) {
		mouseState=-1;
	}
	else return;
	glutPostRedisplay();
}

void myMotion(int x, int y)
{
	if(mouseButton == GLUT_LEFT_BUTTON && mouseState == GLUT_DOWN) {
		rot[1] -= (mouseX - x)/5.;		
		rot[0] -= (mouseY - y)/5.;
		/*center[0] += (mouseX - x)/5.;
		center[1] += (mouseY - y)/5.;*/
		glutPostRedisplay();
		mouseX=x;
		mouseY=y;
	}
	//}
	//else if(mouseButton == GLUT_RIGHT_BUTTON && mouseState == GLUT_DOWN) {
	//	eye[2] = eye[2]-cos(theta)*(mouseX - x)/5;
	//	eye[0] = eye[0]+sin(theta)*(mouseX - x)/5.;
	//	
	//	center[2] = eye[2]-cos(theta);
	//	center[0] = eye[0]+sin(theta);
	//	/*
	//	center[0] += (mouseX - x)/5.;		
	//	center[0] += (mouseX - y)/5.;		

	//	center[0] += (mouseX - x)/5.;		
	//	center[0] += (mouseX - y)/5.;*/
	//	glutPostRedisplay();
	//	mouseX=x;
	//	mouseY=y;
	//}
}


void main (void)
{
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(500,500);
    glutCreateWindow("SpaceMovement");
    glutDisplayFunc(myDisplay);
    glutReshapeFunc(myResize);
    glutKeyboardFunc(myKeyboard);
    glutSpecialFunc(mySKeyboard);
	glutMouseFunc(myMouse);
	glutMotionFunc(myMotion);
	myInit();
	glutMainLoop();
}