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

GIS编程

开发平台:

Visual C++

  1. /* Copyright (c) Mark J. Kilgard, 1997.  */
  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 example shows how to use the GLU polygon tessellator to determine the 
  6.    2D boundary of OpenGL rendered objects.  The program uses OpenGL's
  7.    feedback mechanim to capture transformed polygons and then feeds them to
  8.    the GLU tesselator in GLU_TESS_WINDING_NONZERO and GLU_TESS_BOUNDARY_ONLY
  9.    mode. */
  10. #include <assert.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <GL/glut.h>
  14. #ifdef GLU_VERSION_1_2
  15. #ifndef CALLBACK
  16. #define CALLBACK
  17. #endif
  18. enum {
  19.   M_TORUS, M_CUBE, M_SPHERE, M_ICO, M_TEAPOT, M_ANGLE, M_BOUNDARY
  20. };
  21. struct VertexHolder {
  22.   struct VertexHolder *next;
  23.   GLfloat v[2];
  24. };
  25. int shape = M_TORUS;
  26. int boundary = 1;
  27. GLfloat angle = 0.0;
  28. GLfloat lightDiffuse[] =
  29. {1.0, 0.0, 0.0, 1.0};
  30. GLfloat lightPosition[] =
  31. {1.0, 1.0, 1.0, 0.0};
  32. GLUtesselator *tess;
  33. int width, height;
  34. static void CALLBACK
  35. begin(GLenum type)
  36. {
  37.   assert(type == GL_LINE_LOOP);
  38.   glBegin(type);
  39. }
  40. static void CALLBACK
  41. vertex(void *data)
  42. {
  43.   GLfloat *v = data;
  44.   glVertex2fv(v);
  45. }
  46. static void CALLBACK
  47. end(void)
  48. {
  49.   glEnd();
  50. }
  51. static GLfloat *combineList = NULL;
  52. static int combineListSize = 0;
  53. static int combineNext = 0;
  54. static struct VertexHolder *excessList = NULL;
  55. static void
  56. freeExcessList(void)
  57. {
  58.   struct VertexHolder *holder, *next;
  59.   holder = excessList;
  60.   while (holder) {
  61.     next = holder->next;
  62.     free(holder);
  63.     holder = next;
  64.   }
  65.   excessList = NULL;
  66. }
  67. /* ARGSUSED1 */
  68. static void CALLBACK
  69. combine(GLdouble coords[3], void *d[4], GLfloat w[4], void **dataOut)
  70. {
  71.   GLfloat *newCoords;
  72.   struct VertexHolder *holder;
  73.   /* XXX Careful, some systems still don't understand realloc of NULL. */
  74.   if (combineNext >= combineListSize) {
  75.     holder = (struct VertexHolder *) malloc(sizeof(struct VertexHolder));
  76.     holder->next = excessList;
  77.     excessList = holder;
  78.     newCoords = holder->v;
  79.   } else {
  80.     newCoords = &combineList[combineNext * 2];
  81.   }
  82.   newCoords[0] = coords[0];
  83.   newCoords[1] = coords[1];
  84.   *dataOut = newCoords;
  85.   combineNext++;
  86. }
  87. static void CALLBACK
  88. error(GLenum errno)
  89. {
  90.   printf("ERROR: %sn", gluErrorString(errno));
  91. }
  92. void
  93. reshape(int w, int h)
  94. {
  95.   width = w;
  96.   height = h;
  97.   glViewport(0, 0, width, height);
  98. }
  99. void
  100. processFeedback(GLint size, GLfloat * buffer)
  101. {
  102.   GLfloat *loc, *end;
  103.   GLdouble v[3];
  104.   int token, nvertices, i;
  105.   if (combineNext > combineListSize) {
  106.     freeExcessList();
  107.     combineListSize = combineNext;
  108.     combineList = realloc(combineList, sizeof(GLfloat) * 2 * combineListSize);
  109.   }
  110.   combineNext = 0;
  111.   gluTessBeginPolygon(tess, NULL);
  112.   loc = buffer;
  113.   end = buffer + size;
  114.   while (loc < end) {
  115.     token = *loc;
  116.     loc++;
  117.     switch (token) {
  118.     case GL_POLYGON_TOKEN:
  119.       nvertices = *loc;
  120.       loc++;
  121.       assert(nvertices >= 3);
  122.       gluTessBeginContour(tess);
  123.       for (i = 0; i < nvertices; i++) {
  124.         v[0] = loc[0];
  125.         v[1] = loc[1];
  126.         v[2] = 0.0;
  127.         gluTessVertex(tess, v, loc);
  128.         loc += 2;
  129.       }
  130.       gluTessEndContour(tess);
  131.       break;
  132.     default:
  133.       /* Ignore everything but polygons. */
  134.       ;
  135.     }
  136.   }
  137.   gluTessEndPolygon(tess);
  138. }
  139. int
  140. determineBoundary(void (*renderFunc) (void), int probableSize)
  141. {
  142.   static GLfloat *feedbackBuffer = NULL;
  143.   static int bufferSize = 0;
  144.   GLint returned;
  145.   if (bufferSize > probableSize) {
  146.     probableSize = bufferSize;
  147.   }
  148. doFeedback:
  149.   /* XXX Careful, some systems still don't understand realloc of NULL. */
  150.   if (bufferSize < probableSize) {
  151.     bufferSize = probableSize;
  152.     feedbackBuffer = realloc(feedbackBuffer, bufferSize * sizeof(GLfloat));
  153.   }
  154.   glFeedbackBuffer(bufferSize, GL_2D, feedbackBuffer);
  155.   (void) glRenderMode(GL_FEEDBACK);
  156.   (*renderFunc) ();
  157.   returned = glRenderMode(GL_RENDER);
  158. #if 0
  159.   if (returned == -1) {
  160. #else
  161.   /* XXX RealityEngine workaround. */
  162.   if (returned == -1 || returned == probableSize) { 
  163. #endif
  164.     probableSize = probableSize + (probableSize >> 1);
  165.     goto doFeedback;    /* Try again with larger feedback buffer. */
  166.   }
  167.   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  168.   glMatrixMode(GL_PROJECTION);
  169.   glLoadIdentity();
  170.   gluOrtho2D(0, width, 0, height);
  171.   glMatrixMode(GL_MODELVIEW);
  172.   glLoadIdentity();
  173.   processFeedback(returned, feedbackBuffer);
  174.   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  175.   return returned;
  176. }
  177. void
  178. render(void)
  179. {
  180.   glMatrixMode(GL_PROJECTION);
  181.   glLoadIdentity();
  182.   gluPerspective( /* field of view in degree */ 30.0,
  183.   /* aspect ratio */ 1.0,
  184.     /* Z near */ 1.0, /* Z far */ 20.0);
  185.   glMatrixMode(GL_MODELVIEW);
  186.   glLoadIdentity();
  187.   gluLookAt(0.0, 0.0, 10.0,  /* eye is at (0,0,5) */
  188.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  189.     0.0, 1.0, 0.);      /* up is in postivie Y direction */
  190.   glPushMatrix();
  191.   glRotatef(angle, 1.0, 0.3, 0.0);
  192.   switch (shape) {
  193.   case M_TORUS:
  194.     glutSolidTorus(0.275, 0.85, 8, 8);
  195.     break;
  196.   case M_CUBE:
  197.     glutSolidCube(1.0);
  198.     break;
  199.   case M_SPHERE:
  200.     glutSolidSphere(1.0, 10, 10);
  201.     break;
  202.   case M_ICO:
  203.     glutSolidIcosahedron();
  204.     break;
  205.   case M_TEAPOT:
  206.     glutSolidTeapot(1.0);
  207.     break;
  208.   }
  209.   glPopMatrix();
  210. }
  211. void
  212. display(void)
  213. {
  214.   if (boundary) {
  215.     glClear(GL_COLOR_BUFFER_BIT);
  216.     glDisable(GL_LIGHTING);
  217.     glDisable(GL_DEPTH_TEST);
  218.     glEnable(GL_CULL_FACE);
  219.     determineBoundary(render, 250);
  220.   } else {
  221.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  222.     glEnable(GL_LIGHTING);
  223.     glEnable(GL_DEPTH_TEST);
  224.     glDisable(GL_CULL_FACE);
  225.     render();
  226.   }
  227.   glutSwapBuffers();
  228. }
  229. void
  230. menu(int value)
  231. {
  232.   switch (value) {
  233.   case M_TORUS:
  234.   case M_CUBE:
  235.   case M_SPHERE:
  236.   case M_ICO:
  237.   case M_TEAPOT:
  238.     shape = value;
  239.     break;
  240.   case M_ANGLE:
  241.     angle += 10.0;
  242.     break;
  243.   case M_BOUNDARY:
  244.     boundary = !boundary;  /* Toggle. */
  245.     break;
  246.   }
  247.   glutPostRedisplay();
  248. }
  249. /* ARGSUSED1 */
  250. void
  251. special(int key, int x, int y)
  252. {
  253.   switch (key) {
  254.   case GLUT_KEY_UP:
  255.     angle += 10.0;
  256.     glutPostRedisplay();
  257.     break;
  258.   case GLUT_KEY_DOWN:
  259.     angle -= 10.0;
  260.     glutPostRedisplay();
  261.     break;
  262.   }
  263. }
  264. int
  265. main(int argc, char **argv)
  266. {
  267.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  268.   glutInit(&argc, argv);
  269.   glutCreateWindow("boundary");
  270.   glutDisplayFunc(display);
  271.   glutReshapeFunc(reshape);
  272.   glutSpecialFunc(special);
  273.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
  274.   glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
  275.   glEnable(GL_LIGHT0);
  276.   tess = gluNewTess();
  277.   gluTessProperty(tess, GLU_TESS_BOUNDARY_ONLY, GL_TRUE);
  278.   gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
  279.   gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK*)())begin);
  280.   gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)())vertex);
  281.   gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK*)())end);
  282.   gluTessCallback(tess, GLU_TESS_ERROR, (void (CALLBACK*)())error);
  283.   gluTessCallback(tess, GLU_TESS_COMBINE, (void (CALLBACK*)())combine);
  284.   glutCreateMenu(menu);
  285.   glutAddMenuEntry("Torus", M_TORUS);
  286.   glutAddMenuEntry("Cube", M_CUBE);
  287.   glutAddMenuEntry("Sphere", M_SPHERE);
  288.   glutAddMenuEntry("Icosahedron", M_ICO);
  289.   glutAddMenuEntry("Teapot", M_TEAPOT);
  290.   glutAddMenuEntry("Angle", M_ANGLE);
  291.   glutAddMenuEntry("Toggle boundary", M_BOUNDARY);
  292.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  293.   glutMainLoop();
  294.   return 0;             /* ANSI C requires main to return int. */
  295. }
  296. #else
  297. int main(int argc, char** argv)
  298. {
  299.   fprintf(stderr, "This program demonstrates the new tesselator API in GLU 1.2.n");
  300.   fprintf(stderr, "Your GLU library does not support this new interface, sorry.n");
  301.   return 0;
  302. }
  303. #endif  /* GLU_VERSION_1_2 */