/*  texture_pbm.c
 *  Play with 
 *        (1) texture domain size (2 times in s-direction)
 *            so that the bitmap [0,1]^2 gets repeated
 *        (2) evaluation region of the texture
 */

#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>

GLfloat ctrlpoints[3][3][3] = {
   {{ -1.5, -1.5, 0.0}, { 0.0, -1.5, 1.0}, {1.5, -1.5, 0.0}}, 
   {{ -1.5, 0.0, 1.0}, { 0.0, 0.0, 4.0}, {1.5, 0.0, 1.0}}, 
   {{ -1.5, 1.5, 0.0}, { -0.0, 1.5, 1.0}, {1.5, 1.5, 0.0}}
};

GLfloat texpts[2][2][2] = {{{0.0, 0.0}, {0.0, 1.0}}, 
			{{1.0, 0.0}, {1.0, 1.0}}};
// uncomment for (1)
// GLfloat texpts[2][2][2] = {{{0.0, 0.0}, {0.0, 1.0}}, 
//      {{2.0, 0.0}, {2.0, 1.0}}};

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glColor3f(1.0, 1.0, 1.0);
   glEvalMesh2(GL_FILL, 0, 20, 0, 20);
   glFlush();
}

#define	imageWidth 64
#define	imageHeight 64
GLubyte image[3*imageWidth*imageHeight];

void makeImage(void)
{
   int i, j, c;
   for (i = 0; i < 16; i++) {
      for (j = 0; j < 16; j++) {
   //for (i = 0; i < imageWidth; i++) {
      //for (j = 0; j < imageHeight; j++) {
         c = ((((i&0x8)==0)^((j&0x8))==0))*255;
         //image[3*(imageWidth*i+j)] = (GLubyte) c;
         //image[3*(imageWidth*i+j)+1] = (GLubyte) c;
         //image[3*(imageWidth*i+j)+2] = (GLubyte) c;
         image[3*(64*i+j)] = (GLubyte) c;
         image[3*(64*i+j)+1] = (GLubyte) c;
         image[3*(64*i+j)+2] = (GLubyte) c;
      }
   }
}

void init(void)
{
   glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 3, 0, 1, 9, 3, &ctrlpoints[0][0][0]);
   glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 
           0,  1, 4, 2, &texpts[0][0][0]);
// uncomment for (2)
//   glMap2f(GL_MAP2_TEXTURE_COORD_2, 0,    0.5, 2, 2, 
//           0,   0.5, 4, 2, &texpts[0][0][0]);
   glEnable(GL_MAP2_TEXTURE_COORD_2);
   glEnable(GL_MAP2_VERTEX_3);
   glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
   makeImage();
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   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_RGB, imageWidth, imageHeight, 0,
                GL_RGB, GL_UNSIGNED_BYTE, image);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_DEPTH_TEST);
   glShadeModel (GL_FLAT);
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (w <= h)
      glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w, 
              4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0);
   else
      glOrtho(-4.0*(GLfloat)w/(GLfloat)h, 
              4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   //glRotatef(85.0, 1.0, 1.0, 1.0);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         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;
}

