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

GIS编程

开发平台:

Visual C++

  1. /* tess_demo.c */
  2. /* A demo of the GLU polygon tesselation functions written by Bogdan Sikorski. */
  3. /* Bug fixes by Mark Kilgard 11/8/96 */
  4. #include <GL/glut.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. /* Win32 calling conventions. */
  9. #ifndef CALLBACK
  10. #define CALLBACK
  11. #endif
  12. #define MAX_POINTS 200
  13. #define MAX_CONTOURS 50
  14. #define HALF_WIDTH 5     /* half of the width of a grid box */
  15. int menu;
  16. typedef enum {
  17.   QUIT, TESSELATE, CLEAR
  18. } menu_entries;
  19. typedef enum {
  20.   DEFINE, TESSELATED
  21. } mode_type;
  22. struct {
  23.   GLint p[MAX_POINTS][2];
  24.   GLuint point_cnt;
  25. } contours[MAX_CONTOURS];
  26. int contour_cnt;
  27. GLsizei width, height;
  28. mode_type mode;
  29. #ifdef GLU_VERSION_1_2
  30. typedef struct listmem {
  31.    GLint *data;
  32.    struct listmem *next;
  33. } ListMem;
  34. ListMem root;
  35. #endif
  36. void CALLBACK
  37. my_error(GLenum err)
  38. {
  39.   int len, i;
  40.   const char *str;
  41.   glColor3f(0.9, 0.9, 0.9);
  42.   glRasterPos2i(5, 5);
  43.   str = (char *) gluErrorString(err);
  44.   len = (int) strlen(str);
  45.   for (i = 0; i < len; i++)
  46.     glutBitmapCharacter(GLUT_BITMAP_9_BY_15, str[i]);
  47. }
  48. #ifdef GLU_VERSION_1_2
  49. /* ARGSUSED */
  50. void CALLBACK
  51. myCombine(GLdouble coords[3], void *d[4], GLfloat w[4], void **dataOut)
  52. {
  53.    ListMem *ptr = &root;
  54.    while (ptr->next) ptr = ptr->next;
  55.    ptr->next = malloc(sizeof(ListMem));
  56.    ptr = ptr->next;
  57.    ptr->next = 0;
  58.    ptr->data = malloc(3 * sizeof(GLint));
  59.    ptr->data[0] = (GLint) coords[0];
  60.    ptr->data[1] = (GLint) coords[1];
  61.    ptr->data[2] = (GLint) coords[2];
  62.    *dataOut = ptr->data;
  63. }
  64. #endif
  65. void 
  66. set_screen_wh(GLsizei w, GLsizei h)
  67. {
  68.   width = w;
  69.   height = h;
  70. }
  71. void 
  72. tesse(void)
  73. {
  74.   static GLUtriangulatorObj *tobj = NULL;
  75.   GLdouble data[3];
  76.   int i, j, point_cnt;
  77.   if (tobj == NULL) {
  78.     tobj = gluNewTess();
  79.   }
  80.   if (tobj != NULL) {
  81.     glClear(GL_COLOR_BUFFER_BIT);
  82.     glColor3f(0.7, 0.5, 0.0);
  83.     gluTessCallback(tobj, GLU_BEGIN, (void (CALLBACK*)())glBegin);
  84.     gluTessCallback(tobj, GLU_END, (void (CALLBACK*)())glEnd);
  85.     gluTessCallback(tobj, GLU_ERROR, (void (CALLBACK*)()) my_error);
  86.     gluTessCallback(tobj, GLU_VERTEX, (void (CALLBACK*)()) glVertex2iv);
  87. #ifdef GLU_VERSION_1_2
  88.     root.data = 0;
  89.     root.next = 0;
  90.     gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK*)()) myCombine);
  91. #endif
  92.     gluBeginPolygon(tobj);
  93.     for (j = 0; j <= contour_cnt; j++) {
  94.       point_cnt = contours[j].point_cnt;
  95.       gluNextContour(tobj, GLU_UNKNOWN);
  96.       for (i = 0; i < point_cnt; i++) {
  97.         data[0] = (GLdouble) (contours[j].p[i][0]);
  98.         data[1] = (GLdouble) (contours[j].p[i][1]);
  99.         data[2] = 0.0;
  100.         gluTessVertex(tobj, data, contours[j].p[i]);
  101.       }
  102.     }
  103.     gluEndPolygon(tobj);
  104.     mode = TESSELATED;
  105.   }
  106. #ifdef GLU_VERSION_1_2
  107.   {
  108.     ListMem *fptr = root.next;
  109.     ListMem *tmp;
  110.     while (fptr) {
  111.       tmp = fptr->next;
  112.       free(fptr->data);
  113.       free(fptr);
  114.       fptr = tmp;
  115.     }
  116.   }
  117. #endif
  118. }
  119. void 
  120. left_down(int x1, int y1)
  121. {
  122.   GLint P[2];
  123.   GLuint point_cnt;
  124.   /* translate GLUT into GL coordinates */
  125.   P[0] = x1;
  126.   P[1] = height - y1;
  127.   point_cnt = contours[contour_cnt].point_cnt;
  128.   contours[contour_cnt].p[point_cnt][0] = P[0];
  129.   contours[contour_cnt].p[point_cnt][1] = P[1];
  130.   glBegin(GL_LINES);
  131.   if (point_cnt) {
  132.     glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
  133.     glVertex2iv(P);
  134.   } else {
  135.     glVertex2iv(P);
  136.     glVertex2iv(P);
  137.   }
  138.   glEnd();
  139.   glFlush();
  140.   ++(contours[contour_cnt].point_cnt);
  141.   if (contours[contour_cnt].point_cnt >= MAX_POINTS) {
  142.     printf("Too many points specified.n");
  143.     exit(1);
  144.   }
  145. }
  146. /* ARGSUSED */
  147. void 
  148. middle_down(int x1, int y1)
  149. {
  150.   GLuint point_cnt;
  151.   point_cnt = contours[contour_cnt].point_cnt;
  152.   if (point_cnt > 2) {
  153.     glBegin(GL_LINES);
  154.     glVertex2iv(contours[contour_cnt].p[0]);
  155.     glVertex2iv(contours[contour_cnt].p[point_cnt - 1]);
  156.     contours[contour_cnt].p[point_cnt][0] = -1;
  157.     glEnd();
  158.     glFlush();
  159.     contour_cnt++;
  160.     if (contour_cnt >= MAX_CONTOURS) {
  161.       printf("Too many contours specified.n");
  162.       exit(1);
  163.     }
  164.     contours[contour_cnt].point_cnt = 0;
  165.   }
  166. }
  167. void 
  168. mouse_clicked(int button, int state, int x, int y)
  169. {
  170.   x += HALF_WIDTH;
  171.   y += HALF_WIDTH;
  172.   x -= x % (2*HALF_WIDTH);
  173.   y -= y % (2*HALF_WIDTH);
  174.   switch (button) {
  175.   case GLUT_LEFT_BUTTON:
  176.     if (state == GLUT_DOWN)
  177.       left_down(x, y);
  178.     break;
  179.   case GLUT_MIDDLE_BUTTON:
  180.     if (state == GLUT_DOWN)
  181.       middle_down(x, y);
  182.     break;
  183.   }
  184. }
  185. void 
  186. display(void)
  187. {
  188.   GLint i, j;
  189.   int point_cnt;
  190.   glClear(GL_COLOR_BUFFER_BIT);
  191.   switch (mode) {
  192.   case DEFINE:
  193.     /* draw grid */
  194.     glColor3f(0.6, 0.5, 0.5);
  195.     glBegin(GL_LINES);
  196.     for (i = 0; i < width; i += (2*HALF_WIDTH)) {
  197.         glVertex2i(i, height);
  198.         glVertex2i(i, 0);
  199.     }
  200.     for (j = 0; j < height; j += (2*HALF_WIDTH)) {
  201.         glVertex2i(0, j);
  202.         glVertex2i(width, j);
  203.     }
  204.     glColor3f(1.0, 1.0, 0.0);
  205.     for (i = 0; i <= contour_cnt; i++) {
  206.       point_cnt = contours[i].point_cnt;
  207.       glBegin(GL_LINES);
  208.       switch (point_cnt) {
  209.       case 0:
  210.         break;
  211.       case 1:
  212.         glVertex2iv(contours[i].p[0]);
  213.         glVertex2iv(contours[i].p[0]);
  214.         break;
  215.       case 2:
  216.         glVertex2iv(contours[i].p[0]);
  217.         glVertex2iv(contours[i].p[1]);
  218.         break;
  219.       default:
  220.         --point_cnt;
  221.         for (j = 0; j < point_cnt; j++) {
  222.           glVertex2iv(contours[i].p[j]);
  223.           glVertex2iv(contours[i].p[j + 1]);
  224.         }
  225.         if (contours[i].p[j + 1][0] == -1) {
  226.           glVertex2iv(contours[i].p[0]);
  227.           glVertex2iv(contours[i].p[j]);
  228.         }
  229.         break;
  230.       }
  231.       glEnd();
  232.     }
  233.     glFlush();
  234.     break;
  235.   case TESSELATED:
  236.     /* draw lines */
  237.     tesse();
  238.     break;
  239.   }
  240.   glColor3f(1.0, 1.0, 0.0);
  241. }
  242. void 
  243. clear(void)
  244. {
  245.   contour_cnt = 0;
  246.   contours[0].point_cnt = 0;
  247.   glutMouseFunc(mouse_clicked);
  248.   mode = DEFINE;
  249.   display();
  250. }
  251. void 
  252. quit(void)
  253. {
  254.   exit(0);
  255. }
  256. void 
  257. menu_selected(int entry)
  258. {
  259.   switch (entry) {
  260.   case CLEAR:
  261.     clear();
  262.     break;
  263.   case TESSELATE:
  264.     tesse();
  265.     break;
  266.   case QUIT:
  267.     quit();
  268.     break;
  269.   }
  270. }
  271. /* ARGSUSED1 */
  272. void 
  273. key_pressed(unsigned char key, int x, int y)
  274. {
  275.   switch (key) {
  276.   case 't':
  277.   case 'T':
  278.     tesse();
  279.     glFlush();
  280.     break;
  281.   case 'q':
  282.   case 'Q':
  283.     quit();
  284.     break;
  285.   case 'c':
  286.   case 'C':
  287.     clear();
  288.     break;
  289.   }
  290. }
  291. void 
  292. myinit(void)
  293. {
  294.   /* clear background to gray */
  295.   glClearColor(0.4, 0.4, 0.4, 0.0);
  296.   glShadeModel(GL_FLAT);
  297.   menu = glutCreateMenu(menu_selected);
  298.   glutAddMenuEntry("clear", CLEAR);
  299.   glutAddMenuEntry("tesselate", TESSELATE);
  300.   glutAddMenuEntry("quit", QUIT);
  301.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  302.   glutMouseFunc(mouse_clicked);
  303.   glutKeyboardFunc(key_pressed);
  304.   contour_cnt = 0;
  305.   glPolygonMode(GL_FRONT, GL_FILL);
  306.   mode = DEFINE;
  307. }
  308. static void 
  309. reshape(GLsizei w, GLsizei h)
  310. {
  311.   glViewport(0, 0, w, h);
  312.   glMatrixMode(GL_PROJECTION);
  313.   glLoadIdentity();
  314.   glOrtho(0.0, (GLdouble) w, 0.0, (GLdouble) h, -1.0, 1.0);
  315.   glMatrixMode(GL_MODELVIEW);
  316.   glLoadIdentity();
  317.   set_screen_wh(w, h);
  318. }
  319. static void 
  320. usage(void)
  321. {
  322.   printf("Use left mouse button to place vertices.n");
  323.   printf("Press middle mouse button when done.n");
  324.   printf("Select tesselate from the pop-up menu.n");
  325. }
  326. /*  Main Loop
  327.  *  Open window with initial window size, title bar, 
  328.  *  RGBA display mode, and handle input events.
  329.  */
  330. int 
  331. main(int argc, char **argv)
  332. {
  333.   usage();
  334.   glutInitWindowSize(400, 400);
  335.   glutInit(&argc, argv);
  336.   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  337.   glutCreateWindow(argv[0]);
  338.   myinit();
  339.   glutDisplayFunc(display);
  340.   glutReshapeFunc(reshape);
  341.   glutMainLoop();
  342.   return 0;             /* ANSI C requires main to return int. */
  343. }