#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>

int orthographic=1;
float angle = 0;

int showProjection=0;
float viewRotY = 0, viewRotX = 0;


void drawTriangle(void)
	{
	glPushMatrix();
	glRotatef(angle,0.0,1.0,0.0);
	glBegin(GL_TRIANGLES);
	 glVertex3f(-1.0, -1.0, 0.0);
	 glVertex3f(1.0, -1.0, 0.0);
	 glVertex3f(0.0, 1.0, 0.0);
	glEnd();
	glPopMatrix();
	}


void drawGroundPlane(void)
	{
	glColor3f(0.25, 0.25, 0.25);
	glBegin(GL_QUADS);
	glVertex3f(-5.0, -1.0, 0.0);
	glVertex3f(5.0, -1.0, 0.0);
	glVertex3f(5.0, -1.0, -10.0);
	glVertex3f(-5.0, -1.0, -10.0);
	glEnd();
	}



void drawCoordinateAxes(void)
	{
	glLineWidth(2.0);
	glColor3f(0.6, 0.0, 0.0);
	glBegin(GL_LINES);
	 glVertex3f(-10.0, 0.0, 0.0);
	 glVertex3f(10.0, 0.0, 0.0);
	 glVertex3f(0.0, -10.0, 0.0);
	 glVertex3f(0.0, 10.0, 0.0);
	 glVertex3f(0.0, 0.0, -10.0);
	 glVertex3f(0.0, 0.0, 10.0);
	glEnd();
	glLineWidth(1.0);
	glColor3f(1.0, 0.0, 0.0);
	glRasterPos3f(10.0, 0.0, 0.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'X');
	glRasterPos3f(0.0, 10.0, 0.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'Y');
	glRasterPos3f(0.0, 0.0, 10.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'Z');
	}

void drawOrthographicView(void)
	{
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	 glVertex3f(-5.0, -5.0, 0.0);
	 glVertex3f(5.0, -5.0, 0.0);
	 glVertex3f(5.0, 5.0, 0.0);
	 glVertex3f(-5.0, 5.0, 0.0);
	 glVertex3f(-5.0, -5.0, 0.0);
	glEnd();
	glBegin(GL_LINE_STRIP);
	 glVertex3f(-5.0, -5.0, -10.0);
	 glVertex3f(5.0, -5.0, -10.0);
	 glVertex3f(5.0, 5.0, -10.0);
	 glVertex3f(-5.0, 5.0, -10.0);
	 glVertex3f(-5.0, -5.0, -10.0);
	glEnd();
	glBegin(GL_LINES);
	 glVertex3f(-5.0, -5.0, 0.0);
	 glVertex3f(-5.0, -5.0, -10.0);
	 glVertex3f(5.0, -5.0, 0.0);
	 glVertex3f(5.0, -5.0, -10.0);
	 glVertex3f(5.0, 5.0, 0.0);
	 glVertex3f(5.0, 5.0, -10.0);
	 glVertex3f(-5.0, 5.0, 0.0);
	 glVertex3f(-5.0, 5.0, -10.0);
	glEnd();
	}


void drawPerspectiveView(void)
	{
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_STRIP);
	 glVertex3f(-1.0, -1.0, -1.0);
	 glVertex3f(1.0, -1.0, -1.0);
	 glVertex3f(1.0, 1.0, -1.0);
	 glVertex3f(-1.0, 1.0, -1.0);
	 glVertex3f(-1.0, -1.0, -1.0);
	glEnd();
	glBegin(GL_LINE_STRIP);
	 glVertex3f(-10.0, -10.0, -10.0);
	 glVertex3f(10.0, -10.0, -10.0);
	 glVertex3f(10.0, 10.0, -10.0);
	 glVertex3f(-10.0, 10.0, -10.0);
	 glVertex3f(-10.0, -10.0, -10.0);
	glEnd();
	glBegin(GL_LINES);
	 glVertex3f(-1.0, -1.0, -1.0);
	 glVertex3f(-10.0, -10.0, -10.0);
	 glVertex3f(1.0, -1.0, -1.0);
	 glVertex3f(10.0, -10.0, -10.0);
	 glVertex3f(1.0, 1.0, -1.0);
	 glVertex3f(10.0, 10.0, -10.0);
	 glVertex3f(-1.0, 1.0, -1.0);
	 glVertex3f(-10.0, 10.0, -10.0);
	glEnd();
	}


void drawEverything(void)
	{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (showProjection)
		gluPerspective(30.0, 1.0, 0.1, 100.0);
	else if (orthographic)
		glOrtho(-5.0, 5.0, -5.0, 5.0, 0.0, 10.0);
	else
		gluPerspective(90.0, 1.0, 1.0, 10.0);
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	if (showProjection)
		{
		glEnable(GL_DEPTH_TEST);
		glClear(GL_DEPTH_BUFFER_BIT);
		glTranslatef(0.0, 0.0, -50.0);
		glRotatef(viewRotX, 1.0, 0.0, 0.0);
		glRotatef(viewRotY, 0.0, 1.0, 0.0);
		drawCoordinateAxes();
		if (orthographic)
			drawOrthographicView();
		else
			drawPerspectiveView();
		}
	else
		glDisable(GL_DEPTH_TEST);

	drawGroundPlane();
	
	glTranslatef(-4.0, 0.0, -8.0);
	glColor3f(0.5, 0.4, 0.0);
	drawTriangle();
	
	glTranslatef(2.0, 0.0, 1.0);
	glColor3f(1.0, 0.9, 0.0);
	drawTriangle();

	glTranslatef(2.0, 0.0, 1.0);
	glColor3f(0.5, 0.9, 0.5);
	drawTriangle();

	glTranslatef(2.0, 0.0, 1.0);
	glColor3f(0.0, 0.9, 1.0);
	drawTriangle();

	glTranslatef(2.0, 0.0, 1.0);
	glColor3f(0.0, 0.0, 0.7);
	drawTriangle();

	glutSwapBuffers();
	}


static void key(unsigned char k, int x, int y)
	{
	if (k == 27)
		exit(0);
	else if (k == 'p')
		orthographic = 0;
	else if (k == 'o')
		orthographic = 1;
	else if (k == 13)
		showProjection = !showProjection;
	else if (k == 'w')
		viewRotX += 3;
	else if (k == 's')
		viewRotX -= 3;
	else if (k == 'a')
		viewRotY += 3;
	else if (k == 'd')
		viewRotY -= 3;
	glutPostRedisplay();
	}


static void specialkey(int k, int x, int y)
	{
	if (k == GLUT_KEY_LEFT)
		angle += 3;
	else if (k == GLUT_KEY_RIGHT)
		angle -= 3;
	glutPostRedisplay();
	}



int main(int argc, char *argv[])
	{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow("example");
	glutDisplayFunc(drawEverything);
	glutKeyboardFunc(key);
	glutSpecialFunc(specialkey);
	glutMainLoop();
	return 0;
	}
