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

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. /* New GLUT 3.0 glutGetModifiers() functionality used to make Shift-Left
  6.    mouse scale the dinosaur's size. */
  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. #include "trackball.h"
  13. typedef enum {
  14.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  15.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  16. } displayLists;
  17. int spinning = 0, moving = 0;
  18. int beginx, beginy;
  19. int W = 300, H = 300;
  20. float curquat[4];
  21. float lastquat[4];
  22. GLdouble bodyWidth = 3.0;
  23. int newModel = 1;
  24. int scaling;
  25. float scalefactor = 1.0;
  26. /* *INDENT-OFF* */
  27. GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  28.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  29.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  30.   {1, 2} };
  31. GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  32.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  33.   {13, 9}, {11, 11}, {9, 11} };
  34. GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  35.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  36. GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  37.   {9.6, 15.25}, {9, 15.25} };
  38. GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0};
  39. GLfloat lightZeroColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  40. GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0};
  41. GLfloat lightOneColor[] = {0.6, 0.3, 0.2, 1.0}; /* red-tinted */
  42. GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  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 = (int) (dataSize / (2 * sizeof(GLfloat)));
  52.   if (tobj == NULL) {
  53.     tobj = gluNewTess();  /* create and initialize a GLU
  54.                              polygon tesselation 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.                                */
  101.   glCallList(side);
  102.   glPopMatrix();
  103.   glEndList();
  104. }
  105. void
  106. makeDinosaur(void)
  107. {
  108.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  109.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  110.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  111.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  112.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  113.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  114.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  115.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  116.   glNewList(DINOSAUR, GL_COMPILE);
  117.   glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  118.   glCallList(BODY_WHOLE);
  119.   glPushMatrix();
  120.   glTranslatef(0.0, 0.0, bodyWidth);
  121.   glCallList(ARM_WHOLE);
  122.   glCallList(LEG_WHOLE);
  123.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  124.   glCallList(ARM_WHOLE);
  125.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  126.   glCallList(LEG_WHOLE);
  127.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  128.   glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  129.   glCallList(EYE_WHOLE);
  130.   glPopMatrix();
  131.   glEndList();
  132. }
  133. void
  134. recalcModelView(void)
  135. {
  136.   GLfloat m[4][4];
  137.   glPopMatrix();
  138.   glPushMatrix();
  139.   build_rotmatrix(m, curquat);
  140.   glMultMatrixf(&m[0][0]);
  141.   if (scalefactor == 1.0) {
  142.     glDisable(GL_NORMALIZE);
  143.   } else {
  144.     glEnable(GL_NORMALIZE);
  145.   }
  146.   glScalef(scalefactor, scalefactor, scalefactor);
  147.   glTranslatef(-8, -8, -bodyWidth / 2);
  148.   newModel = 0;
  149. }
  150. void
  151. showMessage(GLfloat x, GLfloat y, GLfloat z, char *message)
  152. {
  153.   glPushMatrix();
  154.   glDisable(GL_LIGHTING);
  155.   glTranslatef(x, y, z);
  156.   glScalef(.02, .02, .02);
  157.   while (*message) {
  158.     glutStrokeCharacter(GLUT_STROKE_ROMAN, *message);
  159.     message++;
  160.   }
  161.   glEnable(GL_LIGHTING);
  162.   glPopMatrix();
  163. }
  164. void
  165. redraw(void)
  166. {
  167.   if (newModel)
  168.     recalcModelView();
  169.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  170.   glCallList(DINOSAUR);
  171.   showMessage(2, 7.1, 4.1, "Spin me.");
  172.   glutSwapBuffers();
  173. }
  174. void
  175. myReshape(int w, int h)
  176. {
  177.   glViewport(0, 0, w, h);
  178.   W = w;
  179.   H = h;
  180. }
  181. void
  182. mouse(int button, int state, int x, int y)
  183. {
  184.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  185.     spinning = 0;
  186.     glutIdleFunc(NULL);
  187.     moving = 1;
  188.     beginx = x;
  189.     beginy = y;
  190.     if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
  191.       scaling = 1;
  192.     } else {
  193.       scaling = 0;
  194.     }
  195.   }
  196.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  197.     moving = 0;
  198.   }
  199. }
  200. void
  201. animate(void)
  202. {
  203.   add_quats(lastquat, curquat, curquat);
  204.   newModel = 1;
  205.   glutPostRedisplay();
  206. }
  207. void
  208. motion(int x, int y)
  209. {
  210.   if (scaling) {
  211.     scalefactor = scalefactor * (1.0 + (((float) (beginy - y)) / H));
  212.     beginx = x;
  213.     beginy = y;
  214.     newModel = 1;
  215.     glutPostRedisplay();
  216.     return;
  217.   }
  218.   if (moving) {
  219.     trackball(lastquat,
  220.       (2.0 * beginx - W) / W,
  221.       (H - 2.0 * beginy) / H,
  222.       (2.0 * x - W) / W,
  223.       (H - 2.0 * y) / H
  224.       );
  225.     beginx = x;
  226.     beginy = y;
  227.     spinning = 1;
  228.     glutIdleFunc(animate);
  229.   }
  230. }
  231. GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
  232. void
  233. controlLights(int value)
  234. {
  235.   switch (value) {
  236.   case 1:
  237.     lightZeroSwitch = !lightZeroSwitch;
  238.     if (lightZeroSwitch) {
  239.       glEnable(GL_LIGHT0);
  240.     } else {
  241.       glDisable(GL_LIGHT0);
  242.     }
  243.     break;
  244.   case 2:
  245.     lightOneSwitch = !lightOneSwitch;
  246.     if (lightOneSwitch) {
  247.       glEnable(GL_LIGHT1);
  248.     } else {
  249.       glDisable(GL_LIGHT1);
  250.     }
  251.     break;
  252. #ifdef GL_MULTISAMPLE_SGIS
  253.   case 3:
  254.     if (glIsEnabled(GL_MULTISAMPLE_SGIS)) {
  255.       glDisable(GL_MULTISAMPLE_SGIS);
  256.     } else {
  257.       glEnable(GL_MULTISAMPLE_SGIS);
  258.     }
  259.     break;
  260. #endif
  261.   case 4:
  262.     glutFullScreen();
  263.     break;
  264.   case 5:
  265.     exit(0);
  266.     break;
  267.   }
  268.   glutPostRedisplay();
  269. }
  270. void
  271. vis(int visible)
  272. {
  273.   if (visible == GLUT_VISIBLE) {
  274.     if (spinning)
  275.       glutIdleFunc(animate);
  276.   } else {
  277.     if (spinning)
  278.       glutIdleFunc(NULL);
  279.   }
  280. }
  281. int
  282. main(int argc, char **argv)
  283. {
  284.   glutInit(&argc, argv);
  285.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  286.   trackball(curquat, 0.0, 0.0, 0.0, 0.0);
  287.   glutCreateWindow("dinospin");
  288.   glutDisplayFunc(redraw);
  289.   glutReshapeFunc(myReshape);
  290.   glutVisibilityFunc(vis);
  291.   glutMouseFunc(mouse);
  292.   glutMotionFunc(motion);
  293.   glutCreateMenu(controlLights);
  294.   glutAddMenuEntry("Toggle right light", 1);
  295.   glutAddMenuEntry("Toggle left light", 2);
  296.   if (glutGet(GLUT_WINDOW_NUM_SAMPLES) > 0) {
  297.     glutAddMenuEntry("Toggle multisampling", 3);
  298.     glutSetWindowTitle("dinospin (multisample capable)");
  299.   }
  300.   glutAddMenuEntry("Full screen", 4);
  301.   glutAddMenuEntry("Quit", 5);
  302.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  303.   makeDinosaur();
  304.   glEnable(GL_CULL_FACE);
  305.   glEnable(GL_DEPTH_TEST);
  306.   glEnable(GL_LIGHTING);
  307.   glMatrixMode(GL_PROJECTION);
  308.   gluPerspective( /* field of view in degree */ 40.0,
  309.   /* aspect ratio */ 1.0,
  310.     /* Z near */ 1.0, /* Z far */ 40.0);
  311.   glMatrixMode(GL_MODELVIEW);
  312.   gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
  313.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  314.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  315.   glPushMatrix();       /* dummy push so we can pop on model
  316.                            recalc */
  317.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  318.   glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  319.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  320.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  321.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  322.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  323.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  324.   glEnable(GL_LIGHT0);
  325.   glEnable(GL_LIGHT1);
  326.   glLineWidth(2.0);
  327.   glutMainLoop();
  328.   return 0;             /* ANSI C requires main to return int. */
  329. }