/*
   Program to display a cube that moves around in space.

   Sample for description of events in OpenGL
   
   (c) 1999, Steve Cunningham
*/

#include "glut.h"
#include <stdlib.h>
#include <math.h>

#define RED     1
#define GREEN   2
#define BLUE    3
#define WHITE   4
#define YELLOW  5

int colorName = 1;

void myinit(void)
{
//      set up overall light data, including specular=ambient=light colors
        GLfloat light_position[]={ 10.0, 10.0, -10.0, 1.0 };
        GLfloat light_color[]={ 1.0, 1.0, 1.0, 1.0 };
        GLfloat ambient_color[]={ 0.2, 0.2, 0.2, 1.0 };
        GLfloat mat_specular[]={ 1.0, 1.0, 1.0, 1.0 };

        glClearColor( 0.0, 0.0, 1.0, 0.0 );
        glShadeModel(GL_SMOOTH);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular );
        glLightfv(GL_LIGHT0, GL_POSITION, light_position );
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color );
        glLightfv(GL_LIGHT0, GL_SPECULAR, light_color );
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color );

/* attributes */

        glEnable(GL_LIGHTING);   // so lighting models are used
        glEnable(GL_LIGHT0);     // we'll use LIGHT0
        glEnable(GL_DEPTH_TEST); // allow z-buffer display
}

void cube(void)
{
/* define a point data type */

    typedef GLfloat point3[3];

    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 normals[6]={{ 0.0, 0.0, 1.0},
                       {-1.0, 0.0, 0.0},
                       { 0.0, 0.0,-1.0},
                       { 1.0, 0.0, 0.0},
                       { 0.0,-1.0, 0.0},
                       { 0.0, 1.0, 0.0} };

    GLfloat color[4];
    GLfloat mat_shininess[]={ 50.0 };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // clear window
    
//  set the color based on the menu choice

	switch (colorName) {
		case RED:
			color[0] = 1.0;
			color[1] = 0.0;
			color[2] = 0.0;
			color[3] = 1.0;
			break;
		case GREEN:
			color[0] = 0.0;
			color[1] = 1.0;
			color[2] = 0.0;
			color[3] = 1.0;
			break;
		case BLUE:
			color[0] = 0.0;
			color[1] = 0.0;
			color[2] = 1.0;
			color[3] = 1.0;
			break;
		case WHITE:
			color[0] = 1.0;
			color[1] = 1.0;
			color[2] = 1.0;
			color[3] = 1.0;
			break;
		case YELLOW:
			color[0] = 1.0;
			color[1] = 1.0;
			color[2] = 0.0;
			color[3] = 1.0;
			break;
	}

//  draw our cube

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color );
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color );
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess );
    glBegin(GL_QUADS);
      glNormal3fv(normals[0]);   // first quad: positive Z face
      glVertex3fv(vertices[1]);
      glNormal3fv(normals[0]);
      glVertex3fv(vertices[5]);
      glNormal3fv(normals[0]);
      glVertex3fv(vertices[7]);
      glNormal3fv(normals[0]);
      glVertex3fv(vertices[3]);
      glNormal3fv(normals[5]);   // second quad: positive Y face
      glVertex3fv(vertices[7]);
      glNormal3fv(normals[5]);
      glVertex3fv(vertices[6]);
      glNormal3fv(normals[5]);
      glVertex3fv(vertices[2]);
      glNormal3fv(normals[5]);
      glVertex3fv(vertices[3]);
      glNormal3fv(normals[2]);   // third quad: negative Z face
      glVertex3fv(vertices[2]);
      glNormal3fv(normals[2]);
      glVertex3fv(vertices[6]);
      glNormal3fv(normals[2]);
      glVertex3fv(vertices[4]);
      glNormal3fv(normals[2]);
      glVertex3fv(vertices[0]);
      glNormal3fv(normals[3]);  // fourth quad: positive X face
      glVertex3fv(vertices[5]);
      glNormal3fv(normals[3]);
      glVertex3fv(vertices[4]);
      glNormal3fv(normals[3]);
      glVertex3fv(vertices[6]);
      glNormal3fv(normals[3]);
      glVertex3fv(vertices[7]);
      glNormal3fv(normals[4]);  // fifth quad: negative Y face
      glVertex3fv(vertices[4]);
      glNormal3fv(normals[4]);
      glVertex3fv(vertices[5]);
      glNormal3fv(normals[4]);
      glVertex3fv(vertices[1]);
      glNormal3fv(normals[4]);
      glVertex3fv(vertices[0]);
      glNormal3fv(normals[1]);  // sixth quad: negative X face
      glVertex3fv(vertices[0]);
      glNormal3fv(normals[1]);
      glVertex3fv(vertices[1]);
      glNormal3fv(normals[1]);
      glVertex3fv(vertices[3]);
      glNormal3fv(normals[1]);
      glVertex3fv(vertices[2]);
    glEnd();
    glutSwapBuffers();
 }

void display( void )
{
	cube();
}

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();
        /*           eye point        center of view      up   */
        gluLookAt(10.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void options_menu(int input)
{
	colorName = input;
	glutPostRedisplay();
}

void main(int argc, char** argv)
{

/* Standard GLUT initialization */

        glutInit(&argc,argv);
//      initialize for double buffering, RGB color, and depth tests
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(500,500);
        glutInitWindowPosition(70,70);
        glutCreateWindow("color-changing cube");
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);

		glutCreateMenu(options_menu);	    // create the options menu
		glutAddMenuEntry("Red", RED);	    // 1 add the menu entries
		glutAddMenuEntry("Green", GREEN);   // 2
		glutAddMenuEntry("Blue", BLUE);     // 3
		glutAddMenuEntry("White", WHITE);   // 4
		glutAddMenuEntry("Yellow", YELLOW); // 5
		glutAttachMenuName(GLUT_RIGHT_BUTTON, "Colors");	/* give the menu a name */

        myinit();
        glutMainLoop();
}

