new test which uses mixed texgen/non-texgen texture coordinates to exhibit potential...
authorRoland Scheidegger <rscheidegger@gmx.ch>
Fri, 25 Jun 2004 13:49:46 +0000 (13:49 +0000)
committerRoland Scheidegger <rscheidegger@gmx.ch>
Fri, 25 Jun 2004 13:49:46 +0000 (13:49 +0000)
progs/tests/texgenmix.c [new file with mode: 0644]

diff --git a/progs/tests/texgenmix.c b/progs/tests/texgenmix.c
new file mode 100644 (file)
index 0000000..f8942f1
--- /dev/null
@@ -0,0 +1,640 @@
+
+/*
+ * Demonstrates mixed texgen/non-texgen texture coordinates.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <GL/glut.h>
+
+#undef max
+#undef min
+#define max( a, b )    ((a) >= (b) ? (a) : (b))
+#define min( a, b )    ((a) <= (b) ? (a) : (b))
+
+GLfloat labelColor0[4] = { 1.0, 1.0, 1.0, 1.0 };
+GLfloat labelColor1[4] = { 1.0, 1.0, 0.4, 1.0 };
+GLfloat *labelInfoColor = labelColor0;
+
+GLboolean doubleBuffered = GL_TRUE;
+GLboolean drawTextured = GL_TRUE;
+
+int textureWidth = 64;
+int textureHeight = 64;
+
+int winWidth = 580, winHeight = 720;
+
+const GLfloat texmat_swap_rq[16] = { 1.0, 0.0, 0.0, 0.0,
+                                     0.0, 1.0, 0.0, 0.0,
+                                     0.0, 0.0, 0.0, 1.0,
+                                     0.0, 0.0, 1.0, 0.0};
+
+const GLfloat nullPlane[4] = { 0.0, 0.0, 0.0, 0.0 };
+const GLfloat ObjPlaneS1[4] = { 1.0, 0.0, 1.0, 0.0 };
+const GLfloat ObjPlaneS2[4] = { 0.5, 0.0, 0.0, 0.0 };
+const GLfloat ObjPlaneS3[4] = { 1.0, 0.0, 0.0, 0.0 };
+const GLfloat ObjPlaneT[4] = { 0.0, 1.0, 0.0, 0.0 };
+const GLfloat ObjPlaneT2[4] = { 0.0, 0.5, 0.0, 0.0 };
+const GLfloat ObjPlaneT3[4] = { 0.0, 1.0, 0.0, 0.0 };
+const GLfloat ObjPlaneR[4] = { 0.0, 0.0, 1.0, 0.0 };
+const GLfloat ObjPlaneQ[4] = { 0.0, 0.0, 0.0, 0.5 };
+
+
+static void checkErrors( void )
+{
+   GLenum error;
+
+   while ( (error = glGetError()) != GL_NO_ERROR ) {
+      fprintf( stderr, "Error: %s\n", (char *) gluErrorString( error ) );
+   }
+}
+
+static void drawString( const char *string, GLfloat x, GLfloat y,
+                        const GLfloat color[4] )
+{
+   glColor4fv( color );
+   glRasterPos2f( x, y );
+
+   while ( *string ) {
+      glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_10, *string );
+      string++;
+   }
+}
+
+static void begin2D( int width, int height )
+{
+   glMatrixMode( GL_PROJECTION );
+
+   glPushMatrix();
+   glLoadIdentity();
+
+   glOrtho( 0, width, 0, height, -1, 1 );
+   glMatrixMode( GL_MODELVIEW );
+
+   glPushMatrix();
+   glLoadIdentity();
+}
+
+static void end2D( void )
+{
+   glMatrixMode( GL_PROJECTION );
+   glPopMatrix();
+   glMatrixMode( GL_MODELVIEW );
+   glPopMatrix();
+}
+
+static void initialize( void )
+{
+   glMatrixMode( GL_PROJECTION );
+   glLoadIdentity();
+
+   glOrtho( -1.5, 1.5, -1.5, 1.5, -1.5, 1.5 );
+
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+
+   glShadeModel( GL_FLAT );
+}
+
+/* ARGSUSED1 */
+static void keyboard( unsigned char c, int x, int y )
+{
+   switch ( c ) {
+   case 't':
+      drawTextured = !drawTextured;
+      break;
+   case 27:             /* Escape key should force exit. */
+      exit(0);
+      break;
+   default:
+      break;
+   }
+   glutPostRedisplay();
+}
+
+/* ARGSUSED1 */
+static void special( int key, int x, int y )
+{
+   switch ( key ) {
+   case GLUT_KEY_DOWN:
+      break;
+   case GLUT_KEY_UP:
+      break;
+   case GLUT_KEY_LEFT:
+      break;
+   case GLUT_KEY_RIGHT:
+      break;
+   default:
+      break;
+   }
+   glutPostRedisplay();
+}
+
+static void
+reshape( int w, int h )
+{
+   winWidth = w;
+   winHeight = h;
+   /* No need to call glViewPort here since "draw" calls it! */
+}
+
+static void loadTexture( int width, int height )
+{
+   int         alphaSize = 1;
+   int         rgbSize = 3;
+   GLubyte     *texImage, *p;
+   int         elementsPerGroup, elementSize, groupSize, rowSize;
+   int         i, j;
+
+
+   elementsPerGroup = alphaSize + rgbSize;
+   elementSize = sizeof(GLubyte);
+   groupSize = elementsPerGroup * elementSize;
+   rowSize = width * groupSize;
+
+   if ( (texImage = (GLubyte *) malloc( height * rowSize ) ) == NULL ) {
+      fprintf( stderr, "texture malloc failed\n" );
+      return;
+   }
+
+   for ( i = 0 ; i < height ; i++ )
+   {
+      p = texImage + i * rowSize;
+
+      for ( j = 0 ; j < width ; j++ )
+      {
+        if ( rgbSize > 0 )
+        {
+           /**
+            ** +-----+-----+
+            ** |     |     |
+            ** |  R  |  G  |
+            ** |     |     |
+            ** +-----+-----+
+            ** |     |     |
+            ** |  Y  |  B  |
+            ** |     |     |
+            ** +-----+-----+
+            **/
+           if ( i > height / 2 ) {
+              if ( j < width / 2 ) {
+                 p[0] = 0xff;
+                 p[1] = 0x00;
+                 p[2] = 0x00;
+              } else {
+                 p[0] = 0x00;
+                 p[1] = 0xff;
+                 p[2] = 0x00;
+              }
+           } else {
+              if ( j < width / 2 ) {
+                 p[0] = 0xff;
+                 p[1] = 0xff;
+                 p[2] = 0x00;
+              } else {
+                 p[0] = 0x00;
+                 p[1] = 0x00;
+                 p[2] = 0xff;
+              }
+           }
+           p += 3 * elementSize;
+        }
+
+        if ( alphaSize > 0 )
+        {
+           /**
+            ** +-----------+
+            ** |     W     |
+            ** |  +-----+  |
+            ** |  |     |  |
+            ** |  |  B  |  |
+            ** |  |     |  |
+            ** |  +-----+  |
+            ** |           |
+            ** +-----------+
+            **/
+           int i2 = i - height / 2;
+           int j2 = j - width / 2;
+           int h8 = height / 8;
+           int w8 = width / 8;
+           if ( -h8 <= i2 && i2 <= h8 && -w8 <= j2 && j2 <= w8 ) {
+              p[0] = 0x00;
+           } else if ( -2 * h8 <= i2 && i2 <= 2 * h8 && -2 * w8 <= j2 && j2 <= 2 * w8 ) {
+              p[0] = 0x55;
+           } else if ( -3 * h8 <= i2 && i2 <= 3 * h8 && -3 * w8 <= j2 && j2 <= 3 * w8 ) {
+              p[0] = 0xaa;
+           } else {
+              p[0] = 0xff;
+           }
+           p += elementSize;
+        }
+      }
+   }
+
+   glTexImage2D( GL_TEXTURE_2D, 0,
+                GL_RGBA, width, height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, texImage );
+
+   free( texImage );
+}
+
+
+static void drawSample( int x, int y, int w, int h,
+                        int texgenenabled, int coordnr )
+{
+   char buf[255];
+
+   glViewport( x, y, w, h );
+   glScissor( x, y, w, h );
+
+   glClearColor( 0.1, 0.1, 0.1, 1.0 );
+   glClear( GL_COLOR_BUFFER_BIT );
+
+   begin2D( w, h );
+   if (texgenenabled == 2) {
+      sprintf( buf, "TexCoord%df", coordnr);
+      drawString( buf, 10, h - 15, labelInfoColor );
+      sprintf( buf, "texgen enabled for %s coordinate(s)", coordnr == 2 ? "S" : "S/T");
+      drawString( buf, 10, 5, labelInfoColor );
+   }
+   else if (texgenenabled == 0) {
+      sprintf( buf, "TexCoord%df", coordnr);
+      drawString( buf, 10, h - 15, labelInfoColor );
+      drawString( "no texgen", 10, 5, labelInfoColor );
+   }
+   else if (texgenenabled == 1) {
+      drawString( "no TexCoord", 10, h - 15, labelInfoColor );
+      sprintf( buf, "texgen enabled for %s coordinate(s)",
+         coordnr == 2 ? "S/T" : (coordnr == 3 ? "S/T/R" : "S/T/R/Q"));
+      drawString( buf, 10, 5, labelInfoColor );
+   }
+
+   end2D();
+
+   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
+
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+
+   loadTexture( textureWidth, textureHeight );
+
+   if ( drawTextured ) {
+      glEnable( GL_TEXTURE_2D );
+   }
+
+   glDisable( GL_TEXTURE_GEN_S );
+   glDisable( GL_TEXTURE_GEN_T );
+   glDisable( GL_TEXTURE_GEN_R );
+   glDisable( GL_TEXTURE_GEN_Q );
+
+   glMatrixMode( GL_TEXTURE );
+   glLoadIdentity();
+   glMatrixMode( GL_MODELVIEW );
+   glPushMatrix();
+
+   switch (coordnr) {
+   case 2:
+      switch (texgenenabled) {
+      case 0:
+         glBegin( GL_QUADS );
+         glTexCoord2f( 0.0, 0.0 );
+         glVertex2f( -0.8, -0.8 );
+
+         glTexCoord2f( 1.0, 0.0 );
+         glVertex2f( 0.8, -0.8 );
+
+         glTexCoord2f( 1.0, 1.0 );
+         glVertex2f( 0.8, 0.8 );
+
+         glTexCoord2f( 0.0, 1.0 );
+         glVertex2f( -0.8, 0.8 );
+         glEnd();
+         break;
+      case 1:
+      /* why doesn't this case work with software mesa? The S/T tex coords
+         should turn out as 0 and 1 if dot product of vertex coordinates with
+         ObjPlaneS3/T3 is calculated, and Q coord should be default value (1.0), no?
+         Submitting one dummy tex coordinate fixes this? */
+         glTranslatef( -0.8, -0.8, 0.0 );
+         glScalef( 1.6, 1.6, 1.0 );
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS3);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, ObjPlaneT3);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, nullPlane);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, nullPlane);
+
+         glEnable( GL_TEXTURE_GEN_S );
+         glEnable( GL_TEXTURE_GEN_T );
+
+         glBegin( GL_QUADS );
+/*         glTexCoord1f( 0.0 );*/
+         glVertex2f( 0.0, 0.0 );
+         glVertex2f( 1.0, 0.0 );
+         glVertex2f( 1.0, 1.0 );
+         glVertex2f( 0.0, 1.0 );
+         glEnd();
+         break;
+      case 2:
+         /* make sure that texgen T and non-texgen S coordinate are wrong */
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS1);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, nullPlane);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, nullPlane);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, nullPlane);
+
+         glEnable( GL_TEXTURE_GEN_S );
+
+         glBegin( GL_QUADS );
+         /* use z coordinate to get correct texgen values... */
+         glTexCoord2f( 0.0, 0.0 );
+         glVertex3f( -0.8, -0.8, 0.8 );
+
+         glTexCoord2f( 0.0, 0.0 );
+         glVertex3f( 0.8, -0.8, 0.2 );
+
+         glTexCoord2f( 0.0, 1.0 );
+         glVertex3f( 0.8, 0.8, 0.2 );
+
+         glTexCoord2f( 0.0, 1.0 );
+         glVertex3f( -0.8, 0.8, 0.8 );
+         glEnd();
+         break;
+      }
+      break;
+   case 3:
+      glMatrixMode( GL_TEXTURE );
+      glLoadMatrixf( texmat_swap_rq );
+      glMatrixMode( GL_MODELVIEW );
+      glTranslatef( -0.8, -0.8, 0.0 );
+      glScalef( 1.6, 1.6, 1.0 );
+      switch (texgenenabled) {
+      case 0:
+         glBegin( GL_QUADS );
+         glTexCoord3f( 0.0, 0.0, 0.5 );
+         glVertex2f( 0.0, 0.0 );
+
+         glTexCoord3f( 0.5, 0.0, 0.5 );
+         glVertex2f( 1.0, 0.0 );
+
+         glTexCoord3f( 0.5, 0.5, 0.5 );
+         glVertex2f( 1.0, 1.0 );
+
+         glTexCoord3f( 0.0, 0.5, 0.5 );
+         glVertex2f( 0.0, 1.0 );
+         glEnd();
+         break;
+      case 1:
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS2);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, ObjPlaneT2);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, ObjPlaneR);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, nullPlane);
+
+         glEnable( GL_TEXTURE_GEN_S );
+         glEnable( GL_TEXTURE_GEN_T );
+         glEnable( GL_TEXTURE_GEN_R );
+
+         glBegin( GL_QUADS );
+         glVertex3f( 0.0, 0.0, 0.5 );
+         glVertex3f( 1.0, 0.0, 0.5 );
+         glVertex3f( 1.0, 1.0, 0.5 );
+         glVertex3f( 0.0, 1.0, 0.5 );
+         glEnd();
+         break;
+      case 2:
+         /* make sure that texgen R/Q and non-texgen S/T coordinates are wrong */
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS2);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, ObjPlaneT2);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, nullPlane);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, nullPlane);
+
+         glEnable( GL_TEXTURE_GEN_S );
+         glEnable( GL_TEXTURE_GEN_T );
+
+         glBegin( GL_QUADS );
+         glTexCoord3f( 0.0, 0.0, 0.5 );
+         glVertex2f( 0.0, 0.0);
+
+         glTexCoord3f( 0.0, 0.0, 0.5 );
+         glVertex2f( 1.0, 0.0);
+
+         glTexCoord3f( 0.0, 0.0, 0.5 );
+         glVertex2f( 1.0, 1.0);
+
+         glTexCoord3f( 0.0, 0.0, 0.5 );
+         glVertex2f( 0.0, 1.0);
+         glEnd();
+         break;
+      }
+      break;
+   case 4:
+      switch (texgenenabled) {
+      case 0:
+         glBegin( GL_QUADS );
+         /* don't need r coordinate but still setting it I'm mean */
+         glTexCoord4f( 0.0, 0.0, 0.0, 0.5 );
+         glVertex2f( -0.8, -0.8 );
+
+         glTexCoord4f( 0.5, 0.0, 0.2, 0.5 );
+         glVertex2f( 0.8, -0.8 );
+
+         glTexCoord4f( 0.5, 0.5, 0.5, 0.5 );
+         glVertex2f( 0.8, 0.8 );
+
+         glTexCoord4f( 0.0, 0.5, 0.5, 0.5 );
+         glVertex2f( -0.8, 0.8 );
+         glEnd();
+         break;
+      case 1:
+         glTranslatef( -0.8, -0.8, 0.0 );
+         glScalef( 1.6, 1.6, 1.0 );
+         /* make sure that texgen R/Q and non-texgen S/T coordinates are wrong */
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS2);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, ObjPlaneT2);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, ObjPlaneR);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, ObjPlaneQ);
+
+         glEnable( GL_TEXTURE_GEN_S );
+         glEnable( GL_TEXTURE_GEN_T );
+         glEnable( GL_TEXTURE_GEN_R );
+         glEnable( GL_TEXTURE_GEN_Q );
+
+         glBegin( GL_QUADS );
+         glVertex2f( 0.0, 0.0 );
+         glVertex2f( 1.0, 0.0 );
+         glVertex2f( 1.0, 1.0 );
+         glVertex2f( 0.0, 1.0 );
+         glEnd();
+         break;
+      case 2:
+         glTranslatef( -0.8, -0.8, 0.0 );
+         glScalef( 1.6, 1.6, 1.0 );
+         /* make sure that texgen R/Q and non-texgen S/T coordinates are wrong */
+         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
+         glTexGenfv(GL_S, GL_OBJECT_PLANE, ObjPlaneS2);
+         glTexGenfv(GL_T, GL_OBJECT_PLANE, ObjPlaneT2);
+         glTexGenfv(GL_R, GL_OBJECT_PLANE, nullPlane);
+         glTexGenfv(GL_Q, GL_OBJECT_PLANE, nullPlane);
+
+         glEnable( GL_TEXTURE_GEN_S );
+         glEnable( GL_TEXTURE_GEN_T );
+
+         glBegin( GL_QUADS );
+         glTexCoord4f( 0.0, 0.0, 0.0, 0.5 );
+         glVertex2f( 0.0, 0.0 );
+
+         glTexCoord4f( 0.0, 0.0, 0.2, 0.5 );
+         glVertex2f( 1.0, 0.0 );
+
+         glTexCoord4f( 0.0, 0.0, 0.5, 0.5 );
+         glVertex2f( 1.0, 1.0 );
+
+         glTexCoord4f( 0.0, 0.0, 0.75, 0.5 );
+         glVertex2f( 0.0, 1.0 );
+         glEnd();
+         break;
+      }
+      break;
+   }
+
+   glPopMatrix();
+   glDisable( GL_TEXTURE_2D );
+
+}
+
+static void display( void )
+{
+   int         numX = 3, numY = 3;
+   float       xBase = (float) winWidth * 0.01;
+   float       xOffset = (winWidth - xBase) / numX;
+   float       xSize = max( xOffset - xBase, 1 );
+   float       yBase = (float) winHeight * 0.01;
+   float       yOffset = (winHeight - yBase) / numY;
+   float       ySize = max( yOffset - yBase, 1 );
+   float       x, y;
+   int         i, j;
+
+   glViewport( 0, 0, winWidth, winHeight );
+   glDisable( GL_SCISSOR_TEST );
+   glClearColor( 0.0, 0.0, 0.0, 0.0 );
+   glClear( GL_COLOR_BUFFER_BIT );
+   glEnable( GL_SCISSOR_TEST );
+
+   x = xBase;
+   y = (winHeight - 1) - yOffset;
+
+   for ( i = 0 ; i < numY ; i++ )
+   {
+
+      labelInfoColor = labelColor1;
+
+
+      for ( j = 0 ; j < numX ; j++ ) {
+        drawSample( x, y, xSize, ySize, i, j+2 );
+        x += xOffset;
+      }
+
+      x = xBase;
+      y -= yOffset;
+   }
+
+   if ( doubleBuffered ) {
+      glutSwapBuffers();
+   } else {
+      glFlush();
+   }
+
+   checkErrors();
+}
+
+static void usage( char *name )
+{
+   fprintf( stderr, "usage: %s [ options ]\n", name );
+   fprintf( stderr, "\n" );
+   fprintf( stderr, "options:\n" );
+   fprintf( stderr, "    -sb    single buffered\n" );
+   fprintf( stderr, "    -db    double buffered\n" );
+   fprintf( stderr, "    -info  print OpenGL driver info\n" );
+}
+
+static void instructions( void )
+{
+   fprintf( stderr, "texgenmix - mixed texgen/non-texgen texture coordinate test\n" );
+   fprintf( stderr, "all quads should look the same!\n" );
+   fprintf( stderr, "\n" );
+   fprintf( stderr, "  [t] - toggle texturing\n" );
+}
+
+int main( int argc, char *argv[] )
+{
+   GLboolean info = GL_FALSE;
+   int i;
+
+   glutInit( &argc, argv );
+
+   for ( i = 1 ; i < argc ; i++ ) {
+      if ( !strcmp( "-sb", argv[i] ) ) {
+        doubleBuffered = GL_FALSE;
+      } else if ( !strcmp( "-db", argv[i] ) ) {
+        doubleBuffered = GL_TRUE;
+      } else if ( !strcmp( "-info", argv[i] ) ) {
+        info = GL_TRUE;
+      } else {
+        usage( argv[0] );
+        exit( 1 );
+      }
+   }
+
+   if ( doubleBuffered ) {
+      glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
+   } else {
+      glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE );
+   }
+
+   glutInitWindowSize( winWidth, winHeight );
+   glutInitWindowPosition( 0, 0 );
+   glutCreateWindow( "Mixed texgen/non-texgen texture coordinate test" );
+
+   initialize();
+   instructions();
+
+   if ( info ) {
+      printf( "\n" );
+      printf( "GL_RENDERER   = %s\n", (char *) glGetString( GL_RENDERER ) );
+      printf( "GL_VERSION    = %s\n", (char *) glGetString( GL_VERSION ) );
+      printf( "GL_VENDOR     = %s\n", (char *) glGetString( GL_VENDOR ) ) ;
+      printf( "GL_EXTENSIONS = %s\n", (char *) glGetString( GL_EXTENSIONS ) );
+   }
+
+   glutDisplayFunc( display );
+   glutReshapeFunc( reshape );
+   glutKeyboardFunc( keyboard );
+   glutSpecialFunc( special );
+   glutMainLoop();
+
+   return 0;
+}