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

GIS编程

开发平台:

Visual C++

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <GL/glut.h>
  5. /* Some <math.h> files do not define M_PI... */
  6. #ifndef M_PI
  7. #define M_PI 3.14159265358979323846
  8. #endif
  9. #define TRUE 1
  10. #define FALSE 0
  11. /*
  12.  * #define the following symbol if you know your glClear honors the
  13.  * stencil mask.  The O2 workstation stencil clear doesn't appear
  14.  * to honor the mask, so we use a workaround.  The workaround may work
  15.  * on any other OpenGL which has this clear bug.
  16.  */
  17. #undef CLEAR_HONORS_STENCIL_MASK
  18. GLUquadricObj *quadric;
  19. int doCSG = 0;
  20. int whereToStop = -1;
  21. typedef enum {CONTINUE, STOP} progressEnum;
  22. int whichTree = 0;
  23. int showSurfaces = 1;
  24. int showOnlyCurrent = 0;
  25. int stenSize;
  26. enum {COLOR, DEPTH, STENCILVALUES, STENCILPLANES} bufferInterest = COLOR;
  27. void drawFace(void)
  28. {
  29.     glBegin(GL_QUADS);
  30.     glNormal3i(0, 0, 1);
  31.     glVertex3f(1, 1, 1);
  32.     glVertex3f(-1, 1, 1);
  33.     glVertex3f(-1, -1, 1);
  34.     glVertex3f(1, -1, 1);
  35.     glEnd();
  36. }
  37. void drawBox(void)
  38. {
  39.     glPushMatrix();
  40.     drawFace();
  41.     glRotatef(90, 1, 0, 0);
  42.     drawFace();
  43.     glRotatef(90, 1, 0, 0);
  44.     drawFace();
  45.     glRotatef(90, 1, 0, 0);
  46.     drawFace();
  47.     glPopMatrix();
  48.     glPushMatrix();
  49.     glRotatef(90, 0, 1, 0);
  50.     drawFace();
  51.     glRotatef(180, 0, 1, 0);
  52.     drawFace();
  53.     glPopMatrix();
  54. }
  55. void drawCylinder(void)
  56. {
  57.     glPushMatrix();
  58.     glTranslatef(0, 0, -.5);
  59.     gluCylinder(quadric, 1, 1, 1, 30, 5);
  60.     glRotatef(180, 0, 1, 0);
  61.     gluDisk(quadric, 0, 1, 30, 2);
  62.     glPopMatrix();
  63.     glPushMatrix();
  64.     glTranslatef(0, 0, .5);
  65.     gluDisk(quadric, 0, 1, 30, 2);
  66.     glPopMatrix();
  67. }
  68. void drawCone(void)
  69. {
  70.     glPushMatrix();
  71.     glTranslatef(0, 0, -.5);
  72.     gluCylinder(quadric, 1, 0, 1, 30, 5);
  73.     glRotatef(180, 0, 1, 0);
  74.     gluDisk(quadric, 0, 1, 30, 2);
  75.     glPopMatrix();
  76. }
  77. void drawSphere(void)
  78. {
  79.     gluSphere(quadric, 1, 30, 20);
  80. }
  81. struct transformation {
  82.     float translation[3];
  83.     float rotation[4];
  84.     float scale[3];
  85. };
  86. struct primitive {
  87.     float color[4];
  88.     void (*draw)(void);
  89.     struct transformation xform;
  90. };
  91. struct transformation globalXform = {
  92.     0, 0, 0,
  93.     1, 0, 0, 0,
  94.     1, 1, 1
  95. };
  96. struct primitive prims[20] = {
  97.     {
  98.         {.5, .5, 1},
  99. drawBox,
  100. {
  101.     -3, 0, 0,
  102.     1, 0, 0, 0,
  103.     1, 1, 1
  104. }
  105.     },
  106.     {
  107.         {1, .5, .5},
  108. drawCylinder,
  109. {
  110.     -1, 0, 0,
  111.     1, 0, 0, 0,
  112.     1, 1, 1
  113. }
  114.     },
  115.     {
  116.         {.5, 1, .5},
  117. drawCone,
  118. {
  119.     1, 0, 0,
  120.     1, 0, 0, 0,
  121.     1, 1, 1
  122. }
  123.     },
  124.     {
  125.         {1, .5, 1},
  126. drawSphere,
  127. {
  128.     3, 0, 0,
  129.     1, 0, 0, 0,
  130.     1, 1, 1
  131. }
  132.     }
  133. };
  134. int numPrims = 4;
  135. int curPrim = 0;
  136. void drawXform(struct transformation *xform, int applyScale)
  137. {
  138.     glTranslatef(xform->translation[0], xform->translation[1], xform->translation[2]);
  139.     glRotatef(xform->rotation[3] / M_PI * 180, xform->rotation[0], xform->rotation[1], xform->rotation[2]);
  140.     if(applyScale)
  141. glScalef(xform->scale[0], xform->scale[1], xform->scale[2]);
  142. }
  143. int magicTranspHack = 0;
  144. void drawPrim(int i)
  145. {
  146.     struct primitive *p = &prims[i];
  147.     struct transformation *xform = &p->xform;
  148.     if(magicTranspHack)
  149.     {
  150.         float c[4];
  151. c[0] = p->color[0];
  152. c[1] = p->color[1];
  153. c[2] = p->color[2];
  154. c[3] = .25;
  155. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
  156.     }
  157.     else
  158. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, p->color);
  159.     glPushMatrix();
  160.     drawXform(xform, TRUE);
  161.     p->draw();
  162.     glPopMatrix();
  163. }
  164. struct product {
  165.     int targetPrim;
  166.     int frontFace;
  167.     int whichSurface;
  168.     int numTrimPrims;
  169.     int *trimmingPrims;
  170.     int *isComplemented;
  171. };
  172. int prodAtrimmingPrims1[] = {1};
  173. int prodAisComplemented1[] = {1};
  174. int prodBtrimmingPrims1[] = {0};
  175. int prodBisComplemented1[] = {0};
  176. int prodAtrimmingPrims2[] = {1};
  177. int prodAisComplemented2[] = {0};
  178. int prodBtrimmingPrims2[] = {0};
  179. int prodBisComplemented2[] = {1};
  180. int prodAtrimmingPrims3[] = {1};
  181. int prodAisComplemented3[] = {0};
  182. int prodBtrimmingPrims3[] = {0};
  183. int prodBisComplemented3[] = {0};
  184. int prodAtrimmingPrims4[] = {1, 2, 3};
  185. int prodAisComplemented4[] = {0, 1, 1};
  186. int prodBtrimmingPrims4[] = {1, 0, 2};
  187. int prodBisComplemented4[] = {0, 0, 1};
  188. int prodCtrimmingPrims4[] = {1, 0, 3};
  189. int prodCisComplemented4[] = {0, 0, 1};
  190. int prodDtrimmingPrims4[] = {0, 2, 3};
  191. int prodDisComplemented4[] = {0, 1, 1};
  192. struct product products[][4] = {
  193.     { /* A - B */
  194. {
  195.     0, 1, 0,
  196.     1,
  197.     prodAtrimmingPrims1,
  198.     prodAisComplemented1,
  199. },
  200. {
  201.     1, 0, 0,
  202.     1,
  203.     prodBtrimmingPrims1,
  204.     prodBisComplemented1,
  205. },
  206.     },
  207.     {    /* B - A */
  208. {
  209.     0, 0, 0,
  210.     1,
  211.     prodAtrimmingPrims2,
  212.     prodAisComplemented2,
  213. },
  214. {
  215.     1, 1, 0,
  216.     1,
  217.     prodBtrimmingPrims2,
  218.     prodBisComplemented2,
  219. },
  220.     },
  221.     {    /* A and B */
  222. {
  223.     0, 1, 0,
  224.     1,
  225.     prodAtrimmingPrims3,
  226.     prodAisComplemented3,
  227. },
  228. {
  229.     1, 1, 0,
  230.     1,
  231.     prodBtrimmingPrims3,
  232.     prodBisComplemented3,
  233. },
  234.     },
  235.     { /* A and B - D - C */
  236. {
  237.     0, 1, 0,
  238.     3,
  239.     prodAtrimmingPrims4,
  240.     prodAisComplemented4,
  241. },
  242. {
  243.     3, 0, 0,
  244.     3,
  245.     prodBtrimmingPrims4,
  246.     prodBisComplemented4,
  247. },
  248. {
  249.     2, 0, 0,
  250.     3,
  251.     prodCtrimmingPrims4,
  252.     prodCisComplemented4,
  253. },
  254. {
  255.     1, 1, 0,
  256.     3,
  257.     prodDtrimmingPrims4,
  258.     prodDisComplemented4,
  259. },
  260.     },
  261. };
  262. int numProducts[4] = {2, 2, 2, 4};
  263. int  winWidth, winHeight;
  264. GLfloat  *depthSave = NULL;
  265. GLubyte  *stencilSave = NULL;
  266. GLubyte  *colorSave = NULL;
  267. void resizeBuffers(void)
  268. {
  269.     if(colorSave != NULL)
  270.         free(colorSave);
  271.     colorSave = malloc(winWidth * winHeight * 4 * sizeof(GLubyte));
  272.     if(depthSave != NULL)
  273.         free(depthSave);
  274.     depthSave = malloc(winWidth * winHeight * sizeof(GLfloat));
  275.     stencilSave = (GLubyte *)depthSave;
  276. }
  277. void pushOrthoView(float left, float right, float bottom, float top,
  278.     float znear, float zfar)
  279. {
  280.     glPushMatrix();
  281.     glLoadIdentity();
  282.     glMatrixMode(GL_PROJECTION);
  283.     glPushMatrix();
  284.     glLoadIdentity();
  285.     glOrtho(left, right, bottom, top, znear, zfar);
  286. }
  287. void popView(void)
  288. {
  289.     glPopMatrix();
  290.     glMatrixMode(GL_MODELVIEW);
  291.     glPopMatrix();
  292. }
  293. void copyDepthToColor(GLenum whichColorBuffer)
  294. {
  295.     int x, y;
  296.     GLfloat max, min;
  297.     GLint previousColorBuffer;
  298.     glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
  299.         depthSave);
  300.     /* I'm sure this could be done much better with OpenGL */
  301.     max = 0;
  302.     min = 1;
  303.     for(y = 0; y < winHeight; y++)
  304. for(x = 0; x < winWidth; x++) {
  305.     if(depthSave[winWidth * y + x] < min)
  306. min = depthSave[winWidth * y + x];
  307.     if(depthSave[winWidth * y + x] > max && depthSave[winWidth * y + x] < .999)
  308. max = depthSave[winWidth * y + x];
  309. }
  310.     for(y = 0; y < winHeight; y++)
  311. for(x = 0; x < winWidth; x++) {
  312.     if(depthSave[winWidth * y + x] <= max)
  313. depthSave[winWidth * y + x] = 1 -  (depthSave[winWidth * y + x] - min) / (max - min);
  314.     else
  315. depthSave[winWidth * y + x] = 0;
  316. }
  317.     pushOrthoView(0, 1, 0, 1, 0, 1);
  318.     glRasterPos3f(0, 0, -.5);
  319.     glDisable(GL_DEPTH_TEST);
  320.     glDisable(GL_STENCIL_TEST);
  321.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  322.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  323.     glDrawBuffer(whichColorBuffer);
  324.     glDrawPixels(winWidth, winHeight, GL_LUMINANCE , GL_FLOAT, depthSave);
  325.     glDrawBuffer(previousColorBuffer);
  326.     glEnable(GL_DEPTH_TEST);
  327.     popView();
  328. }
  329. unsigned char stencilValueToColorMap[][3] =
  330. {
  331.     {255, 0, 0}, /* red */
  332.     {255, 218, 0}, /* yellow */
  333.     {72, 255, 0}, /* yellowish green */
  334.     {0, 255, 145}, /* bluish cyan */
  335.     {0, 145, 255}, /* cyanish blue */
  336.     {72, 0, 255}, /* purplish blue */
  337.     {255, 0, 218}, /* reddish purple */
  338. };
  339. void copyStencilValuesToColor(GLenum whichColorBuffer)
  340. {
  341.     int x, y;
  342.     GLint previousColorBuffer;
  343.     glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
  344.         stencilSave);
  345.     /* I'm sure this could be done much better with OpenGL */
  346.     for(y = 0; y < winHeight; y++)
  347. for(x = 0; x < winWidth; x++) {
  348.     int stencilValue;
  349.     
  350.     stencilValue = stencilSave[winWidth * y + x];
  351.     colorSave[(winWidth * y + x) * 3 + 0] =
  352.         stencilValueToColorMap[stencilValue % 7][0];
  353.     colorSave[(winWidth * y + x) * 3 + 1] =
  354.         stencilValueToColorMap[stencilValue % 7][1];
  355.     colorSave[(winWidth * y + x) * 3 + 2] =
  356.         stencilValueToColorMap[stencilValue % 7][2];
  357. }
  358.     pushOrthoView(0, 1, 0, 1, 0, 1);
  359.     glRasterPos3f(0, 0, -.5);
  360.     glDisable(GL_DEPTH_TEST);
  361.     glDisable(GL_STENCIL_TEST);
  362.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  363.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  364.     glDrawBuffer(whichColorBuffer);
  365.     glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
  366.     glDrawBuffer(previousColorBuffer);
  367.     glEnable(GL_DEPTH_TEST);
  368.     popView();
  369. }
  370. /*
  371.  * XXX This function should make colors that identify individual bits in
  372.  * the stencil buffer, but it seems like too hard a problem to solve
  373.  * in five minutes.  Fix later.
  374.  */
  375. void copyStencilPlanesToColor(GLenum whichColorBuffer)
  376. {
  377.     int x, y;
  378.     GLint previousColorBuffer;
  379.     glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
  380.         stencilSave);
  381.     /* I'm sure this could be done much better with OpenGL */
  382.     for(y = 0; y < winHeight; y++)
  383. for(x = 0; x < winWidth; x++) {
  384.     /* Have to think of something clever to do here */
  385. }
  386.     pushOrthoView(0, 1, 0, 1, 0, 1);
  387.     glRasterPos3f(0, 0, -.5);
  388.     glDisable(GL_DEPTH_TEST);
  389.     glDisable(GL_STENCIL_TEST);
  390.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  391.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  392.     glDrawBuffer(whichColorBuffer);
  393.     glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
  394.     glDrawBuffer(previousColorBuffer);
  395.     glEnable(GL_DEPTH_TEST);
  396.     popView();
  397. }
  398. void copyInterest(void)
  399. {
  400.     switch(bufferInterest) {
  401.         case COLOR:
  402.     break; /* Well, that's already there. */
  403. case STENCILVALUES:
  404.     copyStencilValuesToColor(GL_BACK);
  405.     break;
  406. case STENCILPLANES:
  407.     copyStencilPlanesToColor(GL_BACK);
  408.     break;
  409. case DEPTH:
  410.     copyDepthToColor(GL_BACK);
  411.     break;
  412.     }
  413. }
  414. void axisamountToMat(float aa[], float mat[])
  415. {
  416.     float c, s, t;
  417.     c = (float)cos(aa[3]);
  418.     s = (float)sin(aa[3]);
  419.     t = 1.0f - c;
  420.     mat[0] = t * aa[0] * aa[0] + c;
  421.     mat[1] = t * aa[0] * aa[1] + s * aa[2];
  422.     mat[2] = t * aa[0] * aa[2] - s * aa[1];
  423.     mat[3] = t * aa[0] * aa[1] - s * aa[2];
  424.     mat[4] = t * aa[1] * aa[1] + c;
  425.     mat[5] = t * aa[1] * aa[2] + s * aa[0];
  426.     mat[6] = t * aa[0] * aa[2] + s * aa[1];
  427.     mat[7] = t * aa[1] * aa[2] - s * aa[0];
  428.     mat[8] = t * aa[2] * aa[2] + c;
  429. }
  430. void matToAxisamount(float mat[], float aa[])
  431. {
  432.     float c;
  433.     float s;
  434.     c = (mat[0] + mat[4] + mat[8] - 1.0f) / 2.0f;
  435.     aa[3] = (float)acos(c);
  436.     s = (float)sin(aa[3]);
  437.     if(fabs(s / M_PI - (int)(s / M_PI)) < .0000001)
  438.     {
  439.         aa[0] = 0.0f;
  440.         aa[1] = 1.0f;
  441.         aa[2] = 0.0f;
  442.     }
  443.     else
  444.     {
  445. aa[0] = (mat[5] - mat[7]) / (2.0f * s);
  446. aa[1] = (mat[6] - mat[2]) / (2.0f * s);
  447. aa[2] = (mat[1] - mat[3]) / (2.0f * s);
  448.     }
  449. }
  450. void multMat(float m1[], float m2[], float r[])
  451. {
  452.     float t[9];
  453.     int i;
  454.     t[0] = m1[0] * m2[0] + m1[1] * m2[3] + m1[2] * m2[6];
  455.     t[1] = m1[0] * m2[1] + m1[1] * m2[4] + m1[2] * m2[7];
  456.     t[2] = m1[0] * m2[2] + m1[1] * m2[5] + m1[2] * m2[8];
  457.     t[3] = m1[3] * m2[0] + m1[4] * m2[3] + m1[5] * m2[6];
  458.     t[4] = m1[3] * m2[1] + m1[4] * m2[4] + m1[5] * m2[7];
  459.     t[5] = m1[3] * m2[2] + m1[4] * m2[5] + m1[5] * m2[8];
  460.     t[6] = m1[6] * m2[0] + m1[7] * m2[3] + m1[8] * m2[6];
  461.     t[7] = m1[6] * m2[1] + m1[7] * m2[4] + m1[8] * m2[7];
  462.     t[8] = m1[6] * m2[2] + m1[7] * m2[5] + m1[8] * m2[8];
  463.     for(i = 0; i < 9; i++)
  464.     {
  465.         r[i] = t[i];
  466.     }
  467. }
  468. void rotateTrackball(int dx, int dy, float rotation[4])
  469. {
  470.     float dist;
  471.     float oldMat[9];
  472.     float rotMat[9];
  473.     float newRot[4];
  474.     dist = (float)sqrt((double)(dx * dx + dy * dy));
  475.     if(fabs(dist) < 0.99)
  476.         return;
  477.     newRot[0] = (float) dy / dist;
  478.     newRot[1] = (float) dx / dist;
  479.     newRot[2] = 0.0f;
  480.     newRot[3] = (float)M_PI * dist / winWidth;
  481.     axisamountToMat(rotation, oldMat);
  482.     axisamountToMat(newRot, rotMat);
  483.     multMat(oldMat, rotMat, oldMat);
  484.     matToAxisamount(oldMat, rotation);
  485.     dist = (float)sqrt(rotation[0] * rotation[0] + rotation[1] * rotation[1] +
  486.         rotation[2] * rotation[2]);
  487.     rotation[0] /= dist;
  488.     rotation[1] /= dist;
  489.     rotation[2] /= dist;
  490. }
  491. struct transformation *curXform;
  492. void init(void)
  493. {
  494.     glMatrixMode(GL_PROJECTION);
  495.     glFrustum(-.33, .33, -.33, .33, .5, 40);
  496.     glMatrixMode(GL_MODELVIEW);
  497.     gluLookAt(0, 0, 7, 0, 0, 0, 0, 1, 0);
  498.     glEnable(GL_LIGHTING);
  499.     glEnable(GL_LIGHT0);
  500.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  501.     glEnable(GL_NORMALIZE);
  502.     quadric = gluNewQuadric();
  503.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
  504.     curXform = &prims[0].xform;
  505. }
  506. void setupLight(void)
  507. {
  508.     static GLfloat lightpos[] = {0, 1, 0, 0};
  509.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  510. }
  511. void redrawNoCSG(void)
  512. {
  513.     int i;
  514.     glDisable(GL_STENCIL_TEST);
  515.     glEnable(GL_DEPTH_TEST);
  516.     glDepthFunc(GL_LESS);
  517.     glEnable(GL_CULL_FACE);
  518.     glCullFace(GL_BACK);
  519.     glDepthMask(GL_TRUE);
  520.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  521.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  522.     glPushMatrix();
  523.     drawXform(&globalXform, FALSE);
  524.     for(i = 0; i < numPrims; i++)
  525.     {
  526.         if(i == curPrim || !showOnlyCurrent)
  527.     drawPrim(i);
  528.     }
  529.     glPopMatrix();
  530.     copyInterest();
  531.     glutSwapBuffers();
  532. }
  533. int whereSoFar;
  534. GLfloat *depthResults = NULL;
  535. void saveDepth(void)
  536. {
  537.     depthResults = realloc(depthResults, winWidth * winHeight *
  538.         sizeof(GLfloat));
  539.     glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
  540. depthResults);
  541. }
  542. void restoreDepth(void)
  543. {
  544.     glStencilMask(0);
  545.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  546.     glDepthMask(GL_TRUE);
  547.     glEnable(GL_DEPTH_TEST);
  548.     glDepthFunc(GL_ALWAYS);
  549.     glDisable(GL_STENCIL_TEST);
  550.     pushOrthoView(0, 1, 0, 1, 0, 1);
  551.     glRasterPos3f(0, 0, -.5);
  552.     glDrawPixels(winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
  553.         depthResults);
  554.     popView();
  555. }
  556. #define COPY_AND_RETURN_IF_DONE(s) 
  557.     { 
  558. if(whereSoFar++ == whereToStop) { 
  559.     printf("%sn", s); 
  560.     return(STOP);  
  561.     }
  562. #define COPY_AND_GOTO_IF_DONE(s) 
  563.     { 
  564. if(whereSoFar++ == whereToStop) { 
  565.     printf("%sn", s); 
  566.     goto doneWithFrame;  
  567.     }
  568. int sCountMask = 0x01; /* 1-convexity maximum */
  569. int sCountShift = 0;
  570. int sPMask = 1;
  571. int sPShift = 0;
  572. void drawFarRect(void)
  573. {
  574.     pushOrthoView(0, 1, 0, 1, 0, 1);
  575.     /* Can I just draw & let be clipped? */
  576.     glBegin(GL_QUADS);
  577.     glVertex3f(0, 0, -1);
  578.     glVertex3f(1, 0, -1);
  579.     glVertex3f(1, 1, -1);
  580.     glVertex3f(0, 1, -1);
  581.     glEnd();
  582.     popView();
  583. }
  584. progressEnum renderPrimDepths(int targetPrim, int frontFace, int whichSurface)
  585. {
  586.     glClear(GL_DEPTH_BUFFER_BIT);
  587.     glDepthFunc(GL_ALWAYS);
  588.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  589.     glStencilMask(sCountMask);
  590. #ifndef CLEAR_HONORS_STENCIL_MASK /* see comment at beginning of source */
  591.     glDisable(GL_CULL_FACE);
  592.     glDisable(GL_DEPTH_TEST);
  593.     glDepthMask(GL_FALSE);
  594.     glStencilFunc(GL_ALWAYS, 0, 0);
  595.     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  596.     drawFarRect();
  597.     COPY_AND_RETURN_IF_DONE("After clearing p bit in stencil");
  598. #else
  599.     glClearStencil(0);
  600.     glClear(GL_STENCIL_BUFFER_BIT);
  601. #endif
  602.     glEnable(GL_CULL_FACE);
  603.     if(frontFace)
  604.         glCullFace(GL_BACK);
  605.     else
  606.         glCullFace(GL_FRONT);
  607.     glEnable(GL_DEPTH_TEST);
  608.     glDepthMask(GL_TRUE);
  609.     glStencilFunc(GL_EQUAL, whichSurface, sCountMask);
  610.     glStencilOp(GL_INCR, GL_INCR, GL_INCR);
  611.     drawPrim(targetPrim);
  612.     return(CONTINUE);
  613. }
  614. progressEnum trimWithPrimitive(int trimPrim, int isComplemented)
  615. {
  616.     glDepthFunc(GL_LESS);
  617.     glEnable(GL_STENCIL_TEST);
  618.     glDepthMask(GL_FALSE);
  619.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  620.     glStencilMask(sPMask);
  621.     glDisable(GL_CULL_FACE);
  622. #ifndef CLEAR_HONORS_STENCIL_MASK /* see comment at beginning of source */
  623.     glDisable(GL_DEPTH_TEST);
  624.     glStencilFunc(GL_ALWAYS, isComplemented ? (1 << sPShift) : 0, 0);
  625.     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  626.     drawFarRect();
  627. #else
  628.     glClearStencil(isComplemented ? (1 << sPShift) : 0);
  629.     glClear(GL_STENCIL_BUFFER_BIT);
  630. #endif
  631.     glEnable(GL_DEPTH_TEST);
  632.     glStencilFunc(GL_ALWAYS, 0, 0);
  633.     glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
  634.     drawPrim(trimPrim);
  635.     COPY_AND_RETURN_IF_DONE("After setting stencil to mark depths "
  636.         "inside trimming primitive");
  637.     /* stencil == 0 where pixels were not inside */
  638.     /* so now set Z to far where stencil == 0, everywhere pixels trimmed */
  639.     glStencilFunc(GL_EQUAL, 0, sPMask);
  640.     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  641.     glDepthMask(1);
  642.     glDepthFunc(GL_ALWAYS);
  643.     glDisable(GL_LIGHTING);
  644.     drawFarRect();
  645.     glEnable(GL_LIGHTING);
  646.     COPY_AND_RETURN_IF_DONE("After clearing depths where target outside "
  647.         "trimming primitive");
  648.     return(CONTINUE);
  649. }
  650. progressEnum markProductPixels(int product, int accumBit)
  651. {
  652.     int i;
  653.     struct product *p;
  654.     p = &products[whichTree][product];
  655.     if(renderPrimDepths(p->targetPrim, p->frontFace, p->whichSurface) == STOP)
  656.         return(STOP);
  657.     COPY_AND_RETURN_IF_DONE("After rendering target depths");
  658.     for(i = 0; i < p->numTrimPrims; i++)
  659.     {
  660.         if(trimWithPrimitive(p->trimmingPrims[i], p->isComplemented[i]) == STOP)
  661.     return(STOP);
  662.     }
  663.     COPY_AND_RETURN_IF_DONE("After target has been trimmed by all "
  664.         "trimming primitives");
  665.     /* set accumulator stencil bit for this primitive everywhere depth != far */
  666.     glStencilFunc(GL_ALWAYS, 1 << accumBit, 0);
  667.     glStencilOp(GL_KEEP, GL_ZERO, GL_REPLACE);
  668.     glStencilMask(1 << accumBit);
  669.     glDepthMask(0);
  670.     glDepthFunc(GL_GREATER);
  671.     glDisable(GL_LIGHTING);
  672.     drawFarRect();
  673.     glEnable(GL_LIGHTING);
  674.     COPY_AND_RETURN_IF_DONE("After setting accumulator where depths != far");
  675.     return(CONTINUE);
  676. }
  677. progressEnum drawProduct(int product, int accumBit)
  678. {
  679.     struct product *p;
  680.     p = &products[whichTree][product];
  681.     glEnable(GL_CULL_FACE);
  682.     if(p->frontFace)
  683.         glCullFace(GL_BACK);
  684.     else
  685.         glCullFace(GL_FRONT);
  686.     glDepthMask(GL_TRUE);
  687.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  688.     glEnable(GL_DEPTH_TEST);
  689.     glDepthFunc(GL_LESS);
  690.     glEnable(GL_STENCIL_TEST);
  691.     glStencilFunc(GL_EQUAL, 1 << accumBit, 1 << accumBit);
  692.     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  693.     drawPrim(p->targetPrim);
  694.     COPY_AND_RETURN_IF_DONE("After drawing target color and depth");
  695.     return(CONTINUE);
  696. }
  697. void redrawCSG(void)
  698. {
  699.     int i;
  700.     int accumBit;
  701.     int firstProduct;
  702.     int lastProduct;
  703.     whereSoFar = 0;
  704.     glDepthMask(GL_TRUE);
  705.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
  706.     glClear(GL_COLOR_BUFFER_BIT);
  707.     /* Only have to do this if you're going to look at the stencil buffer */
  708.     glClearStencil(0);
  709.     glStencilMask((1 << stenSize) - 1);
  710.     glClear(GL_STENCIL_BUFFER_BIT);
  711.     glPushMatrix();
  712.     drawXform(&globalXform, FALSE);
  713.     firstProduct = 0;
  714.     while(firstProduct != numProducts[whichTree]) {
  715.     
  716.   /*
  717.  * set lastProduct so that accum bits for first to last fit in
  718.  * stencil buffer minus bits needed for surface counting bits
  719.  */
  720. lastProduct = firstProduct + (stenSize - 1) - 1;
  721. if(lastProduct >= numProducts[whichTree])
  722.     lastProduct = numProducts[whichTree] - 1;
  723. if(firstProduct > 0) /* know depth is clear before 1st group */
  724.     saveDepth();
  725. accumBit = 1; /* first available after counting bits */
  726. for(i = firstProduct; i <= lastProduct; i++)
  727.     if(markProductPixels(i, accumBit++) == STOP)
  728. goto doneWithFrame;
  729. COPY_AND_GOTO_IF_DONE("After marking "inside" target accumulators");
  730. if(firstProduct > 0) /* know depth was clear before first group */
  731.     restoreDepth();
  732. else {
  733.     glDepthMask(GL_TRUE);
  734.     glClear(GL_DEPTH_BUFFER_BIT);
  735. }
  736. accumBit = 1; /* first available after counting bits */
  737. for(i = firstProduct; i <= lastProduct; i++)
  738.     if(drawProduct(i, accumBit++) == STOP)
  739. goto doneWithFrame;
  740. COPY_AND_GOTO_IF_DONE("After drawing all target colors and depths");
  741. firstProduct = lastProduct + 1;
  742.     }
  743.     if(showSurfaces) {
  744. glDisable(GL_STENCIL_TEST);
  745. glDepthMask(GL_FALSE);
  746. glEnable(GL_CULL_FACE);
  747. glCullFace(GL_BACK);
  748. glEnable(GL_BLEND);
  749. magicTranspHack = 1;
  750. for(i = 0; i < numProducts[whichTree]; i++)
  751. {
  752.     struct product *p;
  753.     p = &products[whichTree][i];
  754.     if(i == curPrim || !showOnlyCurrent)
  755. drawPrim(p->targetPrim);
  756. }
  757. magicTranspHack = 0;
  758. glDisable(GL_BLEND);
  759.     }
  760. doneWithFrame:
  761.     glPopMatrix();
  762.     copyInterest();
  763.     glutSwapBuffers();
  764. }
  765. enum trackballModeEnum {
  766.     ROTATE,
  767.     TRANSLATEXY,
  768.     TRANSLATEZ,
  769.     SCALEX,
  770.     SCALEY,
  771.     SCALEZ
  772. } trackballMode = ROTATE;
  773. /* ARGSUSED1 */
  774. void special(int thing, int x, int y)
  775. {
  776.      switch(thing) {
  777.          case GLUT_KEY_F1:
  778.      prims[curPrim].draw = drawBox;
  779.      glutPostRedisplay();
  780.      break;
  781.          case GLUT_KEY_F2:
  782.      prims[curPrim].draw = drawCylinder;
  783.      glutPostRedisplay();
  784.      break;
  785.          case GLUT_KEY_F3:
  786.      prims[curPrim].draw = drawCone;
  787.      glutPostRedisplay();
  788.      break;
  789.          case GLUT_KEY_F4:
  790.      prims[curPrim].draw = drawSphere;
  791.      glutPostRedisplay();
  792.      break;
  793.      }
  794. }
  795. /* ARGSUSED1 */
  796. void keyboard(unsigned char key, int x, int y)
  797. {
  798.     switch(key)
  799.     {
  800.         case '1':
  801.         case '2':
  802.         case '3':
  803.         case '4':
  804.     whichTree = key - '1';
  805.     glutPostRedisplay();
  806.     break;
  807.         case 'r':
  808.     trackballMode = ROTATE;
  809.     break;
  810. case 't':
  811.     trackballMode = TRANSLATEXY;
  812.     break;
  813. case 'T':
  814.     trackballMode = TRANSLATEZ;
  815.     break;
  816. case 'x':
  817.     trackballMode = SCALEX;
  818.     break;
  819. case 'y':
  820.     trackballMode = SCALEY;
  821.     break;
  822. case 'z':
  823.     trackballMode = SCALEZ;
  824.     break;
  825. case 'q': case 'Q': case '33':
  826.     exit(0);
  827.     break;
  828. case '<': case ',':
  829.     if(curXform != &globalXform)
  830.     {
  831. curPrim = (curPrim - 1 + numPrims) % numPrims;
  832. curXform = &prims[curPrim].xform;
  833. printf("Manipulating transformation for object %dn", curPrim);
  834.     }
  835.     else
  836.     {
  837.         printf("Have to toggle out of global mode firstn");
  838.     }
  839.     glutPostRedisplay();
  840.     break;
  841. case '>': case '.':
  842.     if(curXform != &globalXform)
  843.     {
  844. curPrim = (curPrim + 1) % numPrims;
  845. curXform = &prims[curPrim].xform;
  846. printf("Manipulating transformation for object %dn", curPrim);
  847.     }
  848.     else
  849.     {
  850.         printf("Have to toggle out of global mode firstn");
  851.     }
  852.     break;
  853. case 'g':
  854.     if(curXform == &globalXform){
  855. curXform = &prims[curPrim].xform;
  856. printf("Manipulating transformation for object %dn", curPrim);
  857.     }else{
  858. curXform = &globalXform;
  859. printf("Manipulating global transformationn");
  860.     }
  861.     break;
  862. case '+': case '=':
  863.     whereToStop++;
  864.     glutPostRedisplay();
  865.     break;
  866. case '-': case '_':
  867.     whereToStop--;
  868.     glutPostRedisplay();
  869.     break;
  870. case 's':
  871.     glutPostRedisplay();
  872.     showSurfaces = !showSurfaces;
  873.     break;
  874. case 'c':
  875.     doCSG = ! doCSG;
  876.     if(doCSG)
  877. glutDisplayFunc(redrawCSG);
  878.     else
  879. glutDisplayFunc(redrawNoCSG);
  880.     glutPostRedisplay();
  881.     break;
  882. case ' ':
  883.     showOnlyCurrent = !showOnlyCurrent;
  884.     glutPostRedisplay();
  885.     break;
  886.     }
  887. }
  888. static int ox, oy;
  889. /* ARGSUSED */
  890. void button(int b, int state, int x, int y)
  891. {
  892.     ox = x;
  893.     oy = y;
  894. }
  895. void motion(int x, int y)
  896. {
  897.     int dx, dy;
  898.     dx = x - ox;
  899.     dy = y - oy;
  900.     ox = x;
  901.     oy = y;
  902.     switch(trackballMode) {
  903. case ROTATE:
  904.     rotateTrackball(dx, dy, curXform->rotation);
  905.     break;
  906. case SCALEX:
  907.     curXform->scale[0] += (dx + dy) / 40.0f;
  908.     if(curXform->scale[0] < 1/40.0)
  909.         curXform->scale[0] = 1/40.0;
  910.     break;
  911. case SCALEY:
  912.     curXform->scale[1] += (dx + dy) / 40.0f;
  913.     if(curXform->scale[1] < 1/40.0)
  914.         curXform->scale[1] = 1/40.0;
  915.     break;
  916. case SCALEZ:
  917.     curXform->scale[2] += (dx + dy) / 40.0f;
  918.     if(curXform->scale[2] < 1/40.0)
  919.         curXform->scale[2] = 1/40.0;
  920.     break;
  921. case TRANSLATEXY:
  922.     curXform->translation[0] += dx / 40.0f;
  923.     curXform->translation[1] -= dy / 40.0f;
  924.     break;
  925. case TRANSLATEZ:
  926.     curXform->translation[2] += (dx + dy) / 40.0f;
  927.     break;
  928.     }
  929.     glutPostRedisplay();
  930. }
  931. void reshape(int width, int height)
  932. {
  933.     glViewport(0, 0, width, height);
  934.     winWidth = width;
  935.     winHeight = height;
  936.     resizeBuffers();
  937.     glutPostRedisplay();
  938. }
  939. int mainMenu;
  940. void mainMenuFunc(int choice)
  941. {
  942.     switch(choice)
  943.     {
  944.         case 1:
  945.     doCSG = !doCSG;
  946.     if(doCSG) {
  947.      printf("CSG expression onn");
  948. glutDisplayFunc(redrawCSG);
  949. glutChangeToMenuEntry(1, "Turn off CSG", 0);
  950.     }
  951.     else {
  952.      printf("CSG expression offn");
  953. glutDisplayFunc(redrawNoCSG);
  954. glutChangeToMenuEntry(1, "Turn on CSG", 0);
  955.     }
  956. glutPostRedisplay();
  957.     break;
  958.         case 2:
  959.     showSurfaces = !showSurfaces;
  960.     if(showSurfaces) {
  961.      printf("Transparent surfaces onn");
  962. glutChangeToMenuEntry(2, "(s) Don't show objects transparent in CSG", 2);
  963.     }
  964.     else {
  965.      printf("Transparent surfaces offn");
  966. glutChangeToMenuEntry(2, "(s) Show objects transparent in CSG", 2);
  967.     }
  968. glutPostRedisplay();
  969.     break;
  970.     }
  971. }
  972. void interestBufferFunc(int data)
  973. {
  974.     char *s;
  975.     bufferInterest = data;
  976.     switch(data) {
  977.         case COLOR:
  978.     s = "color";
  979.     break;
  980.         case STENCILVALUES:
  981.     s = "stencil values";
  982.     break;
  983.         case STENCILPLANES:
  984.     s = "individual stencil plane converage";
  985.     break;
  986.         case DEPTH:
  987.     s = "depth";
  988.     break;
  989.     }
  990.     printf("Now displaying %s datan", s);
  991.     glutPostRedisplay();
  992. }
  993. void csgMenuFunc(int data)
  994. {
  995.     whichTree = data;
  996.     glutPostRedisplay();
  997. }
  998. void whichObjectFunc(int data)
  999. {
  1000.     switch(data)
  1001.     {
  1002.         case 0:
  1003.         case 1:
  1004.         case 2:
  1005.         case 3:
  1006.     curPrim = data;
  1007.     curXform = &prims[curPrim].xform;
  1008.     printf("Editing object %dn", data);
  1009.     break;
  1010. case 4:
  1011.     curXform = &globalXform;
  1012.     printf("Editing global transformation %dn", data);
  1013.     break;
  1014.     }
  1015. }
  1016. void morphMenuFunc(int data)
  1017. {
  1018.     switch(data) {
  1019.         case 0:
  1020.     prims[curPrim].draw = drawBox;
  1021.     glutPostRedisplay();
  1022.     break;
  1023.         case 1:
  1024.     prims[curPrim].draw = drawCylinder;
  1025.     glutPostRedisplay();
  1026.     break;
  1027.         case 2:
  1028.     prims[curPrim].draw = drawCone;
  1029.     glutPostRedisplay();
  1030.     break;
  1031.         case 3:
  1032.     prims[curPrim].draw = drawSphere;
  1033.     glutPostRedisplay();
  1034.     break;
  1035.      }
  1036. }
  1037. void helpFakeFunc(int d)
  1038. {
  1039. }
  1040. int main(int argc, char **argv)
  1041. {
  1042.     int bufferMenu;
  1043.     int csgMenu;
  1044.     int whichObjectMenu;
  1045.     int morphMenu;
  1046.     int helpFakeMenu;
  1047.     glutInitWindowSize(512,512);
  1048.     glutInit(&argc, argv);
  1049.     glutInitDisplayString("samples stencil>=3 rgb double depth");
  1050.     /* glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH|GLUT_RGBA); */
  1051.     (void)glutCreateWindow("csg using stencil");
  1052.     glutDisplayFunc(redrawNoCSG);
  1053.     glutKeyboardFunc(keyboard);
  1054.     glutSpecialFunc(special);
  1055.     glutMotionFunc(motion);
  1056.     glutMouseFunc(button);
  1057.     glutReshapeFunc(reshape);
  1058.     glGetIntegerv(GL_STENCIL_BITS, &stenSize);
  1059.     printf("%d bits of stencil available in this visualn", stenSize);
  1060.     printf("Hit 'S' to turn stencil on/offn");
  1061.     bufferMenu = glutCreateMenu(interestBufferFunc);
  1062.     glutAddMenuEntry("Color data", COLOR);
  1063.     glutAddMenuEntry("Stencil values", STENCILVALUES);
  1064.     glutAddMenuEntry("Coverage in each stencil plane", STENCILPLANES);
  1065.     glutAddMenuEntry("Depth data", DEPTH);
  1066.     csgMenu = glutCreateMenu(csgMenuFunc);
  1067.     glutAddMenuEntry("(1) obj 1 MINUS obj 2", 0);
  1068.     glutAddMenuEntry("(2) obj 2 MINUS obj 1", 1);
  1069.     glutAddMenuEntry("(3) obj 1 AND obj 2", 2);
  1070.     glutAddMenuEntry("(4) (obj 1 AND obj 2) MINUS (obj 3 or obj 4)", 3);
  1071.     whichObjectMenu = glutCreateMenu(whichObjectFunc);
  1072.     glutAddMenuEntry("Object 1 (blue)", 0);
  1073.     glutAddMenuEntry("Object 2 (peach)", 1);
  1074.     glutAddMenuEntry("Object 3 (green)", 2);
  1075.     glutAddMenuEntry("Object 4 (purple)", 3);
  1076.     glutAddMenuEntry("(g) Toggle between global and local", 4);
  1077.     morphMenu = glutCreateMenu(morphMenuFunc);
  1078.     glutAddMenuEntry("(F1) Box", 0);
  1079.     glutAddMenuEntry("(F2) Cylinder", 1);
  1080.     glutAddMenuEntry("(F3) Cone", 2);
  1081.     glutAddMenuEntry("(F4) Sphere", 3);
  1082.     helpFakeMenu = glutCreateMenu(helpFakeFunc);
  1083.     glutAddMenuEntry("Click the left mouse button and drag to manipulaten", 0);
  1084.     glutAddMenuEntry("Push 'r' to rotate like a trackballn", 0);
  1085.     glutAddMenuEntry("Push 't' to translate in the X-Y planen", 0);
  1086.     glutAddMenuEntry("Push 'T' to translate in the Z axisn", 0);
  1087.     glutAddMenuEntry("Push 'X' to scale in Xn", 0);
  1088.     glutAddMenuEntry("Push 'X' to scale in Yn", 0);
  1089.     glutAddMenuEntry("Push 'Z' to scale in Zn", 0);
  1090.     mainMenu = glutCreateMenu(mainMenuFunc);
  1091.     glutAddMenuEntry("(c) Turn on CSG", 1);
  1092.     glutAddMenuEntry("(s) Show objects transparent in CSG", 2);
  1093.     glutAddSubMenu("Buffer of interest", bufferMenu);
  1094.     glutAddSubMenu("Which CSG expression", csgMenu);
  1095.     glutAddSubMenu("Object for manipulation", whichObjectMenu);
  1096.     glutAddSubMenu("Turn current object into...", morphMenu);
  1097.     glutAddSubMenu("Help with moving and rotating:", helpFakeMenu);
  1098.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  1099.     init();
  1100.     glutMainLoop();
  1101.     return 0;
  1102. }