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

GIS编程

开发平台:

Visual C++

  1. /* csg.c - by Tom McReynolds, SGI */
  2. /* Doing constructive solid geometry (CSG) with stencil. */
  3. #include <GL/glut.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. enum {
  7.   CSG_A, CSG_B, CSG_A_OR_B, CSG_A_AND_B, CSG_A_SUB_B, CSG_B_SUB_A
  8. };
  9. /* just draw single object */
  10. void
  11. one(void (*a) (void))
  12. {
  13.   glEnable(GL_DEPTH_TEST);
  14.   a();
  15.   glDisable(GL_DEPTH_TEST);
  16. }
  17. /* "or" is easy; simply draw both objects with depth buffering on */
  18. void
  19. or(void (*a) (void), void (*b) (void))
  20. {
  21.   glEnable(GL_DEPTH_TEST);
  22.   a();
  23.   b();
  24.   glDisable(GL_DEPTH_TEST);
  25. }
  26. /* Set stencil buffer to show the part of a (front or back face) that's
  27.    inside b's volume. Requirements: GL_CULL_FACE enabled, depth func GL_LESS
  28.    Side effects: depth test, stencil func, stencil op */
  29. void
  30. firstInsideSecond(void (*a) (void), void (*b) (void), GLenum face, GLenum test)
  31. {
  32.   glEnable(GL_DEPTH_TEST);
  33.   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  34.   glCullFace(face);     /* controls which face of a to use */
  35.   a();                  /* draw a face of a into depth buffer */
  36.   /* use stencil plane to find parts of a in b */
  37.   glDepthMask(GL_FALSE);
  38.   glEnable(GL_STENCIL_TEST);
  39.   glStencilFunc(GL_ALWAYS, 0, 0);
  40.   glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  41.   glCullFace(GL_BACK);
  42.   b();                  /* increment the stencil where the front face of b is 
  43.                            drawn */
  44.   glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
  45.   glCullFace(GL_FRONT);
  46.   b();                  /* decrement the stencil buffer where the back face
  47.                            of b is drawn */
  48.   glDepthMask(GL_TRUE);
  49.   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  50.   glStencilFunc(test, 0, 1);
  51.   glDisable(GL_DEPTH_TEST);
  52.   glCullFace(face);
  53.   a();                  /* draw the part of a that's in b */
  54. }
  55. void
  56. fixDepth(void (*a) (void))
  57. {
  58.   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  59.   glEnable(GL_DEPTH_TEST);
  60.   glDisable(GL_STENCIL_TEST);
  61.   glDepthFunc(GL_ALWAYS);
  62.   a();                  /* draw the front face of a, fixing the depth buffer */
  63.   glDepthFunc(GL_LESS);
  64. }
  65. /* "and" two objects together */
  66. void
  67. and(void (*a) (void), void (*b) (void))
  68. {
  69.   firstInsideSecond(a, b, GL_BACK, GL_NOTEQUAL);
  70.   fixDepth(b);
  71.   firstInsideSecond(b, a, GL_BACK, GL_NOTEQUAL);
  72.   glDisable(GL_STENCIL_TEST);  /* reset things */
  73. }
  74. /* subtract b from a */
  75. void
  76. sub(void (*a) (void), void (*b) (void))
  77. {
  78.   firstInsideSecond(a, b, GL_FRONT, GL_NOTEQUAL);
  79.   fixDepth(b);
  80.   firstInsideSecond(b, a, GL_BACK, GL_EQUAL);
  81.   glDisable(GL_STENCIL_TEST);  /* reset things */
  82. }
  83. enum {
  84.   SPHERE = 1, CONE
  85. };
  86. /* Draw a cone */
  87. GLfloat coneX = 0.f, coneY = 0.f, coneZ = 0.f;
  88. void
  89. cone(void)
  90. {
  91.   glPushMatrix();
  92.   glTranslatef(coneX, coneY, coneZ);
  93.   glTranslatef(0.f, 0.f, -30.f);
  94.   glCallList(CONE);
  95.   glPopMatrix();
  96. }
  97. /* Draw a sphere */
  98. GLfloat sphereX = 0.f, sphereY = 0.f, sphereZ = 0.f;
  99. void
  100. sphere(void)
  101. {
  102.   glPushMatrix();
  103.   glTranslatef(sphereX, sphereY, sphereZ);
  104.   glCallList(SPHERE);
  105.   glPopMatrix();
  106. }
  107. int csg_op = CSG_A;
  108. /* add menu callback */
  109. void 
  110. menu(int csgop)
  111. {
  112.   csg_op = csgop;
  113.   glutPostRedisplay();
  114. }
  115. GLfloat viewangle;
  116. void 
  117. redraw(void)
  118. {
  119.   /* clear stencil each time */
  120.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  121.   glPushMatrix();
  122.   glRotatef(viewangle, 0.f, 1.f, 0.f);
  123.   switch (csg_op) {
  124.   case CSG_A:
  125.     one(cone);
  126.     break;
  127.   case CSG_B:
  128.     one(sphere);
  129.     break;
  130.   case CSG_A_OR_B:
  131.     or(cone, sphere);
  132.     break;
  133.   case CSG_A_AND_B:
  134.     and(cone, sphere);
  135.     break;
  136.   case CSG_A_SUB_B:
  137.     sub(cone, sphere);
  138.     break;
  139.   case CSG_B_SUB_A:
  140.     sub(sphere, cone);
  141.     break;
  142.   }
  143.   glPopMatrix();
  144.   glutSwapBuffers();
  145. }
  146. /* animate scene by rotating */
  147. enum {
  148.   ANIM_LEFT, ANIM_RIGHT
  149. };
  150. int animDirection = ANIM_LEFT;
  151. void 
  152. anim(void)
  153. {
  154.   if (animDirection == ANIM_LEFT)
  155.     viewangle -= 3.f;
  156.   else
  157.     viewangle += 3.f;
  158.   glutPostRedisplay();
  159. }
  160. /* ARGSUSED1 */
  161. /* special keys, like array and F keys */
  162. void 
  163. special(int key, int x, int y)
  164. {
  165.   switch (key) {
  166.   case GLUT_KEY_LEFT:
  167.     glutIdleFunc(anim);
  168.     animDirection = ANIM_LEFT;
  169.     break;
  170.   case GLUT_KEY_RIGHT:
  171.     glutIdleFunc(anim);
  172.     animDirection = ANIM_RIGHT;
  173.     break;
  174.   case GLUT_KEY_UP:
  175.   case GLUT_KEY_DOWN:
  176.     glutIdleFunc(0);
  177.     break;
  178.   }
  179. }
  180. /* ARGSUSED1 */
  181. void 
  182. key(unsigned char key, int x, int y)
  183. {
  184.   switch (key) {
  185.   case 'a':
  186.     viewangle -= 10.f;
  187.     glutPostRedisplay();
  188.     break;
  189.   case 's':
  190.     viewangle += 10.f;
  191.     glutPostRedisplay();
  192.     break;
  193.   case '33':
  194.     exit(0);
  195.   }
  196. }
  197. int picked_object;
  198. int xpos = 0, ypos = 0;
  199. int newxpos, newypos;
  200. int startx, starty;
  201. void
  202. mouse(int button, int state, int x, int y)
  203. {
  204.   if (state == GLUT_UP) {
  205.     picked_object = button;
  206.     xpos += newxpos;
  207.     ypos += newypos;
  208.     newxpos = 0;
  209.     newypos = 0;
  210.   } else {              /* GLUT_DOWN */
  211.     startx = x;
  212.     starty = y;
  213.   }
  214. }
  215. #define DEGTORAD (2 * 3.1415 / 360)
  216. void 
  217. motion(int x, int y)
  218. {
  219.   GLfloat r, objx, objy, objz;
  220.   newxpos = x - startx;
  221.   newypos = starty - y;
  222.   r = (newxpos + xpos) * 50.f / 512.f;
  223.   objx = r * cos(viewangle * DEGTORAD);
  224.   objy = (newypos + ypos) * 50.f / 512.f;
  225.   objz = r * sin(viewangle * DEGTORAD);
  226.   switch (picked_object) {
  227.   case CSG_A:
  228.     coneX = objx;
  229.     coneY = objy;
  230.     coneZ = objz;
  231.     break;
  232.   case CSG_B:
  233.     sphereX = objx;
  234.     sphereY = objy;
  235.     sphereZ = objz;
  236.     break;
  237.   }
  238.   glutPostRedisplay();
  239. }
  240. int
  241. main(int argc, char **argv)
  242. {
  243.   static GLfloat lightpos[] =
  244.   {25.f, 50.f, -50.f, 1.f};
  245.   static GLfloat sphere_mat[] =
  246.   {1.f, .5f, 0.f, 1.f};
  247.   static GLfloat cone_mat[] =
  248.   {0.f, .5f, 1.f, 1.f};
  249.   GLUquadricObj *sphere, *cone, *base;
  250.   glutInit(&argc, argv);
  251.   glutInitWindowSize(512, 512);
  252.   glutInitDisplayMode(GLUT_STENCIL | GLUT_DEPTH | GLUT_DOUBLE);
  253.   (void) glutCreateWindow("csg");
  254.   glutDisplayFunc(redraw);
  255.   glutKeyboardFunc(key);
  256.   glutSpecialFunc(special);
  257.   glutMouseFunc(mouse);
  258.   glutMotionFunc(motion);
  259.   glutCreateMenu(menu);
  260.   glutAddMenuEntry("A only", CSG_A);
  261.   glutAddMenuEntry("B only", CSG_B);
  262.   glutAddMenuEntry("A or B", CSG_A_OR_B);
  263.   glutAddMenuEntry("A and B", CSG_A_AND_B);
  264.   glutAddMenuEntry("A sub B", CSG_A_SUB_B);
  265.   glutAddMenuEntry("B sub A", CSG_B_SUB_A);
  266.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  267.   glEnable(GL_CULL_FACE);
  268.   glEnable(GL_LIGHTING);
  269.   glEnable(GL_LIGHT0);
  270.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  271.   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  272.   /* make display lists for sphere and cone; for efficiency */
  273.   glNewList(SPHERE, GL_COMPILE);
  274.   sphere = gluNewQuadric();
  275.   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  276.   gluSphere(sphere, 20.f, 64, 64);
  277.   gluDeleteQuadric(sphere);
  278.   glEndList();
  279.   glNewList(CONE, GL_COMPILE);
  280.   cone = gluNewQuadric();
  281.   base = gluNewQuadric();
  282.   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  283.   gluQuadricOrientation(base, GLU_INSIDE);
  284.   gluDisk(base, 0., 15., 64, 1);
  285.   gluCylinder(cone, 15., 0., 60., 64, 64);
  286.   gluDeleteQuadric(cone);
  287.   gluDeleteQuadric(base);
  288.   glEndList();
  289.   glMatrixMode(GL_PROJECTION);
  290.   glOrtho(-50., 50., -50., 50., -50., 50.);
  291.   glMatrixMode(GL_MODELVIEW);
  292.   glutMainLoop();
  293.   return 0;             /* ANSI C requires main to return int. */
  294. }