#include <GL/gl.h>

#include <GL/glu.h>

#include <GL/glut.h>

#include <stdlib.h>

#include <stdio.h>

 

/*  Create checkerboard texture  */

#define checkImageWidth 128

#define checkImageHeight 128

static GLubyte checkImage[checkImageHeight][checkImageWidth][4];

 

static GLuint texName;

 

void makeCheckImage(void)

{

   int i, j, c;

   

   for (i = 0; i < checkImageHeight; i++) {

      for (j = 0; j < checkImageWidth; j++) {

         c = ((((i&0x8)==0)^((j&0x8)==0)))*255;

         checkImage[i][j][0] = (GLubyte) c;

         checkImage[i][j][1] = (GLubyte) c;

         checkImage[i][j][2] = (GLubyte) c;

         checkImage[i][j][3] = (GLubyte) 255;

      }

   }

}

 

void init(void)

{   

       GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

          GLfloat mat_shininess[] = { 50.0 };

 

          glClearColor (0.0, 0.0, 0.0, 0.0);

          glShadeModel(GL_FLAT);

          glEnable(GL_DEPTH_TEST);

          glDepthFunc(GL_LEQUAL);

 

          /* texture stuff */

          makeCheckImage();

          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

 

          glGenTextures(1, &texName);

          glBindTexture(GL_TEXTURE_2D, texName);

 

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,

                                            GL_NEAREST);

          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,

                                            GL_NEAREST);

          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth,

                                         checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,

                                         checkImage);

 

          /* lighting stuff */

          glShadeModel (GL_SMOOTH);

 

          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);

          glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);

 

          glEnable(GL_LIGHTING);

          glEnable(GL_LIGHT0);

 

}

 

void display(void)

{

          GLfloat mat_red[] = {1.0, 0.0, 0.0, 0.0};

          GLfloat mat_green[] = {0.0, 1.0, 0.0, 0.0};

          GLfloat mat_blue[]  = {0.0, 0.0, 1.0, 0.0};

          GLfloat mat_black[] = {0.0, 0.0, 0.0, 0.0};

          GLfloat light_position[] = {10.0, 10.0, 10.0, 0.0};

          /* this will be your shadow matrix.  You need to specify what this contains.

           * OpenGL has a funky ordering for rows and columns

           * use this ordering for rows and columns

           */

          GLfloat m[16];

          m[0]= 1; m[4]= 0; m[8] = 0; m[12]= 0;

          m[1]= 0; m[5]= 1; m[9] = 0; m[13]= 0;

          m[2]= 0; m[6]= 0; m[10]= 0; m[14]= 0;

          m[3]= 0; m[7]= 0; m[11]= 0; m[15]= 1;

         

          glLoadIdentity();

          gluLookAt(10,0,5, 0,0,0, 0,0,1);

 

          glLightfv(GL_LIGHT0, GL_POSITION, light_position);

 

          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 

         

          /* draw checkered floor */

          glEnable(GL_TEXTURE_2D);

          glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

          glBindTexture(GL_TEXTURE_2D, texName);

          glBegin(GL_QUADS);

                     /* z=-0.01 so that the floor doesn't overlap your shadows */

                     glTexCoord2f(0.0, 0.0); glVertex3f(-4.0, -4.0, -0.01);

                     glTexCoord2f(0.0, 1.0); glVertex3f(-4.0,  4.0, -0.01);

                     glTexCoord2f(1.0, 1.0); glVertex3f( 4.0,  4.0, -0.01);

                     glTexCoord2f(1.0, 0.0); glVertex3f( 4.0, -4.0, -0.01);

          glEnd();

          glFlush();

          glDisable(GL_TEXTURE_2D);

 

 

          /* draw cubes */

 

          /* scale translate and draw blue cube */

          glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_blue);

          glPushMatrix();

          glTranslatef(2.5, 2.5, 0);          // translate cube front and right.

          glScalef(0.5, 0.5, 3);                  // scale to be narrow and tall

          glTranslatef(0,0,0.5);                  // translate unit cube to surface

          glutSolidCube(1);                            // draw unit cube

          glPopMatrix();

 

          /* scale rotate and draw green cube */

          glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_green);

          glPushMatrix();

          glTranslatef(0, -3, 0.5); // translate to left side and up so that it is on the surface

          glRotatef(90, 1, 0, 0);                // rotate to its side

          glScalef(0.5, 0.5, 3);                  // scale to be narrow and tall

          glutSolidCube(1);                            // draw unit cube

          glPopMatrix();

 

          /* apply a matrix 'm' to a cone w/o scaling, rotation, or projection */

          /* the matrix is wrong, so don't expect this to work */

         

          glDisable(GL_LIGHTING);                // so that OpenGL doesn't shade your shadows.

          glColor3f(0.0, 0.0, 0.0); // shadow color

          glPushMatrix();

          glMultMatrixf(m);                            // apply transform of matrix m

          glutSolidCube(1);                            // draw unit cube

          glPopMatrix();

          glEnable(GL_LIGHTING);                  // enable lighting for future calls to display()

 

          glFlush();

}

 

void reshape(int w, int h)

{

   glViewport(0, 0, (GLsizei) w, (GLsizei) h);

   glMatrixMode(GL_PROJECTION);

   glLoadIdentity();

   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0);

   glMatrixMode(GL_MODELVIEW);

   glLoadIdentity();

}

 

void keyboard (unsigned char key, int x, int y)

{

   switch (key) {

      case 27:

         exit(0);

         break;

      default:

         break;

   }

}

 

int main(int argc, char** argv)

{

   glutInit(&argc, argv);

   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);

   glutInitWindowSize(500, 500);

   glutInitWindowPosition(100, 100);

   glutCreateWindow(argv[0]);

   init();

   glutDisplayFunc(display);

   glutReshapeFunc(reshape);

   glutKeyboardFunc(keyboard);

   glutMainLoop();

   return 0;

}