// Demonstration of tracking zoom.

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

const double PI = 3.1415926535;

int window_width = 600;
int window_height = 600;

const GLfloat gold[] = { 0.8, 0.8, 0.0, 1.0 };
const GLfloat blue[] = { 0.2, 0.2, 1.0, 1.0 };
const GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
const GLfloat light_pos[] = { 0.0, 0.0, 0.0, 1.0 };

const double TRANS_INIT = 75.0;
double trans = TRANS_INIT;
double zoom = 5.0;

double x[] = { -2.0, 2.0,  2.0, -2.0 };
double y[] = {  2.0, 2.0, -2.0, -2.0 };

void display () {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(zoom, GLfloat(window_width)/GLfloat(window_height), 1.0, 200.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0, 0.0, - trans);

	glPushMatrix();
		glTranslatef(0.0, 0.0, 0.3 * TRANS_INIT);
		glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
	glPopMatrix();

	glMaterialfv(GL_FRONT, GL_AMBIENT, gold);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, gold);

	for (int p = 0; p < 4; p++) {
		glPushMatrix();
		glTranslatef(x[p], y[p], - 1.5 * TRANS_INIT);
		for (int q = 0; q < 100; q++) {
			glTranslatef(0.0, 0.0, 3.0);
			glutSolidCube(0.5);
		}
		glPopMatrix();
	}

	glMaterialfv(GL_FRONT, GL_AMBIENT, blue);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
	glPushMatrix();
		glTranslatef(2.0, 0.0, 0.0);
		glScalef(1.0, 9.0, 1.0);
		glutSolidCube(0.5);
		glTranslatef(-4.0, 0.0, 0.0);
		glutSolidCube(0.5);
	glPopMatrix();
	glPushMatrix();
		glTranslatef(0.0, 2.0, 0.0);
		glScalef(9.0, 1.0, 1.0);
		glutSolidCube(0.5);
		glTranslatef(0.0, -4.0, 0.0);
		glutSolidCube(0.5);
	glPopMatrix();

	glutSwapBuffers();
	glFlush();
}

void move () {
	trans *= 0.99;
	zoom = (360.0 / PI ) * atan(5.0 / trans);
	if (zoom > 150.0) {
		glutIdleFunc(NULL);
		return;
	}
	glutPostRedisplay();
}

void keyboard (unsigned char key, int x, int y) {
	if (key == ' ') {
		trans = TRANS_INIT;
		glutIdleFunc(move);
	}
	else if (key == 27)
		exit(0);
}

void resize_window (int w, int h) {
	window_width = w;
	window_height = h;
	glViewport(0, 0, window_width, window_height);
	glutPostRedisplay();
}

void init () {
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
	glLightfv(GL_LIGHT0, GL_SPECULAR, white);
	glEnable(GL_DEPTH_TEST);
	glutDisplayFunc(display);
	glutIdleFunc(move);
	glutKeyboardFunc(keyboard);
	glutReshapeFunc(resize_window);
}

int main (int argc, char *argv[]) {

	// Initialize OpenGL and enter loop.
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(window_width, window_height);
	glutCreateWindow("Vertigo");
	init();
	cout << "Press space to repeat, ESC to escape." << endl;
	glutMainLoop();
	return 0;
}


