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

GIS编程

开发平台:

Visual C++

  1. /* Copyright (c) Mark J. Kilgard, 1997, 1998.  */
  2. /* This program is freely distributable without licensing fees and is
  3.    provided without guarantee or warrantee expressed or implied.  This
  4.    program is -not- in the public domain. */
  5. /* This code demonstrates use of the OpenGL Real-time Shadowing (RTS)
  6.    routines.  The program renders two objects with two light sources in a
  7.    scene with several other walls and curved surfaces.  Objects cast shadows
  8.    on the walls and curved surfaces as well as each other.  The shadowing
  9.    objects spin.  See the rts.c and  rtshadow.h source code for more details. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include <stdlib.h>
  14. #include <GL/glut.h>
  15. #ifdef GLU_VERSION_1_2
  16. #include "rtshadow.h"
  17. extern GLuint makeNVidiaLogo(GLuint dlistBase);
  18. /* Some <math.h> files do not define M_PI... */
  19. #ifndef M_PI
  20. #define M_PI 3.14159265358979323846
  21. #endif
  22. enum {
  23.   X, Y, Z
  24. };
  25. enum {
  26.   DL_NONE, DL_TORUS, DL_CUBE, DL_DOUBLE_TORUS, DL_SPHERE, DL_NVIDIA_LOGO
  27. };
  28. enum {
  29.   M_TORUS, M_CUBE, M_DOUBLE_TORUS, M_NVIDIA_LOGO,
  30.   M_NORMAL_VIEW, M_LIGHT1_VIEW, M_LIGHT2_VIEW,
  31.   M_START_MOTION, M_ROTATING,
  32.   M_TWO_BIT_STENCIL, M_ALL_STENCIL,
  33.   M_RENDER_SILHOUETTE,
  34.   M_ENABLE_STENCIL_HACK, M_DISABLE_STENCIL_HACK
  35. };
  36. #define OBJECT_1  0x8000
  37. #define OBJECT_2  0x4000
  38. int fullscreen = 0, forceStencilHack = 0;
  39. int lightView = M_NORMAL_VIEW;
  40. int rotate1 = 1, rotate2 = 1;
  41. RTSscene *scene;
  42. RTSlight *light;
  43. RTSlight *light2;
  44. RTSobject *object, *object2;
  45. GLfloat eyePos[3] =
  46. {0.0, 0.0, 10.0};
  47. GLfloat lightPos[4] =
  48. {-3.9, 5.0, 1.0, 1.0};
  49. GLfloat lightPos2[4] =
  50. {4.0, 5.0, 0.0, 1.0};
  51. GLfloat objectPos[3] =
  52. {-1.0, 1.0, 0.0};
  53. GLfloat objectPos2[3] =
  54. {2.0, -2.0, 0.0};
  55. GLfloat pink[4] =
  56. {0.75, 0.5, 0.5, 1.0};
  57. GLfloat greeny[4] =
  58. {0.5, 0.75, 0.5, 1.0};
  59. int shape1 = M_TORUS, shape2 = M_CUBE;
  60. int renderSilhouette1, renderSilhouette2;
  61. GLfloat angle1 = 75.0;
  62. GLfloat angle2 = 75.0;
  63. GLfloat viewAngle = 0.0;
  64. int moving, begin;
  65. void
  66. renderBasicObject(int shape)
  67. {
  68.   switch (shape) {
  69.   case M_TORUS:
  70.     glCallList(DL_TORUS);
  71.     break;
  72.   case M_CUBE:
  73.     glCallList(DL_CUBE);
  74.     break;
  75.   case M_DOUBLE_TORUS:
  76.     glCallList(DL_DOUBLE_TORUS);
  77.     break;
  78.   case M_NVIDIA_LOGO:
  79.     glCallList(DL_NVIDIA_LOGO);
  80.     break;
  81.   }
  82. }
  83. /* ARGSUSED */
  84. void
  85. renderObject(void *data)
  86. {
  87.   glPushMatrix();
  88.   glTranslatef(objectPos[X], objectPos[Y], objectPos[Z]);
  89.   glRotatef(angle1, 1.0, 1.2, 0.0);
  90.   renderBasicObject(shape1);
  91.   glPopMatrix();
  92. }
  93. /* ARGSUSED */
  94. void
  95. renderObject2(void *data)
  96. {
  97.   glPushMatrix();
  98.   glTranslatef(objectPos2[X], objectPos2[Y], objectPos2[Z]);
  99.   glRotatef(-angle2, 1.3, 0.0, 1.0);
  100.   renderBasicObject(shape2);
  101.   glPopMatrix();
  102. }
  103. /* ARGSUSED1 */
  104. void
  105. renderScene(GLenum castingLight, void *sceneData, RTSscene * scene)
  106. {
  107.   glMatrixMode(GL_MODELVIEW);
  108.   glLoadIdentity();
  109.   switch (lightView) {
  110.   case M_NORMAL_VIEW:
  111.     gluLookAt(eyePos[X], eyePos[Y], eyePos[Z],
  112.       objectPos[X], objectPos[Y], objectPos[Z],
  113.       0.0, 1.0, 0.0);
  114.     break;
  115.   case M_LIGHT1_VIEW:
  116.     gluLookAt(lightPos[X], lightPos[Y], lightPos[Z],
  117.       objectPos[X], objectPos[Y], objectPos[Z],
  118.       0.0, 1.0, 0.0);
  119.     break;
  120.   case M_LIGHT2_VIEW:
  121.     gluLookAt(lightPos2[X], lightPos2[Y], lightPos2[Z],
  122.       objectPos[X], objectPos[Y], objectPos[Z],
  123.       0.0, 1.0, 0.0);
  124.     break;
  125.   }
  126.   glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  127.   glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
  128.   glEnable(GL_NORMALIZE);
  129.   glPushMatrix();
  130.   glTranslatef(0.0, 8.0, -5.0);
  131.   glScalef(3.0, 3.0, 3.0);
  132.   glCallList(DL_SPHERE);
  133.   glPopMatrix();
  134.   glDisable(GL_NORMALIZE);
  135.   glPushMatrix();
  136.   glTranslatef(-5.0, 0.0, 0.0);
  137.   glCallList(DL_SPHERE);
  138.   glPopMatrix();
  139.   glBegin(GL_QUADS);
  140.   glNormal3f(0.0, 0.0, 1.0);
  141.   glVertex3f(-7.5, -7.5, -7.0);
  142.   glVertex3f(7.5, -7.5, -7.0);
  143.   glVertex3f(7.5, 7.5, -7.0);
  144.   glVertex3f(-7.5, 7.5, -7.0);
  145.   glNormal3f(-1.0, 0.0, 0.0);
  146.   glVertex3f(5.0, -5.0, -5.0);
  147.   glVertex3f(5.0, -5.0, 5.0);
  148.   glVertex3f(5.0, 5.0, 5.0);
  149.   glVertex3f(5.0, 5.0, -5.0);
  150.   glNormal3f(0.0, 1.0, 0.0);
  151.   glVertex3f(-5.0, -5.0, -5.0);
  152.   glVertex3f(-5.0, -5.0, 5.0);
  153.   glVertex3f(5.0, -5.0, 5.0);
  154.   glVertex3f(5.0, -5.0, -5.0);
  155.   glEnd();
  156.   if (castingLight == GL_NONE) {
  157.     /* Rendering that is not affected by lighting should be drawn only once.
  158.        The time to render it is when no light is casting. */
  159.     glDisable(GL_LIGHTING);
  160.     glColor3fv(pink);
  161.     glPushMatrix();
  162.     glTranslatef(lightPos[X], lightPos[Y], lightPos[Z]);
  163.     glutSolidSphere(0.3, 8, 8);
  164.     glPopMatrix();
  165.     glColor3fv(greeny);
  166.     glPushMatrix();
  167.     glTranslatef(lightPos2[X], lightPos2[Y], lightPos2[Z]);
  168.     glutSolidSphere(0.3, 8, 8);
  169.     glPopMatrix();
  170.     glEnable(GL_LIGHTING);
  171.   }
  172.   renderObject(NULL);
  173.   renderObject2(NULL);
  174. }
  175. void
  176. reshape(int w, int h)
  177. {
  178.   GLfloat wf = w, hf = h;
  179.   glViewport(0, 0, w, h);
  180.   glMatrixMode(GL_PROJECTION);
  181.   glLoadIdentity();
  182.   gluPerspective(70.0, wf/hf, 0.5, 30.0);
  183.   glMatrixMode(GL_MODELVIEW);
  184. }
  185. void
  186. display(void)
  187. {
  188.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  189.   rtsRenderScene(scene, RTS_USE_SHADOWS);
  190.   if (renderSilhouette1) {
  191.     glColor3f(0.0, 1.0, 0.0);
  192.     rtsRenderSilhouette(scene, light, object);
  193.     glColor3f(0.0, 0.0, 1.0);
  194.     rtsRenderSilhouette(scene, light2, object);
  195.   }
  196.   if (renderSilhouette2) {
  197.     glColor3f(1.0, 0.0, 0.0);
  198.     rtsRenderSilhouette(scene, light, object2);
  199.     glColor3f(1.0, 1.0, 0.0);
  200.     rtsRenderSilhouette(scene, light2, object2);
  201.   }
  202.   glutSwapBuffers();
  203. }
  204. void
  205. idle(void)
  206. {
  207.   if (rotate1) {
  208.     angle1 += 10;
  209.     rtsUpdateObjectShape(object);
  210.   }
  211.   if (rotate2) {
  212.     angle2 += 10;
  213.     rtsUpdateObjectShape(object2);
  214.   }
  215.   glutPostRedisplay();
  216. }
  217. /* ARGSUSED1 */
  218. void
  219. special(int c, int x, int y)
  220. {
  221.   switch (c) {
  222.   case GLUT_KEY_UP:
  223.     lightPos[Y] += 0.5;
  224.     rtsUpdateLightPos(light, lightPos);
  225.     break;
  226.   case GLUT_KEY_DOWN:
  227.     lightPos[Y] -= 0.5;
  228.     rtsUpdateLightPos(light, lightPos);
  229.     break;
  230.   case GLUT_KEY_RIGHT:
  231.     lightPos[X] += 0.5;
  232.     rtsUpdateLightPos(light, lightPos);
  233.     break;
  234.   case GLUT_KEY_LEFT:
  235.     lightPos[X] -= 0.5;
  236.     rtsUpdateLightPos(light, lightPos);
  237.     break;
  238.   case GLUT_KEY_PAGE_UP:
  239.     lightPos[Z] += 0.5;
  240.     rtsUpdateLightPos(light, lightPos);
  241.     break;
  242.   case GLUT_KEY_PAGE_DOWN:
  243.     lightPos[Z] -= 0.5;
  244.     rtsUpdateLightPos(light, lightPos);
  245.     break;
  246.   case GLUT_KEY_HOME:
  247.     angle1 += 15;
  248.     angle2 += 15;
  249.     rtsUpdateObjectShape(object);
  250.     rtsUpdateObjectShape(object2);
  251.     break;
  252.   case GLUT_KEY_END:
  253.     angle1 -= 15;
  254.     angle2 -= 15;
  255.     rtsUpdateObjectShape(object);
  256.     rtsUpdateObjectShape(object2);
  257.     break;
  258.   case GLUT_KEY_F1:
  259.     lightView = !lightView;
  260.     break;
  261.   }
  262.   glutPostRedisplay();
  263. }
  264. void
  265. updateIdleCallback(void)
  266. {
  267.   if (rotate1 || rotate2) {
  268.     glutIdleFunc(idle);
  269.   } else {
  270.     glutIdleFunc(NULL);
  271.   }
  272. }
  273. /* ARGSUSED1 */
  274. void
  275. menuHandler(int value)
  276. {
  277.   switch (value) {
  278.   case OBJECT_1 | M_TORUS:
  279.   case OBJECT_1 | M_CUBE:
  280.   case OBJECT_1 | M_DOUBLE_TORUS:
  281.   case OBJECT_1 | M_NVIDIA_LOGO:
  282.     shape1 = value & ~OBJECT_1;
  283.     rtsUpdateObjectShape(object);
  284.     glutPostRedisplay();
  285.     break;
  286.   case OBJECT_2 | M_TORUS:
  287.   case OBJECT_2 | M_CUBE:
  288.   case OBJECT_2 | M_DOUBLE_TORUS:
  289.   case OBJECT_2 | M_NVIDIA_LOGO:
  290.     shape2 = value & ~OBJECT_2;
  291.     rtsUpdateObjectShape(object2);
  292.     glutPostRedisplay();
  293.     break;
  294.   case M_NORMAL_VIEW:
  295.   case M_LIGHT1_VIEW:
  296.   case M_LIGHT2_VIEW:
  297.     lightView = value;
  298.     glutPostRedisplay();
  299.     break;
  300.   case M_START_MOTION:
  301.     rotate1 = 1;
  302.     rotate2 = 1;
  303.     glutIdleFunc(idle);
  304.     break;
  305.   case OBJECT_1 | M_ROTATING:
  306.     rotate1 = !rotate1;
  307.     updateIdleCallback();
  308.     break;
  309.   case OBJECT_2 | M_ROTATING:
  310.     rotate2 = !rotate2;
  311.     updateIdleCallback();
  312.     break;
  313.   case M_ALL_STENCIL:
  314.     rtsUpdateUsableStencilBits(scene, ~0);
  315.     glutPostRedisplay();
  316.     break;
  317.   case M_TWO_BIT_STENCIL:
  318.     rtsUpdateUsableStencilBits(scene, 0x3);
  319.     glutPostRedisplay();
  320.     break;
  321.   case OBJECT_1 | M_RENDER_SILHOUETTE:
  322.     renderSilhouette1 = !renderSilhouette1;
  323.     glutPostRedisplay();
  324.     break;
  325.   case OBJECT_2 | M_RENDER_SILHOUETTE:
  326.     renderSilhouette2 = !renderSilhouette2;
  327.     glutPostRedisplay();
  328.     break;
  329.   case M_ENABLE_STENCIL_HACK:
  330.     rtsStencilRenderingInvariantHack(scene, GL_TRUE);
  331.     glutPostRedisplay();
  332.     break;
  333.   case M_DISABLE_STENCIL_HACK:
  334.     rtsStencilRenderingInvariantHack(scene, GL_FALSE);
  335.     glutPostRedisplay();
  336.     break;
  337.   }
  338. }
  339. void
  340. keyboard(unsigned char c, int x, int y)
  341. {
  342.   switch (c) {
  343.   case 27:
  344.     exit(0);
  345.     /* NOTREACHED */
  346.     break;
  347.   case ' ':
  348.     if (rotate1 || rotate2) {
  349.       glutIdleFunc(NULL);
  350.       rotate1 = 0;
  351.       rotate2 = 0;
  352.     } else {
  353.       glutIdleFunc(idle);
  354.       rotate1 = 1;
  355.       rotate2 = 1;
  356.     }
  357.     break;
  358.   case '1':
  359.     menuHandler(OBJECT_1 | M_TORUS);
  360.     break;
  361.   case '2':
  362.     menuHandler(OBJECT_1 | M_CUBE);
  363.     break;
  364.   case '3':
  365.     menuHandler(OBJECT_1 | M_DOUBLE_TORUS);
  366.     break;
  367.   case '4':
  368.     menuHandler(OBJECT_1 | M_NVIDIA_LOGO);
  369.     break;
  370.   case '5':
  371.     menuHandler(OBJECT_2 | M_TORUS);
  372.     break;
  373.   case '6':
  374.     menuHandler(OBJECT_2 | M_CUBE);
  375.     break;
  376.   case '7':
  377.     menuHandler(OBJECT_2 | M_DOUBLE_TORUS);
  378.     break;
  379.   case '8':
  380.     menuHandler(OBJECT_2 | M_NVIDIA_LOGO);
  381.     break;
  382.   }
  383. }
  384. void
  385. visible(int vis)
  386. {
  387.   if (vis == GLUT_VISIBLE)
  388.     updateIdleCallback();
  389.   else
  390.     glutIdleFunc(NULL);
  391. }
  392. void
  393. initMenu(void)
  394. {
  395.   glutCreateMenu(menuHandler);
  396.   glutAddMenuEntry("1 Torus", OBJECT_1 | M_TORUS);
  397.   glutAddMenuEntry("1 Cube", OBJECT_1 | M_CUBE);
  398.   glutAddMenuEntry("1 Double torus", OBJECT_1 | M_DOUBLE_TORUS);
  399.   glutAddMenuEntry("1 NVIDIA logo", OBJECT_1 | M_NVIDIA_LOGO);
  400.   glutAddMenuEntry("2 Torus", OBJECT_2 | M_TORUS);
  401.   glutAddMenuEntry("2 Cube", OBJECT_2 | M_CUBE);
  402.   glutAddMenuEntry("2 Double torus", OBJECT_2 | M_DOUBLE_TORUS);
  403.   glutAddMenuEntry("2 NVIDIA logo", OBJECT_2 | M_NVIDIA_LOGO);
  404.   glutAddMenuEntry("Normal view", M_NORMAL_VIEW);
  405.   glutAddMenuEntry("View from light 1", M_LIGHT1_VIEW);
  406.   glutAddMenuEntry("View from light 2", M_LIGHT2_VIEW);
  407.   glutAddMenuEntry("Start motion", M_START_MOTION);
  408.   glutAddMenuEntry("1 Toggle rotating", OBJECT_1 | M_ROTATING);
  409.   glutAddMenuEntry("2 Toggle rotating", OBJECT_2 | M_ROTATING);
  410.   glutAddMenuEntry("Use all stencil", M_ALL_STENCIL);
  411.   glutAddMenuEntry("Use only 2 bits stencil", M_TWO_BIT_STENCIL);
  412.   glutAddMenuEntry("1 Toggle silhouette", OBJECT_1 | M_RENDER_SILHOUETTE);
  413.   glutAddMenuEntry("2 Toggle silhouette", OBJECT_2 | M_RENDER_SILHOUETTE);
  414.   glutAddMenuEntry("Enable stencil hack", M_ENABLE_STENCIL_HACK);
  415.   glutAddMenuEntry("Disable stencil hack", M_DISABLE_STENCIL_HACK);
  416.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  417. }
  418. /* ARGSUSED2 */
  419. void
  420. mouse(int button, int state, int x, int y)
  421. {
  422.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  423.     moving = 1;
  424.     begin = x;
  425.   }
  426.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  427.     moving = 0;
  428.   }
  429. }
  430. /* ARGSUSED1 */
  431. void
  432. motion(int x, int y)
  433. {
  434.   if (moving) {
  435.     viewAngle = viewAngle + (x - begin);
  436.     eyePos[X] = sin(viewAngle * M_PI / 180.0) * 10.0;
  437.     eyePos[Z] = cos(viewAngle * M_PI / 180.0) * 10.0;
  438.     begin = x;
  439.     glutPostRedisplay();
  440.   }
  441. }
  442. /* XXX RIVA 128 board vendors may change their GL_VENDOR
  443.    and GL_RENDERER strings. */
  444. int
  445. needsStencilRenderingInvariantHack(void)
  446. {
  447.   const char *renderer;
  448.   GLint bits;
  449.   renderer = glGetString(GL_RENDERER);
  450.   /* Stencil rendering on RIVA 128 and RIVA 128 ZX 
  451.      is not invariant with stencil-disabled rendering
  452.      in 16-bit hardware accelerated mode. */
  453.   if (!strncmp("RIVA 128", renderer, 8)) {
  454.     glGetIntegerv(GL_INDEX_BITS, &bits);
  455.     return bits == 16;
  456.   }
  457.   /* Stencil rendering on RIVA 128 and RIVA 128 ZX 
  458.      is not invariant with stencil-disabled rendering
  459.      in 16-bit hardware accelerated mode.  32-bit mode
  460.      is invariant (and hardware accelerated though!).  */
  461.   if (!strncmp("RIVA TNT", renderer, 8)) {
  462.     glGetIntegerv(GL_INDEX_BITS, &bits);
  463.     return bits == 16;
  464.   }
  465.   return 1;
  466. }
  467. void
  468. parseArgs(int argc, char **argv)
  469. {
  470.   int i;
  471.   for (i=1; i<argc; i++) {
  472.     if (!strcmp("-fullscreen", argv[i])) {
  473.       fullscreen = 1;
  474.     } else if (!strcmp("-stencilhack", argv[i])) {
  475.       forceStencilHack = 1;
  476.     }
  477.   }
  478. }
  479. int
  480. main(int argc, char **argv)
  481. {
  482.   glutInitDisplayString("stencil>=2 rgb depth samples");
  483.   glutInitDisplayString("stencil>=2 rgb double depth samples");
  484.   glutInit(&argc, argv);
  485.   parseArgs(argc, argv);
  486.   if (fullscreen) {
  487.     glutGameModeString("640x480:32@60");
  488.     glutEnterGameMode();
  489.   } else {
  490.     glutCreateWindow("Hello to Real Time Shadows");
  491.   }
  492.   glutReshapeFunc(reshape);
  493.   glutDisplayFunc(display);
  494.   glutSpecialFunc(special);
  495.   glutKeyboardFunc(keyboard);
  496.   glutVisibilityFunc(visible);
  497.   glutMouseFunc(mouse);
  498.   glutMotionFunc(motion);
  499.   /* 0xffffffff means "use as much stencil as is available". */
  500.   scene = rtsCreateScene(eyePos, 0xffffffff, renderScene, NULL);
  501.   glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  502.   glLightfv(GL_LIGHT0, GL_DIFFUSE, pink);
  503.   light = rtsCreateLight(GL_LIGHT0, lightPos, 1000.0);
  504.   glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
  505.   glLightfv(GL_LIGHT1, GL_DIFFUSE, greeny);
  506.   light2 = rtsCreateLight(GL_LIGHT1, lightPos2, 1000.0);
  507.   object = rtsCreateObject(objectPos, 1.0, renderObject, NULL, 100);
  508.   object2 = rtsCreateObject(objectPos2, 1.0, renderObject2, NULL, 100);
  509.   rtsAddLightToScene(scene, light);
  510.   rtsAddObjectToLight(light, object);
  511.   rtsAddObjectToLight(light, object2);
  512.   rtsAddLightToScene(scene, light2);
  513.   rtsAddObjectToLight(light2, object);
  514.   rtsAddObjectToLight(light2, object2);
  515.   if (forceStencilHack || needsStencilRenderingInvariantHack()) {
  516.     /* RIVA 128 and RIVA 128 ZX lack hardware stencil
  517.        support and the hardware rasterization path
  518.        (non-stenciled) and the software rasterization
  519.        path (with stenciling enabled) do not meet the
  520.        invariants. */
  521.     rtsStencilRenderingInvariantHack(scene, GL_TRUE);
  522.   }
  523.   glEnable(GL_CULL_FACE);
  524.   glEnable(GL_DEPTH_TEST);
  525.   if (!fullscreen) {
  526.     initMenu();
  527.   }
  528.   glNewList(DL_TORUS, GL_COMPILE);
  529.   glutSolidTorus(0.2, 0.8, 10, 10);
  530.   glEndList();
  531.   glNewList(DL_CUBE, GL_COMPILE);
  532.   glutSolidCube(1.0);
  533.   glEndList();
  534.   glNewList(DL_DOUBLE_TORUS, GL_COMPILE);
  535.   glCallList(DL_TORUS);
  536.   glRotatef(90.0, 0.0, 1.0, 0.0);
  537.   glCallList(DL_TORUS);
  538.   glRotatef(-90.0, 0.0, 1.0, 0.0);
  539.   glEndList();
  540.   glNewList(DL_SPHERE, GL_COMPILE);
  541.   glutSolidSphere(1.5, 20, 20);
  542.   glEndList();
  543.   makeNVidiaLogo(1000);
  544.   glNewList(DL_NVIDIA_LOGO, GL_COMPILE);
  545.   glPushMatrix();
  546.   glScalef(.25, .25, .25);
  547.   glEnable(GL_NORMALIZE);
  548.   glCallList(1000);
  549.   glDisable(GL_NORMALIZE);
  550.   glPopMatrix();
  551.   glEndList();
  552.   glutMainLoop();
  553.   return 0;             /* ANSI C requires main to return int. */
  554. }
  555. #else
  556. int main(int argc, char** argv)
  557. {
  558.   fprintf(stderr, "This program requires the new tesselator API in GLU 1.2.n");
  559.   fprintf(stderr, "Your GLU library does not support this new interface, sorry.n");
  560.   return 0;
  561. }
  562. #endif  /* GLU_VERSION_1_2 */