/*  texturedCube.cpp
 *  This program demonstrates the application of
 *  a rotating textured cube.
 *
 *  Click the right button to exit.
 *  F. Cheng
 */
// the usual includes
//#include << windows.h>  //when using Windows 95/98/NT/2000
#include << X11/Xlib.h>
#include << fstream.h>
#include << math.h>
// for CS domain
//#include << GL/gl.h>
//#include << GL/glu.h>
//#include << GL/glut.h>
// for Multi Lab
#include << GLUT/glut.h>
#include << OpenGL/gl.h>
#include << stdlib.h>
#include << stdio.h>
//#include "Camera.h"
#include "RGBpixmap.h"

//######################## GLOBALS ########################
RGBpixmap pix[6];    // make six (empty) pixmaps
float xSpeed = 2.0, ySpeed = 2.0,  xAngle = 0.0, yAngle = 0.0;
//<<<<<<<<<<<<<<<<<<<<<<<<<<< myinit >>>>>>>>>>>>>>>>>>>>>>>>>>>
void myInit(void)
{
    glClearColor(1.0f,1.0f,1.0f,1.0f);  // background is white 
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    pix[0].makeCheckerboard();  // make pixmap procedurally 
    pix[0].setTexture(2001);          // create texture
    //pix[1].readBMPFile("Mandrill.bmp");  // make pixmap from image
    pix[1].makeCheckerboard1();  // make pixmap procedurally 
    pix[1].setTexture(2002);          // create texture
    pix[2].makeCheckerboard2();  // make pixmap procedurally 
    pix[2].setTexture(2003);          // create texture
    pix[3].makeCheckerboard();  // make pixmap procedurally 
    pix[3].setTexture(2004);          // create texture
    //pix[4].readBMPFile("Mandrill.bmp");  // make pixmap from image
    pix[4].makeCheckerboard1();  // make pixmap procedurally 
    pix[4].setTexture(2005);          // create texture
    pix[5].makeCheckerboard2();  // make pixmap procedurally 
    pix[5].setTexture(2006);          // create texture
    // similarly for other four textures 

    glViewport(0, 0, 640, 480); // set up the viewing system
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, 640.0/ 480, 1.0, 30.0); // set camera shape
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslated(0.0, 0.0, -4); // move camera back
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<< display >>>>>>>>>>>>>>>>>>>>>>
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glPushMatrix();
    glRotated(xAngle, 1.0,0.0,0.0);  glRotated(yAngle, 0.0,1.0,0.0); // rotate

    glBindTexture(GL_TEXTURE_2D,2001); 	// top face: 'fake' checkerboard
    glBegin(GL_QUADS);
    glTexCoord2f(-1.0, -1.0); glVertex3f(-1.0f, 1.0f, -1.0f);
    glTexCoord2f(-1.0, 2.0); glVertex3f(-1.0f, 1.0f,  1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f( 1.0f, 1.0f,  1.0f);
    glTexCoord2f(2.0, -1.0); glVertex3f( 1.0f, 1.0f, -1.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D,2002); 	// right face: mandrill (originally)
    // right face: checkerboard1
    glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex3f(1.0f, -1.0f,  1.0f);
    glTexCoord2f(0.0, 2.0); glVertex3f(1.0f, -1.0f, -1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f(1.0f,  1.0f, -1.0f);
    glTexCoord2f(2.0, 0.0); glVertex3f(1.0f,  1.0f,  1.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D,2003); 	// front face: 'fake' checkerboard2
    glBegin(GL_QUADS);
    // not done yet
    glTexCoord2f(-1.0, -1.0); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(-1.0, 2.0); glVertex3f(1.0f, -1.0f,  1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f( 1.0f, 1.0f,  1.0f);
    glTexCoord2f(2.0, -1.0); glVertex3f( -1.0f, 1.0f, 1.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D,2004); 	// bottom face: 'fake' checkerboard
    glBegin(GL_QUADS);
    // not done yet
    glTexCoord2f(-1.0, -1.0); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(-1.0, 2.0); glVertex3f(1.0f, -1.0f,  -1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f( 1.0f, -1.0f,  1.0f);
    glTexCoord2f(2.0, -1.0); glVertex3f( -1.0f, -1.0f, 1.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D,2005); 	// left face: 'fake' checkerboard
    glBegin(GL_QUADS);
    // not done yet
    glTexCoord2f(-1.0, -1.0); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(-1.0, 2.0); glVertex3f(-1.0f, -1.0f,  1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f( -1.0f, 1.0f,  1.0f);
    glTexCoord2f(2.0, -1.0); glVertex3f( -1.0f, 1.0f, -1.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D,2006); 	// back face: 'fake' checkerboard
    glBegin(GL_QUADS);
    // not done yet
    glTexCoord2f(-1.0, -1.0); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(-1.0, 2.0); glVertex3f(-1.0f, 1.0f,  -1.0f);
    glTexCoord2f(2.0, 2.0); glVertex3f( 1.0f, 1.0f,  -1.0f);
    glTexCoord2f(2.0, -1.0); glVertex3f( 1.0f, -1.0f, -1.0f);
    glEnd();

    glFlush();
    glPopMatrix();
    glutSwapBuffers();
}

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< spinner >>>>>>>>>>>>>>>>>>>>>
void spinner(void)
{ // alter angles by small amount
	xAngle += xSpeed;  yAngle += ySpeed;
	display();
}

void myMouse(int button, int state, int x, int y)
{
  switch (button) {
     case GLUT_RIGHT_BUTTON:
        if (state == GLUT_DOWN)
           exit (-1);
        break;
     default:
        break;
  }
}

//<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
//    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(640,480);
    glutInitWindowPosition(10, 10);
    glutCreateWindow("rotating textured cube");
    glutDisplayFunc(display);
    glutMouseFunc(myMouse);                  // register myMouse function
    myInit();
    glutIdleFunc(spinner);
    glutMainLoop();
}