/*
   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 PI 3.14159

		GLfloat cubex = 0.0;
		GLfloat cubey = 0.0;
		GLfloat cubez = 0.0;
		GLfloat aTime  = 0.0;

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 color1[]={1.0, 0.0, 0.0,1.0}, color2[]={0.0,1.0,0.0,1.0};
    GLfloat mat_shininess[]={ 50.0 };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  /*clear window */

/*  draw our cube */

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color1 );
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color1 );
    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]);
    glEnd();

    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color2 );
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color2 );
    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess );
    glBegin(GL_QUADS);
      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 )
{

    glPushMatrix();
    glTranslatef( cubex, cubey, cubez );
	cube();
	glPopMatrix();
}

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 animate(void)
{
		#define deltaTime 0.05
		
//		define position for the cube by modeling time-based behavior

		aTime += deltaTime; if (aTime > 2.0*PI) aTime -= 2.0*PI;
		cubex = sin(2.0*aTime);
		cubey = cos(3.0*aTime);
		cubez = cos(aTime);
		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("moving cube");
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
        glutIdleFunc(animate);

        myinit();

        glutMainLoop();
}

