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

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. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <math.h>       /* for cos(), sin(), and sqrt() */
  9. #include <GL/glut.h>
  10. typedef enum {
  11.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  12.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  13. } displayLists;
  14. GLfloat angle = -150;   /* in degrees */
  15. GLfloat xloc = 0, yloc = 0, zloc = 0;
  16. int moving, begin;
  17. int W = 300, H = 300;
  18. GLdouble bodyWidth = 3.0;
  19. int newModel = 1;
  20. /* *INDENT-OFF* */
  21. GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  22.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  23.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  24.   {1, 2} };
  25. GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  26.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  27.   {13, 9}, {11, 11}, {9, 11} };
  28. GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  29.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  30. GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  31.   {9.6, 15.25}, {9, 15.25} };
  32. GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0};
  33. GLfloat lightZeroColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  34. GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0};
  35. GLfloat lightOneColor[] = {0.6, 0.3, 0.2, 1.0}; /* red-tinted */
  36. GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  37. /* *INDENT-ON* */
  38. void
  39. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  40.   GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
  41. {
  42.   static GLUtriangulatorObj *tobj = NULL;
  43.   GLdouble vertex[3], dx, dy, len;
  44.   int i;
  45.   int count = dataSize / (int) (2 * sizeof(GLfloat));
  46.   if (tobj == NULL) {
  47.     tobj = gluNewTess();  /* create and initialize a GLU
  48.                              polygon tesselation object */
  49.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  50.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky */
  51.     gluTessCallback(tobj, GLU_END, glEnd);
  52.   }
  53.   glNewList(side, GL_COMPILE);
  54.   glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
  55.                                tessellation */
  56.   gluBeginPolygon(tobj);
  57.   for (i = 0; i < count; i++) {
  58.     vertex[0] = data[i][0];
  59.     vertex[1] = data[i][1];
  60.     vertex[2] = 0;
  61.     gluTessVertex(tobj, vertex, data[i]);
  62.   }
  63.   gluEndPolygon(tobj);
  64.   glEndList();
  65.   glNewList(edge, GL_COMPILE);
  66.   glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
  67.                              from being "smoothed" */
  68.   glBegin(GL_QUAD_STRIP);
  69.   for (i = 0; i <= count; i++) {
  70.     /* mod function handles closing the edge */
  71.     glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  72.     glVertex3f(data[i % count][0], data[i % count][1], thickness);
  73.     /* Calculate a unit normal by dividing by Euclidean
  74.        distance. We * could be lazy and use
  75.        glEnable(GL_NORMALIZE) so we could pass in * arbitrary
  76.        normals for a very slight performance hit. */
  77.     dx = data[(i + 1) % count][1] - data[i % count][1];
  78.     dy = data[i % count][0] - data[(i + 1) % count][0];
  79.     len = sqrt(dx * dx + dy * dy);
  80.     glNormal3f(dx / len, dy / len, 0.0);
  81.   }
  82.   glEnd();
  83.   glEndList();
  84.   glNewList(whole, GL_COMPILE);
  85.   glFrontFace(GL_CW);
  86.   glCallList(edge);
  87.   glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  88.   glCallList(side);
  89.   glPushMatrix();
  90.   glTranslatef(0.0, 0.0, thickness);
  91.   glFrontFace(GL_CCW);
  92.   glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side */
  93.   glCallList(side);
  94.   glPopMatrix();
  95.   glEndList();
  96. }
  97. void
  98. makeDinosaur(void)
  99. {
  100.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  101.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  102.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  103.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  104.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  105.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  106.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  107.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  108.   glNewList(DINOSAUR, GL_COMPILE);
  109.   glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  110.   glCallList(BODY_WHOLE);
  111.   glPushMatrix();
  112.   glTranslatef(0.0, 0.0, bodyWidth);
  113.   glCallList(ARM_WHOLE);
  114.   glCallList(LEG_WHOLE);
  115.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  116.   glCallList(ARM_WHOLE);
  117.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  118.   glCallList(LEG_WHOLE);
  119.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  120.   glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  121.   glCallList(EYE_WHOLE);
  122.   glPopMatrix();
  123.   glEndList();
  124. }
  125. void
  126. recalcModelView(void)
  127. {
  128.   glPopMatrix();
  129.   glPushMatrix();
  130.   glTranslatef(xloc, yloc, zloc);
  131.   glRotatef(angle, 0.0, 1.0, 0.0);
  132.   glTranslatef(-8, -8, -bodyWidth / 2);
  133.   newModel = 0;
  134. }
  135. void
  136. redraw(void)
  137. {
  138.   if (newModel)
  139.     recalcModelView();
  140.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  141.   glCallList(DINOSAUR);
  142.   glutSwapBuffers();
  143. }
  144. /* ARGSUSED3 */
  145. void
  146. mouse(int button, int state, int x, int y)
  147. {
  148.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  149.     moving = 1;
  150.     begin = x;
  151.   }
  152.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  153.     moving = 0;
  154.   }
  155. }
  156. /* ARGSUSED1 */
  157. void
  158. motion(int x, int y)
  159. {
  160.   if (moving) {
  161.     angle = angle + (x - begin);
  162.     begin = x;
  163.     newModel = 1;
  164.     glutPostRedisplay();
  165.   }
  166. }
  167. void
  168. tablet(int x, int y)
  169. {
  170.   xloc = ((GLfloat) x) / 500 - 4;
  171.   yloc = ((GLfloat) y) / 1000 - 2;
  172.   newModel = 1;
  173.   glutPostRedisplay();
  174. }
  175. int xt = 1, yt = 1, zt = 1, xr = 1;
  176. void
  177. translate(int x, int y, int z)
  178. {
  179.   GLfloat newz;
  180.   if (xt)
  181.     xloc += ((GLfloat) x) / 100;
  182.   if (yt)
  183.     yloc += ((GLfloat) y) / 100;
  184.   if (zt) {
  185.     newz = zloc - ((GLfloat) z) / 100;
  186.     if (newz > -60.0 && newz < 13.0)
  187.       zloc = newz;
  188.   }
  189.   newModel = 1;
  190.   glutPostRedisplay();
  191. }
  192. /* ARGSUSED1 */
  193. void
  194. rotate(int x, int y, int z)
  195. {
  196.   if (xr) {
  197.     angle += x / 2.0;
  198.     newModel = 1;
  199.     glutPostRedisplay();
  200.   }
  201. }
  202. void
  203. button(int button, int state)
  204. {
  205.   if (state == GLUT_DOWN) {
  206.     switch (button) {
  207.     case 1:
  208.       xt = yt = zt = xr = 1;
  209.       break;
  210.     case 5:
  211.       xt = 1;
  212.       yt = zt = xr = 0;
  213.       break;
  214.     case 6:
  215.       yt = 1;
  216.       xt = zt = xr = 0;
  217.       break;
  218.     case 7:
  219.       zt = 1;
  220.       xt = yt = xr = 0;
  221.       break;
  222.     case 8:
  223.       xr = 1;
  224.       xt = yt = zt = 0;
  225.       break;
  226.     case 9:
  227.       xloc = yloc = zloc = 0;
  228.       newModel = 1;
  229.       glutPostRedisplay();
  230.       break;
  231.     }
  232.   }
  233. }
  234. void
  235. dials(int dial, int value)
  236. {
  237.   if (dial == 0) {
  238.     angle = value / 10.0;
  239.     newModel = 1;
  240.     glutPostRedisplay();
  241.   }
  242. }
  243. GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
  244. void
  245. controlLights(int value)
  246. {
  247.   switch (value) {
  248.   case 1:
  249.     lightZeroSwitch = !lightZeroSwitch;
  250.     if (lightZeroSwitch) {
  251.       glEnable(GL_LIGHT0);
  252.     } else {
  253.       glDisable(GL_LIGHT0);
  254.     }
  255.     break;
  256.   case 2:
  257.     lightOneSwitch = !lightOneSwitch;
  258.     if (lightOneSwitch) {
  259.       glEnable(GL_LIGHT1);
  260.     } else {
  261.       glDisable(GL_LIGHT1);
  262.     }
  263.     break;
  264.   }
  265.   glutPostRedisplay();
  266. }
  267. int
  268. main(int argc, char **argv)
  269. {
  270.   glutInit(&argc, argv);
  271.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  272.   glutCreateWindow("dinoball (Spaceball demo)");
  273.   glutDisplayFunc(redraw);
  274.   glutMouseFunc(mouse);
  275.   glutMotionFunc(motion);
  276.   glutTabletMotionFunc(tablet);
  277.   glutSpaceballMotionFunc(translate);
  278.   glutSpaceballRotateFunc(rotate);
  279.   glutSpaceballButtonFunc(button);
  280.   glutDialsFunc(dials);
  281.   glutCreateMenu(controlLights);
  282.   glutAddMenuEntry("Toggle right light", 1);
  283.   glutAddMenuEntry("Toggle left light", 2);
  284.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  285.   makeDinosaur();
  286.   glEnable(GL_CULL_FACE);
  287.   glEnable(GL_DEPTH_TEST);
  288.   glEnable(GL_LIGHTING);
  289.   glMatrixMode(GL_PROJECTION);
  290.   gluPerspective( /* field of view in degree */ 40.0,
  291.   /* aspect ratio */ 1.0,
  292.     /* Z near */ 1.0, /* Z far */ 100.0);
  293.   glMatrixMode(GL_MODELVIEW);
  294.   gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
  295.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  296.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  297.   glPushMatrix();       /* dummy push so we can pop on model
  298.                            recalc */
  299.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  300.   glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  301.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  302.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  303.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  304.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  305.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  306.   glEnable(GL_LIGHT0);
  307.   glEnable(GL_LIGHT1);
  308.   glutMainLoop();
  309.   return 0;             /* ANSI C requires main to return int. */
  310. }