/*
	Create a simple view of the RGB color cube for classroom use

	Sample for introductory computer graphics course -- copyright (c) 2000, Steve Cunningham
*/
#include "glut.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define SIZE 20.0

static char ch;
typedef GLfloat point3[3];
typedef GLfloat color [4];

// function prototypes
void myinit(void);
void display(void);
void cube(void);
void reshape(int,int);
void keyboard(unsigned char,int,int);

void myinit(void)
{
	glClearColor( 0.5, 0.5, 0.5, 0.0 );
	glEnable(GL_DEPTH_TEST); // allow z-buffer display
	glShadeModel(GL_SMOOTH);
}

void display( void )
{
    typedef GLfloat point3[3];
	#define Angle 2.0

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //  NOTE that we do not take ourselves back to the original raw-world state.
    //  We let the modelview matrix hold our global view of the model, and
    //  we modify it by including the new rotation each time a key is pressed
    switch(ch)
    {
		case 'w':
			glRotatef( Angle, 1.0, 0.0, 0.0); break;
		case 'q':
			glRotatef(-Angle, 1.0, 0.0, 0.0); break;
		case 's':
			glRotatef( Angle, 0.0, 1.0, 0.0); break;
		case 'a':
			glRotatef(-Angle, 0.0, 1.0, 0.0); break;
		case 'x':
			glRotatef( Angle, 0.0, 0.0, 1.0); break;
		case 'z':
			glRotatef(-Angle, 0.0, 0.0, 1.0); break;
	}

	//  NOW we save the state of the modelview transformation so we can restore
	//  it after the axes and cube have been drawn.
	glPushMatrix();
	cube();
	glPopMatrix();
	glutSwapBuffers();
 }

void reshape(int w,int h)
{
	glViewport(0,0,(GLsizei)w,(GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0,1.0,1.0,30.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt( 2.5,  2.5, 2.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}

void cube(void)
{
    point3 vertices[8]={{-1.0, -1.0, -1.0},
                        {-1.0, -1.0,  1.0},
                        {-1.0,  1.0, -1.0},
                        {-1.0,  1.0,  1.0},
                        { 1.0, -1.0, -1.0},
                        { 1.0, -1.0,  1.0},
                        { 1.0,  1.0, -1.0},
                        { 1.0,  1.0,  1.0} };

	point3 colors[8] = {{0.,0.,0.},
						{0.,0.,1.},
						{0.,1.,0.},
						{0.,1.,1.},
						{1.,0.,0.},
						{1.,0.,1.},
						{1.,1.,0.},
						{1.,1.,1.} };

    glBegin(GL_QUADS);
	// first quad: positive Z face
      glColor3fv(colors[1]);
      glVertex3fv(vertices[1]);
      glColor3fv(colors[5]);
      glVertex3fv(vertices[5]);
      glColor3fv(colors[7]);
      glVertex3fv(vertices[7]);
      glColor3fv(colors[3]);
      glVertex3fv(vertices[3]);
	// second quad: positive Y face
      glColor3fv(colors[7]);
      glVertex3fv(vertices[7]);
      glColor3fv(colors[6]);
      glVertex3fv(vertices[6]);
      glColor3fv(colors[2]);
      glVertex3fv(vertices[2]);
      glColor3fv(colors[3]);
      glVertex3fv(vertices[3]);
	// third quad: negative Z face
      glColor3fv(colors[2]);
      glVertex3fv(vertices[2]);
      glColor3fv(colors[6]);
      glVertex3fv(vertices[6]);
      glColor3fv(colors[4]);
      glVertex3fv(vertices[4]);
      glColor3fv(colors[0]);
      glVertex3fv(vertices[0]);
	// fourth quad: positive X face
      glColor3fv(colors[5]);
      glVertex3fv(vertices[5]);
      glColor3fv(colors[4]);
      glVertex3fv(vertices[4]);
      glColor3fv(colors[6]);
      glVertex3fv(vertices[6]);
      glColor3fv(colors[7]);
      glVertex3fv(vertices[7]);
	// fifth quad: negative Y face
      glColor3fv(colors[4]);
      glVertex3fv(vertices[4]);
      glColor3fv(colors[5]);
      glVertex3fv(vertices[5]);
      glColor3fv(colors[1]);
      glVertex3fv(vertices[1]);
      glColor3fv(colors[0]);
      glVertex3fv(vertices[0]);
	// sixth quad: negative X face
      glColor3fv(colors[0]);
      glVertex3fv(vertices[0]);
      glColor3fv(colors[1]);
      glVertex3fv(vertices[1]);
      glColor3fv(colors[3]);
      glVertex3fv(vertices[3]);
      glColor3fv(colors[2]);
      glVertex3fv(vertices[2]);
    glEnd();
 }

void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
		case 'w' :
		case 'q' :
		case 's' :
		case 'a' :
		case 'x' :
		case 'z' :
			ch = key; break;
	}
	glutPostRedisplay();
}

void main(int argc, char** argv)
{
	glutInit(&argc,argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(500,500);
	glutInitWindowPosition(70,70);
	glutCreateWindow("RGB Cube Color Space");
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);

	myinit();
	glutMainLoop();
}