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

GIS编程

开发平台:

Visual C++

  1. /* Copyright (c) Mark J. Kilgard, 1994.  */
  2. /* This program is freely distributable without licensing fees 
  3.    and is provided without guarantee or warrantee expressed or 
  4.    implied. This program is -not- in the public domain. */
  5. /* zoomdino demonstrates GLUT 3.0's new overlay support.  Both
  6.    rubber-banding the display of a help message use the overlays. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <math.h>       /* for cos(), sin(), and sqrt() */
  11. #include <GL/glut.h>
  12. typedef enum {
  13.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  14.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  15. } displayLists;
  16. GLfloat angle = -150;   /* in degrees */
  17. int moving, begin;
  18. int W = 300, H = 300;
  19. GLdouble bodyWidth = 3.0;
  20. int newModel = 1;
  21. /* *INDENT-OFF* */
  22. GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  23.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  24.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  25.   {1, 2} };
  26. GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  27.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  28.   {13, 9}, {11, 11}, {9, 11} };
  29. GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  30.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  31. GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  32.   {9.6, 15.25}, {9, 15.25} };
  33. GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0};
  34. GLfloat lightZeroColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  35. GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0};
  36. GLfloat lightOneColor[] = {0.6, 0.3, 0.2, 1.0}; /* red-tinted */
  37. GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  38. int overlaySupport, red, white, transparent, rubberbanding;
  39. int anchorx, anchory, stretchx, stretchy, pstretchx, pstretchy;
  40. float vx, vy, vx2, vy2, vw, vh;
  41. float wx, wy, wx2, wy2, ww, wh;
  42. int fancy, wasFancy, help, clearHelp;
  43. /* *INDENT-ON* */
  44. void
  45. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  46.   GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
  47. {
  48.   static GLUtriangulatorObj *tobj = NULL;
  49.   GLdouble vertex[3], dx, dy, len;
  50.   int i;
  51.   int count = dataSize / (int) (2 * sizeof(GLfloat));
  52.   if (tobj == NULL) {
  53.     tobj = gluNewTess();  /* create and initialize a GLU
  54.                              polygontesselation object */
  55.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  56.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky 
  57.                                                       */
  58.     gluTessCallback(tobj, GLU_END, glEnd);
  59.   }
  60.   glNewList(side, GL_COMPILE);
  61.   glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
  62.                                tessellation */
  63.   gluBeginPolygon(tobj);
  64.   for (i = 0; i < count; i++) {
  65.     vertex[0] = data[i][0];
  66.     vertex[1] = data[i][1];
  67.     vertex[2] = 0;
  68.     gluTessVertex(tobj, vertex, data[i]);
  69.   }
  70.   gluEndPolygon(tobj);
  71.   glEndList();
  72.   glNewList(edge, GL_COMPILE);
  73.   glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
  74.                              from being "smoothed" */
  75.   glBegin(GL_QUAD_STRIP);
  76.   for (i = 0; i <= count; i++) {
  77.     /* mod function handles closing the edge */
  78.     glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  79.     glVertex3f(data[i % count][0], data[i % count][1], thickness);
  80.     /* Calculate a unit normal by dividing by Euclidean
  81.        distance. We could be lazy and use
  82.        glEnable(GL_NORMALIZE) so we could pass in arbitrary
  83.        normals for a very slight performance hit. */
  84.     dx = data[(i + 1) % count][1] - data[i % count][1];
  85.     dy = data[i % count][0] - data[(i + 1) % count][0];
  86.     len = sqrt(dx * dx + dy * dy);
  87.     glNormal3f(dx / len, dy / len, 0.0);
  88.   }
  89.   glEnd();
  90.   glEndList();
  91.   glNewList(whole, GL_COMPILE);
  92.   glFrontFace(GL_CW);
  93.   glCallList(edge);
  94.   glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  95.   glCallList(side);
  96.   glPushMatrix();
  97.   glTranslatef(0.0, 0.0, thickness);
  98.   glFrontFace(GL_CCW);
  99.   glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side */
  100.   glCallList(side);
  101.   glPopMatrix();
  102.   glEndList();
  103. }
  104. void
  105. makeDinosaur(void)
  106. {
  107.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  108.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  109.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  110.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  111.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  112.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  113.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  114.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  115.   glNewList(DINOSAUR, GL_COMPILE);
  116.   glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  117.   glCallList(BODY_WHOLE);
  118.   glPushMatrix();
  119.   glTranslatef(0.0, 0.0, bodyWidth);
  120.   glCallList(ARM_WHOLE);
  121.   glCallList(LEG_WHOLE);
  122.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  123.   glCallList(ARM_WHOLE);
  124.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  125.   glCallList(LEG_WHOLE);
  126.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  127.   glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  128.   glCallList(EYE_WHOLE);
  129.   glPopMatrix();
  130.   glEndList();
  131. }
  132. void
  133. recalcModelView(void)
  134. {
  135.   glPopMatrix();
  136.   glPushMatrix();
  137.   glRotatef(angle, 0.0, 1.0, 0.0);
  138.   glTranslatef(-8, -8, -bodyWidth / 2);
  139.   newModel = 0;
  140. }
  141. void
  142. redraw(void)
  143. {
  144.   if (newModel)
  145.     recalcModelView();
  146.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  147.   glCallList(DINOSAUR);
  148.   glutSwapBuffers();
  149. }
  150. void
  151. output(int x, int y, char *string)
  152. {
  153.   int len, i;
  154.   glRasterPos2f(x, y);
  155.   len = (int) strlen(string);
  156.   for (i = 0; i < len; i++) {
  157.     glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, string[i]);
  158.   }
  159. }
  160. char *helpMsg[] =
  161. {
  162.   "Welcome to zoomdino!",
  163.   "   Left mouse button rotates",
  164.   "     the dinosaur.",
  165.   "   Middle mouse button zooms",
  166.   "     via overlay rubber-banding.",
  167.   "   Right mouse button shows",
  168.   "     pop-up menu.",
  169.   "   To reset view, use "Reset",
  170.   "     Projection".",
  171.   "(This message is in the overlays.)",
  172.   NULL
  173. };
  174. void
  175. redrawOverlay(void)
  176. {
  177.   if (help) {
  178.     int i;
  179.     glClear(GL_COLOR_BUFFER_BIT);
  180.     glIndexi(white);
  181.     for (i = 0; helpMsg[i]; i++) {
  182.       output(15, 24 + i * 18, helpMsg[i]);
  183.     }
  184.     return;
  185.   }
  186.   if (glutLayerGet(GLUT_OVERLAY_DAMAGED) || clearHelp) {
  187.     /* Opps, damage means we need a full clear. */
  188.     glClear(GL_COLOR_BUFFER_BIT);
  189.     clearHelp = 0;
  190.     wasFancy = 0;
  191.   } else {
  192.     /* Goody!  No damage.  Just erase last rubber-band. */
  193.     if (fancy || wasFancy) {
  194.       glLineWidth(3.0);
  195.     }
  196.     glIndexi(transparent);
  197.     glBegin(GL_LINE_LOOP);
  198.     glVertex2i(anchorx, anchory);
  199.     glVertex2i(anchorx, pstretchy);
  200.     glVertex2i(pstretchx, pstretchy);
  201.     glVertex2i(pstretchx, anchory);
  202.     glEnd();
  203.   }
  204.   if (wasFancy) {
  205.     glLineWidth(1.0);
  206.     wasFancy = 0;
  207.   }
  208.   if (fancy)
  209.     glLineWidth(3.0);
  210.   glIndexi(red);
  211.   glBegin(GL_LINE_LOOP);
  212.   glVertex2i(anchorx, anchory);
  213.   glVertex2i(anchorx, stretchy);
  214.   glVertex2i(stretchx, stretchy);
  215.   glVertex2i(stretchx, anchory);
  216.   glEnd();
  217.   if (fancy) {
  218.     glLineWidth(1.0);
  219.     glIndexi(white);
  220.     glBegin(GL_LINE_LOOP);
  221.     glVertex2i(anchorx, anchory);
  222.     glVertex2i(anchorx, stretchy);
  223.     glVertex2i(stretchx, stretchy);
  224.     glVertex2i(stretchx, anchory);
  225.     glEnd();
  226.   }
  227.   glFlush();
  228.   /* Remember last place rubber-banded so the rubber-band can
  229.      be erased next redisplay. */
  230.   pstretchx = stretchx;
  231.   pstretchy = stretchy;
  232. }
  233. void
  234. defaultProjection(void)
  235. {
  236.   glMatrixMode(GL_PROJECTION);
  237.   glLoadIdentity();
  238.   vx = -1.0;
  239.   vw = 2.0;
  240.   vy = -1.0;
  241.   vh = 2.0;
  242.   glFrustum(vx, vx + vw, vy, vy + vh, 1.0, 40);
  243.   glMatrixMode(GL_MODELVIEW);
  244. }
  245. void
  246. mouse(int button, int state, int x, int y)
  247. {
  248.   if (button == GLUT_LEFT_BUTTON) {
  249.     if (state == GLUT_DOWN) {
  250.       glutSetCursor(GLUT_CURSOR_LEFT_RIGHT);
  251.       moving = 1;
  252.       begin = x;
  253.     } else if (state == GLUT_UP) {
  254.       glutSetCursor(GLUT_CURSOR_INHERIT);
  255.       moving = 0;
  256.     }
  257.   }
  258.   if (overlaySupport && button == GLUT_MIDDLE_BUTTON) {
  259.     if (state == GLUT_DOWN) {
  260.       help = 0;
  261.       clearHelp = 1;
  262.       rubberbanding = 1;
  263.       anchorx = x;
  264.       anchory = y;
  265.       stretchx = x;
  266.       stretchy = y;
  267.       glutShowOverlay();
  268.     } else if (state == GLUT_UP) {
  269.       rubberbanding = 0;
  270.       glutHideOverlay();
  271.       glutUseLayer(GLUT_NORMAL);
  272.       glMatrixMode(GL_PROJECTION);
  273.       glLoadIdentity();
  274. #undef max
  275. #undef min
  276. #define max(a,b)  ((a) > (b) ? (a) : (b))
  277. #define min(a,b)  ((a) < (b) ? (a) : (b))
  278.       wx = min(anchorx, stretchx);
  279.       wy = min(H - anchory, H - stretchy);
  280.       wx2 = max(anchorx, stretchx);
  281.       wy2 = max(H - anchory, H - stretchy);
  282.       ww = wx2 - wx;
  283.       wh = wy2 - wy;
  284.       if (ww == 0 || wh == 0) {
  285.         glutUseLayer(GLUT_NORMAL);
  286.         defaultProjection();
  287.       } else {
  288.         vx2 = wx2 / W * vw + vx;
  289.         vx = wx / W * vw + vx;
  290.         vy2 = wy2 / H * vh + vy;
  291.         vy = wy / H * vh + vy;
  292.         vw = vx2 - vx;
  293.         vh = vy2 - vy;
  294.         glFrustum(vx, vx + vw, vy, vy + vh, 1.0, 40);
  295.       }
  296.       glutPostRedisplay();
  297.       glMatrixMode(GL_MODELVIEW);
  298.     }
  299.   }
  300. }
  301. void
  302. motion(int x, int y)
  303. {
  304.   if (moving) {
  305.     angle = angle + (x - begin);
  306.     begin = x;
  307.     newModel = 1;
  308.     glutPostRedisplay();
  309.   }
  310.   if (rubberbanding) {
  311.     stretchx = x;
  312.     stretchy = y;
  313.     glutPostOverlayRedisplay();
  314.   }
  315. }
  316. void
  317. reshape(int w, int h)
  318. {
  319.   if (overlaySupport) {
  320.     glutUseLayer(GLUT_OVERLAY);
  321.     glViewport(0, 0, w, h);
  322.     glMatrixMode(GL_PROJECTION);
  323.     glLoadIdentity();
  324.     gluOrtho2D(0, w, 0, h);
  325.     glScalef(1, -1, 1);
  326.     glTranslatef(0, -h, 0);
  327.     glMatrixMode(GL_MODELVIEW);
  328.     glutUseLayer(GLUT_NORMAL);
  329.   }
  330.   glViewport(0, 0, w, h);
  331.   W = w;
  332.   H = h;
  333. }
  334. GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
  335. void
  336. controlLights(int value)
  337. {
  338.   glutUseLayer(GLUT_NORMAL);
  339.   switch (value) {
  340.   case 1:
  341.     lightZeroSwitch = !lightZeroSwitch;
  342.     if (lightZeroSwitch) {
  343.       glEnable(GL_LIGHT0);
  344.     } else {
  345.       glDisable(GL_LIGHT0);
  346.     }
  347.     break;
  348.   case 2:
  349.     lightOneSwitch = !lightOneSwitch;
  350.     if (lightOneSwitch) {
  351.       glEnable(GL_LIGHT1);
  352.     } else {
  353.       glDisable(GL_LIGHT1);
  354.     }
  355.     break;
  356.   case 3:
  357.     defaultProjection();
  358.     break;
  359.   case 4:
  360.     fancy = 1;
  361.     break;
  362.   case 5:
  363.     fancy = 0;
  364.     wasFancy = 1;
  365.     break;
  366.   case 6:
  367.     if (!rubberbanding)
  368.       help = 1;
  369.     glutShowOverlay();
  370.     glutPostOverlayRedisplay();
  371.     break;
  372.   }
  373.   glutPostRedisplay();
  374. }
  375. int
  376. main(int argc, char **argv)
  377. {
  378.   glutInit(&argc, argv);
  379.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  380.   glutCreateWindow("zoomdino");
  381.   glutDisplayFunc(redraw);
  382.   glutMouseFunc(mouse);
  383.   glutMotionFunc(motion);
  384.   glutCreateMenu(controlLights);
  385.   glutAddMenuEntry("Toggle right light", 1);
  386.   glutAddMenuEntry("Toggle left light", 2);
  387.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  388.   makeDinosaur();
  389.   glEnable(GL_CULL_FACE);
  390.   glEnable(GL_DEPTH_TEST);
  391.   glEnable(GL_LIGHTING);
  392.   defaultProjection();
  393.   gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
  394.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  395.     0.0, 1.0, 0.);      /* up is in postivie Y direction */
  396.   glPushMatrix();       /* dummy push so we can pop on model
  397.                            recalc */
  398.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  399.   glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  400.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  401.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  402.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  403.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  404.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  405.   glEnable(GL_LIGHT0);
  406.   glEnable(GL_LIGHT1);
  407.   glutInitDisplayMode(GLUT_SINGLE | GLUT_INDEX);
  408.   overlaySupport = glutLayerGet(GLUT_OVERLAY_POSSIBLE);
  409.   if (overlaySupport) {
  410.     glutEstablishOverlay();
  411.     glutHideOverlay();
  412.     transparent = glutLayerGet(GLUT_TRANSPARENT_INDEX);
  413.     glClearIndex(transparent);
  414.     red = (transparent + 1) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);
  415.     white = (transparent + 2) % glutGet(GLUT_WINDOW_COLORMAP_SIZE);
  416.     glutSetColor(red, 1.0, 0.0, 0.0);  /* Red. */
  417.     glutSetColor(white, 1.0, 1.0, 1.0);  /* White. */
  418.     glutOverlayDisplayFunc(redrawOverlay);
  419.     glutReshapeFunc(reshape);
  420.     glutSetWindowTitle("zoomdino with rubber-banding");
  421.     glutAddMenuEntry("------------------", 0);
  422.     glutAddMenuEntry("Reset projection", 3);
  423.     glutAddMenuEntry("------------------", 0);
  424.     glutAddMenuEntry("Fancy rubber-banding", 4);
  425.     glutAddMenuEntry("Simple rubber-banding", 5);
  426.     glutAddMenuEntry("------------------", 0);
  427.     glutAddMenuEntry("Show help", 6);
  428.   } else {
  429.     printf("Sorry, no whizzy zoomdino overlay usage!n");
  430.   }
  431.   glutMainLoop();
  432.   return 0;             /* ANSI C requires main to return int. */
  433. }