envphong.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:16k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* envphong.c - David G. Yu, SGI */
  2. /**
  3.  ** Demonstrates a use of environment texture mapping for improved highlight
  4.  ** shading.
  5.  **
  6.  ** Press mouse button one to move the object, press mouse button two to
  7.  ** move the light source.  Pressing the <s> key switches between using
  8.  ** regular lighting or texture mapping for the specular highlights. The
  9.  ** <o> key will cycle through objects (sphere, cylinder, torus).  Check
  10.  ** out the event loop code below for other keys which do will things.
  11.  **
  12.  ** TBD
  13.  **  - improve accuracy of the highlight texture map
  14.  **  - reduce or eliminate grazing angle artifacts
  15.  **  - improve user interaction
  16.  **
  17.  ** 1995 -- David G Yu
  18.  **
  19.  ** cc -o envphong envphong.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm
  20.  **/
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <math.h>
  25. #include <GL/glut.h>
  26. /* Some <math.h> files do not define M_PI... */
  27. #ifndef M_PI
  28. #define M_PI 3.14159265358979323846
  29. #endif
  30. int win, win2;
  31. int needsLightUpdate = GL_TRUE;
  32. int useLighting = GL_TRUE;
  33. int useSpecularTexture = GL_FALSE;
  34. int useTexture = GL_FALSE;
  35. int useHighRes = GL_FALSE;
  36. int usePattern = GL_FALSE;
  37. int moveLight = GL_FALSE;
  38. int moveObject = GL_FALSE;
  39. int drawObj = 0, maxObj = 2;
  40. GLfloat lightRotX, lightRotY;
  41. GLfloat objectRotX, objectRotY;
  42. int curx, cury, width, height;
  43. void
  44. drawSphere(int numMajor, int numMinor, float radius)
  45. {
  46.   double majorStep = (M_PI / numMajor);
  47.   double minorStep = (2.0 * M_PI / numMinor);
  48.   int i, j;
  49.   for (i = 0; i < numMajor; ++i) {
  50.     double a = i * majorStep;
  51.     double b = a + majorStep;
  52.     double r0 = radius * sin(a);
  53.     double r1 = radius * sin(b);
  54.     GLfloat z0 = radius * cos(a);
  55.     GLfloat z1 = radius * cos(b);
  56.     glBegin(GL_TRIANGLE_STRIP);
  57.     for (j = 0; j <= numMinor; ++j) {
  58.       double c = j * minorStep;
  59.       GLfloat x = cos(c);
  60.       GLfloat y = sin(c);
  61.       glNormal3f((x * r0) / radius, (y * r0) / radius, z0 / radius);
  62.       glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
  63.       glVertex3f(x * r0, y * r0, z0);
  64.       glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
  65.       glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
  66.       glVertex3f(x * r1, y * r1, z1);
  67.     }
  68.     glEnd();
  69.   }
  70. }
  71. void
  72. drawCylinder(int numMajor, int numMinor, float height, float radius)
  73. {
  74.   double majorStep = height / numMajor;
  75.   double minorStep = 2.0 * M_PI / numMinor;
  76.   int i, j;
  77.   for (i = 0; i < numMajor; ++i) {
  78.     GLfloat z0 = 0.5 * height - i * majorStep;
  79.     GLfloat z1 = z0 - majorStep;
  80.     glBegin(GL_TRIANGLE_STRIP);
  81.     for (j = 0; j <= numMinor; ++j) {
  82.       double a = j * minorStep;
  83.       GLfloat x = radius * cos(a);
  84.       GLfloat y = radius * sin(a);
  85.       glNormal3f(x / radius, y / radius, 0.0);
  86.       glTexCoord2f(j / (GLfloat) numMinor, i / (GLfloat) numMajor);
  87.       glVertex3f(x, y, z0);
  88.       glNormal3f(x / radius, y / radius, 0.0);
  89.       glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
  90.       glVertex3f(x, y, z1);
  91.     }
  92.     glEnd();
  93.   }
  94. }
  95. void
  96. drawTorus(int numMajor, int numMinor, float majorRadius, float minorRadius)
  97. {
  98.   double majorStep = 2.0 * M_PI / numMajor;
  99.   double minorStep = 2.0 * M_PI / numMinor;
  100.   int i, j;
  101.   for (i = 0; i < numMajor; ++i) {
  102.     double a0 = i * majorStep;
  103.     double a1 = a0 + majorStep;
  104.     GLfloat x0 = cos(a0);
  105.     GLfloat y0 = sin(a0);
  106.     GLfloat x1 = cos(a1);
  107.     GLfloat y1 = sin(a1);
  108.     glBegin(GL_TRIANGLE_STRIP);
  109.     for (j = 0; j <= numMinor; ++j) {
  110.       double b = j * minorStep;
  111.       GLfloat c = cos(b);
  112.       GLfloat r = minorRadius * c + majorRadius;
  113.       GLfloat z = minorRadius * sin(b);
  114.       glNormal3f(x0 * c, y0 * c, z / minorRadius);
  115.       glTexCoord2f(i / (GLfloat) numMajor, j / (GLfloat) numMinor);
  116.       glVertex3f(x0 * r, y0 * r, z);
  117.       glNormal3f(x1 * c, y1 * c, z / minorRadius);
  118.       glTexCoord2f((i + 1) / (GLfloat) numMajor, j / (GLfloat) numMinor);
  119.       glVertex3f(x1 * r, y1 * r, z);
  120.     }
  121.     glEnd();
  122.   }
  123. }
  124. void
  125. setNullTexture(void)
  126. {
  127.   GLubyte texPixel[4] =
  128.   {0xff, 0xff, 0xff, 0xff};
  129.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  130.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  131.   glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 1, 0,
  132.     GL_RGBA, GL_UNSIGNED_BYTE, texPixel);
  133. }
  134. void
  135. setCheckTexture(void)
  136. {
  137.   int texWidth = 64;
  138.   int texHeight = 64;
  139.   GLubyte *texPixels, *p;
  140.   int i, j;
  141.   texPixels = (GLubyte *) malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
  142.   if (texPixels == NULL) {
  143.     return;
  144.   }
  145.   p = texPixels;
  146.   for (i = 0; i < texHeight; ++i) {
  147.     for (j = 0; j < texWidth; ++j) {
  148.       if ((i ^ j) & 8) {
  149.         p[0] = 0xff;
  150.         p[1] = 0xff;
  151.         p[2] = 0xff;
  152.         p[3] = 0xff;
  153.       } else {
  154.         p[0] = 0x08;
  155.         p[1] = 0x08;
  156.         p[2] = 0x08;
  157.         p[3] = 0xff;
  158.       }
  159.       p += 4;
  160.     }
  161.   }
  162.   glTexParameteri(GL_TEXTURE_2D,
  163.     GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
  164.   glTexParameteri(GL_TEXTURE_2D,
  165.     GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  166.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  167.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  168.   gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  169.     GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
  170.   free(texPixels);
  171. }
  172. void
  173. setLight(void)
  174. {
  175.   GLfloat light0Pos[4] =
  176.   {0.70, 0.70, 1.25, 0.00};
  177.   GLfloat light0Amb[4] =
  178.   {0.00, 0.00, 0.00, 1.00};
  179.   GLfloat light0Diff[4] =
  180.   {1.00, 1.00, 1.00, 1.00};
  181.   GLfloat light0Spec[4] =
  182.   {1.00, 1.00, 1.00, 1.00};
  183.   GLfloat light0SpotDir[3] =
  184.   {0.00, 0.00, -1.00};
  185.   GLfloat light0SpotExp = 0.00;
  186.   GLfloat light0SpotCutoff = 180.00;
  187.   GLfloat light0Atten0 = 1.00;
  188.   GLfloat light0Atten1 = 0.00;
  189.   GLfloat light0Atten2 = 0.00;
  190.   glEnable(GL_LIGHT0);
  191.   glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
  192.   glLightfv(GL_LIGHT0, GL_AMBIENT, light0Amb);
  193.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diff);
  194.   glLightfv(GL_LIGHT0, GL_SPECULAR, light0Spec);
  195.   glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0SpotDir);
  196.   glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, light0SpotExp);
  197.   glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, light0SpotCutoff);
  198.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, light0Atten0);
  199.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, light0Atten1);
  200.   glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0Atten2);
  201. }
  202. #define MAT_ALL 0
  203. #define MAT_NO_SPECULAR 1
  204. #define MAT_SPECULAR_ONLY 2
  205. #define MAT_SPECULAR_TEXTURE_ONLY 3
  206. #define MAT_GEN_SPECULAR_TEXTURE 4
  207. void
  208. setMaterial(int mode)
  209. {
  210.   static GLubyte *texPixels;
  211.   int texWidth = 128;
  212.   int texHeight = 128;
  213.   GLfloat matZero[4] =
  214.   {0.00, 0.00, 0.00, 1.00};
  215.   GLfloat matOne[4] =
  216.   {1.00, 1.00, 1.00, 1.00};
  217.   GLfloat matEm[4] =
  218.   {0.00, 0.00, 0.00, 1.00};
  219.   GLfloat matAmb[4] =
  220.   {0.01, 0.01, 0.01, 1.00};
  221.   GLfloat matDiff[4] =
  222.   {0.02, 0.20, 0.16, 1.00};
  223.   GLfloat matSpec[4] =
  224.   {0.50, 0.50, 0.50, 1.00};
  225.   GLfloat matShine = 20.00;
  226.   if ((mode == MAT_ALL) || (mode == MAT_NO_SPECULAR)) {
  227.     glMaterialfv(GL_FRONT, GL_EMISSION, matEm);
  228.     glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb);
  229.     glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff);
  230.   } else {
  231.     glMaterialfv(GL_FRONT, GL_EMISSION, matZero);
  232.     glMaterialfv(GL_FRONT, GL_AMBIENT, matZero);
  233.     glMaterialfv(GL_FRONT, GL_DIFFUSE, matZero);
  234.   }
  235.   if ((mode == MAT_ALL) || (mode == MAT_SPECULAR_ONLY)) {
  236.     glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec);
  237.     glMaterialf(GL_FRONT, GL_SHININESS, matShine);
  238.   } else {
  239.     glMaterialfv(GL_FRONT, GL_SPECULAR, matZero);
  240.     glMaterialf(GL_FRONT, GL_SHININESS, 1);
  241.   }
  242.   if (mode == MAT_SPECULAR_TEXTURE_ONLY) {
  243.     if (texPixels == NULL) {
  244.       return;
  245.     }
  246.     glMaterialfv(GL_FRONT, GL_SPECULAR, matOne);
  247.     glMaterialf(GL_FRONT, GL_SHININESS, 0);
  248.     glTexParameteri(GL_TEXTURE_2D,
  249.       GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
  250.     glTexParameteri(GL_TEXTURE_2D,
  251.       GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  252.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  253.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  254.     gluBuild2DMipmaps(GL_TEXTURE_2D, 4, texWidth, texHeight,
  255.       GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
  256.   }
  257.   if (mode == MAT_GEN_SPECULAR_TEXTURE) {
  258.     if (texPixels == NULL) {
  259.       texPixels = (GLubyte *)
  260.         malloc(texWidth * texHeight * 4 * sizeof(GLubyte));
  261.       if (texPixels == NULL) {
  262.         return;
  263.       }
  264.     }
  265.     glPushAttrib(GL_ALL_ATTRIB_BITS);
  266.     glClearColor(0.0, 0.0, 0.0, 1.0);
  267.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  268.     setMaterial(MAT_SPECULAR_ONLY);
  269.     glMatrixMode(GL_PROJECTION);
  270.     glPushMatrix();
  271.     glLoadIdentity();
  272.     glOrtho(-1, 1, -1, 1, 1, 3);
  273.     glMatrixMode(GL_MODELVIEW);
  274.     glPushMatrix();
  275.     glLoadIdentity();
  276.     glTranslatef(0, 0, -2);
  277.     glPushMatrix();
  278.     glRotatef(lightRotY, 0, 1, 0);
  279.     glRotatef(lightRotX, 1, 0, 0);
  280.     setLight();
  281.     glPopMatrix();
  282.     glEnable(GL_DEPTH_TEST);
  283.     glEnable(GL_LIGHTING);
  284.     glViewport(0, 0, 128, 128);
  285.     glClearColor(.25, .25, .25, .25);
  286.     glClear(GL_COLOR_BUFFER_BIT);
  287.     drawSphere(128, 128, 1.0);
  288.     glMatrixMode(GL_PROJECTION);
  289.     glPopMatrix();
  290.     glMatrixMode(GL_MODELVIEW);
  291.     glPopMatrix();
  292.     glReadPixels(0, 0, texWidth, texHeight,
  293.       GL_RGBA, GL_UNSIGNED_BYTE, texPixels);
  294.     glPopAttrib();
  295.   }
  296. }
  297. void
  298. initialize(void)
  299. {
  300.   glMatrixMode(GL_PROJECTION);
  301.   glFrustum(-0.50, 0.50, -0.50, 0.50, 1.0, 3.0);
  302.   glMatrixMode(GL_MODELVIEW);
  303.   glTranslatef(0.0, 0.0, -2.0);
  304.   glDepthFunc(GL_LEQUAL);
  305.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
  306. }
  307. void
  308. redraw(void)
  309. {
  310.   glClearColor(0.1, 0.1, 0.1, 1.0);
  311.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  312.   glBegin(GL_QUADS);
  313.   glColor3f(0.9, 0.0, 1.0);
  314.   glVertex3f(-2.0, -2.0, -1.0);
  315.   glColor3f(0.9, 0.0, 1.0);
  316.   glVertex3f(2.0, -2.0, -1.0);
  317.   glColor3f(0.0, 0.1, 0.1);
  318.   glVertex3f(2.0, 2.0, -1.0);
  319.   glColor3f(0.0, 0.1, 0.1);
  320.   glVertex3f(-2.0, 2.0, -1.0);
  321.   glEnd();
  322.   glEnable(GL_DEPTH_TEST);
  323.   if (useLighting) {
  324.     glEnable(GL_LIGHTING);
  325.     glPushMatrix();
  326.     glRotatef(lightRotY, 0, 1, 0);
  327.     glRotatef(lightRotX, 1, 0, 0);
  328.     setLight();
  329.     glPopMatrix();
  330.   } else {
  331.     glColor3f(0.2, 0.2, 0.2);
  332.   }
  333.   if (useTexture || useSpecularTexture) {
  334.     glEnable(GL_TEXTURE_2D);
  335.   }
  336.   if (useTexture) {
  337.     setCheckTexture();
  338.   } else {
  339.     setNullTexture();
  340.   }
  341.   if (useSpecularTexture) {
  342.     /* pass one */
  343.     glEnable(GL_BLEND);
  344.     glBlendFunc(GL_ONE, GL_ZERO);
  345.     setMaterial(MAT_NO_SPECULAR);
  346.   } else {
  347.     setMaterial(MAT_ALL);
  348.   }
  349.   glPushMatrix();
  350.   glRotatef(objectRotY, 0, 1, 0);
  351.   glRotatef(objectRotX, 1, 0, 0);
  352.   if (useHighRes) {
  353.     switch (drawObj) {
  354.     case 0:
  355.       drawSphere(64, 64, 0.8);
  356.       break;
  357.     case 1:
  358.       drawCylinder(32, 64, 1.0, 0.4);
  359.       break;
  360.     case 2:
  361.       drawTorus(64, 64, 0.6, 0.2);
  362.       break;
  363.     default:
  364.       break;
  365.     }
  366.   } else {
  367.     switch (drawObj) {
  368.     case 0:
  369.       drawSphere(16, 32, 0.8);
  370.       break;
  371.     case 1:
  372.       drawCylinder(6, 16, 1.0, 0.4);
  373.       break;
  374.     case 2:
  375.       drawTorus(32, 16, 0.6, 0.2);
  376.       break;
  377.     default:
  378.       break;
  379.     }
  380.   }
  381.   glPopMatrix();
  382.   if (useSpecularTexture) {
  383.     /* pass two */
  384.     if (!useLighting) {
  385.       glColor3f(1.0, 1.0, 1.0);
  386.     }
  387.     glBlendFunc(GL_ONE, GL_ONE);
  388.     glEnable(GL_TEXTURE_GEN_S);
  389.     glEnable(GL_TEXTURE_GEN_T);
  390.     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  391.     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  392.     setMaterial(MAT_SPECULAR_TEXTURE_ONLY);
  393.     glPushMatrix();
  394.     glRotatef(objectRotY, 0, 1, 0);
  395.     glRotatef(objectRotX, 1, 0, 0);
  396.     if (useHighRes) {
  397.       switch (drawObj) {
  398.       case 0:
  399.         drawSphere(64, 64, 0.8);
  400.         break;
  401.       case 1:
  402.         drawCylinder(32, 64, 1.0, 0.4);
  403.         break;
  404.       case 2:
  405.         drawTorus(64, 64, 0.6, 0.2);
  406.         break;
  407.       default:
  408.         break;
  409.       }
  410.     } else {
  411.       switch (drawObj) {
  412.       case 0:
  413.         drawSphere(16, 32, 0.8);
  414.         break;
  415.       case 1:
  416.         drawCylinder(6, 16, 1.0, 0.4);
  417.         break;
  418.       case 2:
  419.         drawTorus(32, 16, 0.6, 0.2);
  420.         break;
  421.       default:
  422.         break;
  423.       }
  424.     }
  425.     glPopMatrix();
  426.   }
  427.   glDisable(GL_DEPTH_TEST);
  428.   glDisable(GL_LIGHTING);
  429.   glDisable(GL_TEXTURE_2D);
  430.   glDisable(GL_BLEND);
  431.   glDisable(GL_TEXTURE_GEN_S);
  432.   glDisable(GL_TEXTURE_GEN_T);
  433. }
  434. void
  435. checkErrors(void)
  436. {
  437.   GLenum error;
  438.   while ((error = glGetError()) != GL_NO_ERROR) {
  439.     fprintf(stderr, "Error: %sn", (char *) gluErrorString(error));
  440.   }
  441. }
  442. void
  443. usage(char *name)
  444. {
  445.   fprintf(stderr, "n");
  446.   fprintf(stderr, "usage: %s [ options ]n", name);
  447.   fprintf(stderr, "n");
  448.   fprintf(stderr, "  Options:n");
  449.   fprintf(stderr, "    nonen");
  450.   fprintf(stderr, "n");
  451. }
  452. void 
  453. help(void)
  454. {
  455.   printf("'h'      - helpn");
  456.   printf("'l'      - toggle lightingn");
  457.   printf("'o'      - switch objectsn");
  458.   printf("'r'      - toggle resolutionn");
  459.   printf("'s'      - toggle two pass lightingn");
  460.   printf("'t'      - toggle texturingn");
  461.   printf("left mouse     - move objectn");
  462.   printf("middle mouse   - move lightn");
  463. }
  464. void
  465. motion(int x, int y)
  466. {
  467.   if (moveLight || moveObject) {
  468.     GLfloat dx = (y - cury) * 360.0 / height;
  469.     GLfloat dy = (x - curx) * 360.0 / width;
  470.     if (moveLight) {
  471.       lightRotX += dx;
  472.       if (lightRotX > 360)
  473.         lightRotX -= 360;
  474.       if (lightRotX < 0)
  475.         lightRotX += 360;
  476.       lightRotY += dy;
  477.       if (lightRotY > 360)
  478.         lightRotY -= 360;
  479.       if (lightRotY < 0)
  480.         lightRotY += 360;
  481.       needsLightUpdate = GL_TRUE;
  482.     } else if (moveObject) {
  483.       objectRotX += dx;
  484.       if (objectRotX > 360)
  485.         objectRotX -= 360;
  486.       if (objectRotX < 0)
  487.         objectRotX += 360;
  488.       objectRotY += dy;
  489.       if (objectRotY > 360)
  490.         objectRotY -= 360;
  491.       if (objectRotY < 0)
  492.         objectRotY += 360;
  493.     }
  494.     curx = x;
  495.     cury = y;
  496.   }
  497.   glutPostRedisplay();
  498. }
  499. void
  500. mouse(int button, int state, int x, int y)
  501. {
  502.   if (state == GLUT_DOWN) {
  503.     switch (button) {
  504.     case GLUT_LEFT_BUTTON:
  505.       moveObject = GL_TRUE;
  506.       motion(curx = x, cury = y);
  507.       break;
  508.     case GLUT_MIDDLE_BUTTON:
  509.       moveLight = GL_TRUE;
  510.       motion(curx = x, cury = y);
  511.       break;
  512.     }
  513.   } else if (state == GLUT_UP) {
  514.     switch (button) {
  515.     case GLUT_LEFT_BUTTON:
  516.       moveObject = GL_FALSE;
  517.       break;
  518.     case GLUT_MIDDLE_BUTTON:
  519.       moveLight = GL_FALSE;
  520.       break;
  521.     }
  522.   }
  523. }
  524. void
  525. display(void)
  526. {
  527.   if (useSpecularTexture && needsLightUpdate) {
  528.     setMaterial(MAT_GEN_SPECULAR_TEXTURE);
  529.     needsLightUpdate = GL_FALSE;
  530.   }
  531.   redraw();
  532.   glFlush();
  533.   glutSwapBuffers();
  534.   checkErrors();
  535. }
  536. void
  537. reshape(int w, int h)
  538. {
  539.   glViewport(0, 0, width = w, height = h);
  540. }
  541. /* ARGSUSED1 */
  542. void
  543. key(unsigned char key, int x, int y)
  544. {
  545.   switch (key) {
  546.   case 'h':
  547.     help();
  548.     break;
  549.   case ' ':
  550.     break;
  551.   case 'l':
  552.     useLighting = !useLighting;
  553.     break;
  554.   case 's':
  555.     useSpecularTexture = !useSpecularTexture;
  556.     needsLightUpdate = GL_TRUE;
  557.     break;
  558.   case 't':
  559.     useTexture = !useTexture;
  560.     break;
  561.   case 'r':
  562.     useHighRes = !useHighRes;
  563.     break;
  564.   case 'o':
  565.     ++drawObj;
  566.     if (drawObj > maxObj)
  567.       drawObj = 0;
  568.     break;
  569.   case '33':
  570.     exit(0);
  571.   }
  572.   glutPostRedisplay();
  573. }
  574. /* ARGSUSED1 */
  575. void
  576. domenu(int value)
  577. {
  578.   key((unsigned char) value, 0, 0);
  579. }
  580. int
  581. main(int argc, char **argv)
  582. {
  583.   int i;
  584.   glutInit(&argc, argv);
  585.   glutInitWindowSize(width = 300, height = 300);
  586.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  587.   for (i = 1; i < argc; ++i) {
  588.     usage(argv[0]);
  589.     exit(1);
  590.   }
  591.   win = glutCreateWindow("envphong");
  592.   glutDisplayFunc(display);
  593.   glutKeyboardFunc(key);
  594.   glutReshapeFunc(reshape);
  595.   glutMouseFunc(mouse);
  596.   glutMotionFunc(motion);
  597.   glutCreateMenu(domenu);
  598.   glutAddMenuEntry("Toggle lighting", 'l');
  599.   glutAddMenuEntry("Toggle checker texture", 't');
  600.   glutAddMenuEntry("Toggle two-pass textured specular", 's');
  601.   glutAddMenuEntry("Toggle object resolution", 'r');
  602.   glutAddMenuEntry("Switch object", 'o');
  603.   glutAddMenuEntry("Print help", 'h');
  604.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  605.   initialize();
  606.   glutMainLoop();
  607.   return 0;             /* ANSI C requires main to return int. */
  608. }