csg.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:31k
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <GL/glut.h>
- /* Some <math.h> files do not define M_PI... */
- #ifndef M_PI
- #define M_PI 3.14159265358979323846
- #endif
- #define TRUE 1
- #define FALSE 0
- /*
- * #define the following symbol if you know your glClear honors the
- * stencil mask. The O2 workstation stencil clear doesn't appear
- * to honor the mask, so we use a workaround. The workaround may work
- * on any other OpenGL which has this clear bug.
- */
- #undef CLEAR_HONORS_STENCIL_MASK
- GLUquadricObj *quadric;
- int doCSG = 0;
- int whereToStop = -1;
- typedef enum {CONTINUE, STOP} progressEnum;
- int whichTree = 0;
- int showSurfaces = 1;
- int showOnlyCurrent = 0;
- int stenSize;
- enum {COLOR, DEPTH, STENCILVALUES, STENCILPLANES} bufferInterest = COLOR;
- void drawFace(void)
- {
- glBegin(GL_QUADS);
- glNormal3i(0, 0, 1);
- glVertex3f(1, 1, 1);
- glVertex3f(-1, 1, 1);
- glVertex3f(-1, -1, 1);
- glVertex3f(1, -1, 1);
- glEnd();
- }
- void drawBox(void)
- {
- glPushMatrix();
- drawFace();
- glRotatef(90, 1, 0, 0);
- drawFace();
- glRotatef(90, 1, 0, 0);
- drawFace();
- glRotatef(90, 1, 0, 0);
- drawFace();
- glPopMatrix();
- glPushMatrix();
- glRotatef(90, 0, 1, 0);
- drawFace();
- glRotatef(180, 0, 1, 0);
- drawFace();
- glPopMatrix();
- }
- void drawCylinder(void)
- {
- glPushMatrix();
- glTranslatef(0, 0, -.5);
- gluCylinder(quadric, 1, 1, 1, 30, 5);
- glRotatef(180, 0, 1, 0);
- gluDisk(quadric, 0, 1, 30, 2);
- glPopMatrix();
- glPushMatrix();
- glTranslatef(0, 0, .5);
- gluDisk(quadric, 0, 1, 30, 2);
- glPopMatrix();
- }
- void drawCone(void)
- {
- glPushMatrix();
- glTranslatef(0, 0, -.5);
- gluCylinder(quadric, 1, 0, 1, 30, 5);
- glRotatef(180, 0, 1, 0);
- gluDisk(quadric, 0, 1, 30, 2);
- glPopMatrix();
- }
- void drawSphere(void)
- {
- gluSphere(quadric, 1, 30, 20);
- }
- struct transformation {
- float translation[3];
- float rotation[4];
- float scale[3];
- };
- struct primitive {
- float color[4];
- void (*draw)(void);
- struct transformation xform;
- };
- struct transformation globalXform = {
- 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1
- };
- struct primitive prims[20] = {
- {
- {.5, .5, 1},
- drawBox,
- {
- -3, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1
- }
- },
- {
- {1, .5, .5},
- drawCylinder,
- {
- -1, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1
- }
- },
- {
- {.5, 1, .5},
- drawCone,
- {
- 1, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1
- }
- },
- {
- {1, .5, 1},
- drawSphere,
- {
- 3, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1
- }
- }
- };
- int numPrims = 4;
- int curPrim = 0;
- void drawXform(struct transformation *xform, int applyScale)
- {
- glTranslatef(xform->translation[0], xform->translation[1], xform->translation[2]);
- glRotatef(xform->rotation[3] / M_PI * 180, xform->rotation[0], xform->rotation[1], xform->rotation[2]);
- if(applyScale)
- glScalef(xform->scale[0], xform->scale[1], xform->scale[2]);
- }
- int magicTranspHack = 0;
- void drawPrim(int i)
- {
- struct primitive *p = &prims[i];
- struct transformation *xform = &p->xform;
- if(magicTranspHack)
- {
- float c[4];
- c[0] = p->color[0];
- c[1] = p->color[1];
- c[2] = p->color[2];
- c[3] = .25;
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
- }
- else
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, p->color);
- glPushMatrix();
- drawXform(xform, TRUE);
- p->draw();
- glPopMatrix();
- }
- struct product {
- int targetPrim;
- int frontFace;
- int whichSurface;
- int numTrimPrims;
- int *trimmingPrims;
- int *isComplemented;
- };
- int prodAtrimmingPrims1[] = {1};
- int prodAisComplemented1[] = {1};
- int prodBtrimmingPrims1[] = {0};
- int prodBisComplemented1[] = {0};
- int prodAtrimmingPrims2[] = {1};
- int prodAisComplemented2[] = {0};
- int prodBtrimmingPrims2[] = {0};
- int prodBisComplemented2[] = {1};
- int prodAtrimmingPrims3[] = {1};
- int prodAisComplemented3[] = {0};
- int prodBtrimmingPrims3[] = {0};
- int prodBisComplemented3[] = {0};
- int prodAtrimmingPrims4[] = {1, 2, 3};
- int prodAisComplemented4[] = {0, 1, 1};
- int prodBtrimmingPrims4[] = {1, 0, 2};
- int prodBisComplemented4[] = {0, 0, 1};
- int prodCtrimmingPrims4[] = {1, 0, 3};
- int prodCisComplemented4[] = {0, 0, 1};
- int prodDtrimmingPrims4[] = {0, 2, 3};
- int prodDisComplemented4[] = {0, 1, 1};
- struct product products[][4] = {
- { /* A - B */
- {
- 0, 1, 0,
- 1,
- prodAtrimmingPrims1,
- prodAisComplemented1,
- },
- {
- 1, 0, 0,
- 1,
- prodBtrimmingPrims1,
- prodBisComplemented1,
- },
- },
- { /* B - A */
- {
- 0, 0, 0,
- 1,
- prodAtrimmingPrims2,
- prodAisComplemented2,
- },
- {
- 1, 1, 0,
- 1,
- prodBtrimmingPrims2,
- prodBisComplemented2,
- },
- },
- { /* A and B */
- {
- 0, 1, 0,
- 1,
- prodAtrimmingPrims3,
- prodAisComplemented3,
- },
- {
- 1, 1, 0,
- 1,
- prodBtrimmingPrims3,
- prodBisComplemented3,
- },
- },
- { /* A and B - D - C */
- {
- 0, 1, 0,
- 3,
- prodAtrimmingPrims4,
- prodAisComplemented4,
- },
- {
- 3, 0, 0,
- 3,
- prodBtrimmingPrims4,
- prodBisComplemented4,
- },
- {
- 2, 0, 0,
- 3,
- prodCtrimmingPrims4,
- prodCisComplemented4,
- },
- {
- 1, 1, 0,
- 3,
- prodDtrimmingPrims4,
- prodDisComplemented4,
- },
- },
- };
- int numProducts[4] = {2, 2, 2, 4};
- int winWidth, winHeight;
- GLfloat *depthSave = NULL;
- GLubyte *stencilSave = NULL;
- GLubyte *colorSave = NULL;
- void resizeBuffers(void)
- {
- if(colorSave != NULL)
- free(colorSave);
- colorSave = malloc(winWidth * winHeight * 4 * sizeof(GLubyte));
- if(depthSave != NULL)
- free(depthSave);
- depthSave = malloc(winWidth * winHeight * sizeof(GLfloat));
- stencilSave = (GLubyte *)depthSave;
- }
- void pushOrthoView(float left, float right, float bottom, float top,
- float znear, float zfar)
- {
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(left, right, bottom, top, znear, zfar);
- }
- void popView(void)
- {
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- void copyDepthToColor(GLenum whichColorBuffer)
- {
- int x, y;
- GLfloat max, min;
- GLint previousColorBuffer;
- glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
- depthSave);
- /* I'm sure this could be done much better with OpenGL */
- max = 0;
- min = 1;
- for(y = 0; y < winHeight; y++)
- for(x = 0; x < winWidth; x++) {
- if(depthSave[winWidth * y + x] < min)
- min = depthSave[winWidth * y + x];
- if(depthSave[winWidth * y + x] > max && depthSave[winWidth * y + x] < .999)
- max = depthSave[winWidth * y + x];
- }
- for(y = 0; y < winHeight; y++)
- for(x = 0; x < winWidth; x++) {
- if(depthSave[winWidth * y + x] <= max)
- depthSave[winWidth * y + x] = 1 - (depthSave[winWidth * y + x] - min) / (max - min);
- else
- depthSave[winWidth * y + x] = 0;
- }
- pushOrthoView(0, 1, 0, 1, 0, 1);
- glRasterPos3f(0, 0, -.5);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
- glDrawBuffer(whichColorBuffer);
- glDrawPixels(winWidth, winHeight, GL_LUMINANCE , GL_FLOAT, depthSave);
- glDrawBuffer(previousColorBuffer);
- glEnable(GL_DEPTH_TEST);
- popView();
- }
- unsigned char stencilValueToColorMap[][3] =
- {
- {255, 0, 0}, /* red */
- {255, 218, 0}, /* yellow */
- {72, 255, 0}, /* yellowish green */
- {0, 255, 145}, /* bluish cyan */
- {0, 145, 255}, /* cyanish blue */
- {72, 0, 255}, /* purplish blue */
- {255, 0, 218}, /* reddish purple */
- };
- void copyStencilValuesToColor(GLenum whichColorBuffer)
- {
- int x, y;
- GLint previousColorBuffer;
- glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
- stencilSave);
- /* I'm sure this could be done much better with OpenGL */
- for(y = 0; y < winHeight; y++)
- for(x = 0; x < winWidth; x++) {
- int stencilValue;
-
- stencilValue = stencilSave[winWidth * y + x];
- colorSave[(winWidth * y + x) * 3 + 0] =
- stencilValueToColorMap[stencilValue % 7][0];
- colorSave[(winWidth * y + x) * 3 + 1] =
- stencilValueToColorMap[stencilValue % 7][1];
- colorSave[(winWidth * y + x) * 3 + 2] =
- stencilValueToColorMap[stencilValue % 7][2];
- }
- pushOrthoView(0, 1, 0, 1, 0, 1);
- glRasterPos3f(0, 0, -.5);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
- glDrawBuffer(whichColorBuffer);
- glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
- glDrawBuffer(previousColorBuffer);
- glEnable(GL_DEPTH_TEST);
- popView();
- }
- /*
- * XXX This function should make colors that identify individual bits in
- * the stencil buffer, but it seems like too hard a problem to solve
- * in five minutes. Fix later.
- */
- void copyStencilPlanesToColor(GLenum whichColorBuffer)
- {
- int x, y;
- GLint previousColorBuffer;
- glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
- stencilSave);
- /* I'm sure this could be done much better with OpenGL */
- for(y = 0; y < winHeight; y++)
- for(x = 0; x < winWidth; x++) {
- /* Have to think of something clever to do here */
- }
- pushOrthoView(0, 1, 0, 1, 0, 1);
- glRasterPos3f(0, 0, -.5);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
- glDrawBuffer(whichColorBuffer);
- glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
- glDrawBuffer(previousColorBuffer);
- glEnable(GL_DEPTH_TEST);
- popView();
- }
- void copyInterest(void)
- {
- switch(bufferInterest) {
- case COLOR:
- break; /* Well, that's already there. */
- case STENCILVALUES:
- copyStencilValuesToColor(GL_BACK);
- break;
- case STENCILPLANES:
- copyStencilPlanesToColor(GL_BACK);
- break;
- case DEPTH:
- copyDepthToColor(GL_BACK);
- break;
- }
- }
- void axisamountToMat(float aa[], float mat[])
- {
- float c, s, t;
- c = (float)cos(aa[3]);
- s = (float)sin(aa[3]);
- t = 1.0f - c;
- mat[0] = t * aa[0] * aa[0] + c;
- mat[1] = t * aa[0] * aa[1] + s * aa[2];
- mat[2] = t * aa[0] * aa[2] - s * aa[1];
- mat[3] = t * aa[0] * aa[1] - s * aa[2];
- mat[4] = t * aa[1] * aa[1] + c;
- mat[5] = t * aa[1] * aa[2] + s * aa[0];
- mat[6] = t * aa[0] * aa[2] + s * aa[1];
- mat[7] = t * aa[1] * aa[2] - s * aa[0];
- mat[8] = t * aa[2] * aa[2] + c;
- }
- void matToAxisamount(float mat[], float aa[])
- {
- float c;
- float s;
- c = (mat[0] + mat[4] + mat[8] - 1.0f) / 2.0f;
- aa[3] = (float)acos(c);
- s = (float)sin(aa[3]);
- if(fabs(s / M_PI - (int)(s / M_PI)) < .0000001)
- {
- aa[0] = 0.0f;
- aa[1] = 1.0f;
- aa[2] = 0.0f;
- }
- else
- {
- aa[0] = (mat[5] - mat[7]) / (2.0f * s);
- aa[1] = (mat[6] - mat[2]) / (2.0f * s);
- aa[2] = (mat[1] - mat[3]) / (2.0f * s);
- }
- }
- void multMat(float m1[], float m2[], float r[])
- {
- float t[9];
- int i;
- t[0] = m1[0] * m2[0] + m1[1] * m2[3] + m1[2] * m2[6];
- t[1] = m1[0] * m2[1] + m1[1] * m2[4] + m1[2] * m2[7];
- t[2] = m1[0] * m2[2] + m1[1] * m2[5] + m1[2] * m2[8];
- t[3] = m1[3] * m2[0] + m1[4] * m2[3] + m1[5] * m2[6];
- t[4] = m1[3] * m2[1] + m1[4] * m2[4] + m1[5] * m2[7];
- t[5] = m1[3] * m2[2] + m1[4] * m2[5] + m1[5] * m2[8];
- t[6] = m1[6] * m2[0] + m1[7] * m2[3] + m1[8] * m2[6];
- t[7] = m1[6] * m2[1] + m1[7] * m2[4] + m1[8] * m2[7];
- t[8] = m1[6] * m2[2] + m1[7] * m2[5] + m1[8] * m2[8];
- for(i = 0; i < 9; i++)
- {
- r[i] = t[i];
- }
- }
- void rotateTrackball(int dx, int dy, float rotation[4])
- {
- float dist;
- float oldMat[9];
- float rotMat[9];
- float newRot[4];
- dist = (float)sqrt((double)(dx * dx + dy * dy));
- if(fabs(dist) < 0.99)
- return;
- newRot[0] = (float) dy / dist;
- newRot[1] = (float) dx / dist;
- newRot[2] = 0.0f;
- newRot[3] = (float)M_PI * dist / winWidth;
- axisamountToMat(rotation, oldMat);
- axisamountToMat(newRot, rotMat);
- multMat(oldMat, rotMat, oldMat);
- matToAxisamount(oldMat, rotation);
- dist = (float)sqrt(rotation[0] * rotation[0] + rotation[1] * rotation[1] +
- rotation[2] * rotation[2]);
- rotation[0] /= dist;
- rotation[1] /= dist;
- rotation[2] /= dist;
- }
- struct transformation *curXform;
- void init(void)
- {
- glMatrixMode(GL_PROJECTION);
- glFrustum(-.33, .33, -.33, .33, .5, 40);
- glMatrixMode(GL_MODELVIEW);
- gluLookAt(0, 0, 7, 0, 0, 0, 0, 1, 0);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_NORMALIZE);
- quadric = gluNewQuadric();
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
- curXform = &prims[0].xform;
- }
- void setupLight(void)
- {
- static GLfloat lightpos[] = {0, 1, 0, 0};
- glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
- }
- void redrawNoCSG(void)
- {
- int i;
- glDisable(GL_STENCIL_TEST);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glPushMatrix();
- drawXform(&globalXform, FALSE);
- for(i = 0; i < numPrims; i++)
- {
- if(i == curPrim || !showOnlyCurrent)
- drawPrim(i);
- }
- glPopMatrix();
- copyInterest();
- glutSwapBuffers();
- }
- int whereSoFar;
- GLfloat *depthResults = NULL;
- void saveDepth(void)
- {
- depthResults = realloc(depthResults, winWidth * winHeight *
- sizeof(GLfloat));
- glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
- depthResults);
- }
- void restoreDepth(void)
- {
- glStencilMask(0);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glDepthMask(GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glDisable(GL_STENCIL_TEST);
- pushOrthoView(0, 1, 0, 1, 0, 1);
- glRasterPos3f(0, 0, -.5);
- glDrawPixels(winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
- depthResults);
- popView();
- }
- #define COPY_AND_RETURN_IF_DONE(s)
- {
- if(whereSoFar++ == whereToStop) {
- printf("%sn", s);
- return(STOP);
- }
- }
- #define COPY_AND_GOTO_IF_DONE(s)
- {
- if(whereSoFar++ == whereToStop) {
- printf("%sn", s);
- goto doneWithFrame;
- }
- }
- int sCountMask = 0x01; /* 1-convexity maximum */
- int sCountShift = 0;
- int sPMask = 1;
- int sPShift = 0;
- void drawFarRect(void)
- {
- pushOrthoView(0, 1, 0, 1, 0, 1);
- /* Can I just draw & let be clipped? */
- glBegin(GL_QUADS);
- glVertex3f(0, 0, -1);
- glVertex3f(1, 0, -1);
- glVertex3f(1, 1, -1);
- glVertex3f(0, 1, -1);
- glEnd();
- popView();
- }
- progressEnum renderPrimDepths(int targetPrim, int frontFace, int whichSurface)
- {
- glClear(GL_DEPTH_BUFFER_BIT);
- glDepthFunc(GL_ALWAYS);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glStencilMask(sCountMask);
- #ifndef CLEAR_HONORS_STENCIL_MASK /* see comment at beginning of source */
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
- glStencilFunc(GL_ALWAYS, 0, 0);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- drawFarRect();
- COPY_AND_RETURN_IF_DONE("After clearing p bit in stencil");
- #else
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT);
- #endif
- glEnable(GL_CULL_FACE);
- if(frontFace)
- glCullFace(GL_BACK);
- else
- glCullFace(GL_FRONT);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
- glStencilFunc(GL_EQUAL, whichSurface, sCountMask);
- glStencilOp(GL_INCR, GL_INCR, GL_INCR);
- drawPrim(targetPrim);
- return(CONTINUE);
- }
- progressEnum trimWithPrimitive(int trimPrim, int isComplemented)
- {
- glDepthFunc(GL_LESS);
- glEnable(GL_STENCIL_TEST);
- glDepthMask(GL_FALSE);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- glStencilMask(sPMask);
- glDisable(GL_CULL_FACE);
- #ifndef CLEAR_HONORS_STENCIL_MASK /* see comment at beginning of source */
- glDisable(GL_DEPTH_TEST);
- glStencilFunc(GL_ALWAYS, isComplemented ? (1 << sPShift) : 0, 0);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- drawFarRect();
- #else
- glClearStencil(isComplemented ? (1 << sPShift) : 0);
- glClear(GL_STENCIL_BUFFER_BIT);
- #endif
- glEnable(GL_DEPTH_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
- drawPrim(trimPrim);
- COPY_AND_RETURN_IF_DONE("After setting stencil to mark depths "
- "inside trimming primitive");
- /* stencil == 0 where pixels were not inside */
- /* so now set Z to far where stencil == 0, everywhere pixels trimmed */
- glStencilFunc(GL_EQUAL, 0, sPMask);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glDepthMask(1);
- glDepthFunc(GL_ALWAYS);
- glDisable(GL_LIGHTING);
- drawFarRect();
- glEnable(GL_LIGHTING);
- COPY_AND_RETURN_IF_DONE("After clearing depths where target outside "
- "trimming primitive");
- return(CONTINUE);
- }
- progressEnum markProductPixels(int product, int accumBit)
- {
- int i;
- struct product *p;
- p = &products[whichTree][product];
- if(renderPrimDepths(p->targetPrim, p->frontFace, p->whichSurface) == STOP)
- return(STOP);
- COPY_AND_RETURN_IF_DONE("After rendering target depths");
- for(i = 0; i < p->numTrimPrims; i++)
- {
- if(trimWithPrimitive(p->trimmingPrims[i], p->isComplemented[i]) == STOP)
- return(STOP);
- }
- COPY_AND_RETURN_IF_DONE("After target has been trimmed by all "
- "trimming primitives");
- /* set accumulator stencil bit for this primitive everywhere depth != far */
- glStencilFunc(GL_ALWAYS, 1 << accumBit, 0);
- glStencilOp(GL_KEEP, GL_ZERO, GL_REPLACE);
- glStencilMask(1 << accumBit);
- glDepthMask(0);
- glDepthFunc(GL_GREATER);
- glDisable(GL_LIGHTING);
- drawFarRect();
- glEnable(GL_LIGHTING);
- COPY_AND_RETURN_IF_DONE("After setting accumulator where depths != far");
- return(CONTINUE);
- }
- progressEnum drawProduct(int product, int accumBit)
- {
- struct product *p;
- p = &products[whichTree][product];
- glEnable(GL_CULL_FACE);
- if(p->frontFace)
- glCullFace(GL_BACK);
- else
- glCullFace(GL_FRONT);
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LESS);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_EQUAL, 1 << accumBit, 1 << accumBit);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- drawPrim(p->targetPrim);
- COPY_AND_RETURN_IF_DONE("After drawing target color and depth");
- return(CONTINUE);
- }
- void redrawCSG(void)
- {
- int i;
- int accumBit;
- int firstProduct;
- int lastProduct;
- whereSoFar = 0;
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glClear(GL_COLOR_BUFFER_BIT);
- /* Only have to do this if you're going to look at the stencil buffer */
- glClearStencil(0);
- glStencilMask((1 << stenSize) - 1);
- glClear(GL_STENCIL_BUFFER_BIT);
- glPushMatrix();
- drawXform(&globalXform, FALSE);
- firstProduct = 0;
- while(firstProduct != numProducts[whichTree]) {
-
- /*
- * set lastProduct so that accum bits for first to last fit in
- * stencil buffer minus bits needed for surface counting bits
- */
- lastProduct = firstProduct + (stenSize - 1) - 1;
- if(lastProduct >= numProducts[whichTree])
- lastProduct = numProducts[whichTree] - 1;
- if(firstProduct > 0) /* know depth is clear before 1st group */
- saveDepth();
- accumBit = 1; /* first available after counting bits */
- for(i = firstProduct; i <= lastProduct; i++)
- if(markProductPixels(i, accumBit++) == STOP)
- goto doneWithFrame;
- COPY_AND_GOTO_IF_DONE("After marking "inside" target accumulators");
- if(firstProduct > 0) /* know depth was clear before first group */
- restoreDepth();
- else {
- glDepthMask(GL_TRUE);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- accumBit = 1; /* first available after counting bits */
-
- for(i = firstProduct; i <= lastProduct; i++)
- if(drawProduct(i, accumBit++) == STOP)
- goto doneWithFrame;
- COPY_AND_GOTO_IF_DONE("After drawing all target colors and depths");
- firstProduct = lastProduct + 1;
- }
- if(showSurfaces) {
- glDisable(GL_STENCIL_TEST);
- glDepthMask(GL_FALSE);
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
- glEnable(GL_BLEND);
- magicTranspHack = 1;
- for(i = 0; i < numProducts[whichTree]; i++)
- {
- struct product *p;
- p = &products[whichTree][i];
- if(i == curPrim || !showOnlyCurrent)
- drawPrim(p->targetPrim);
- }
- magicTranspHack = 0;
- glDisable(GL_BLEND);
- }
- doneWithFrame:
- glPopMatrix();
- copyInterest();
- glutSwapBuffers();
- }
- enum trackballModeEnum {
- ROTATE,
- TRANSLATEXY,
- TRANSLATEZ,
- SCALEX,
- SCALEY,
- SCALEZ
- } trackballMode = ROTATE;
- /* ARGSUSED1 */
- void special(int thing, int x, int y)
- {
- switch(thing) {
- case GLUT_KEY_F1:
- prims[curPrim].draw = drawBox;
- glutPostRedisplay();
- break;
- case GLUT_KEY_F2:
- prims[curPrim].draw = drawCylinder;
- glutPostRedisplay();
- break;
- case GLUT_KEY_F3:
- prims[curPrim].draw = drawCone;
- glutPostRedisplay();
- break;
- case GLUT_KEY_F4:
- prims[curPrim].draw = drawSphere;
- glutPostRedisplay();
- break;
- }
- }
- /* ARGSUSED1 */
- void keyboard(unsigned char key, int x, int y)
- {
- switch(key)
- {
- case '1':
- case '2':
- case '3':
- case '4':
- whichTree = key - '1';
- glutPostRedisplay();
- break;
- case 'r':
- trackballMode = ROTATE;
- break;
- case 't':
- trackballMode = TRANSLATEXY;
- break;
- case 'T':
- trackballMode = TRANSLATEZ;
- break;
- case 'x':
- trackballMode = SCALEX;
- break;
- case 'y':
- trackballMode = SCALEY;
- break;
- case 'z':
- trackballMode = SCALEZ;
- break;
- case 'q': case 'Q': case ' 33':
- exit(0);
- break;
- case '<': case ',':
- if(curXform != &globalXform)
- {
- curPrim = (curPrim - 1 + numPrims) % numPrims;
- curXform = &prims[curPrim].xform;
- printf("Manipulating transformation for object %dn", curPrim);
- }
- else
- {
- printf("Have to toggle out of global mode firstn");
- }
- glutPostRedisplay();
- break;
- case '>': case '.':
- if(curXform != &globalXform)
- {
- curPrim = (curPrim + 1) % numPrims;
- curXform = &prims[curPrim].xform;
- printf("Manipulating transformation for object %dn", curPrim);
- }
- else
- {
- printf("Have to toggle out of global mode firstn");
- }
- break;
- case 'g':
- if(curXform == &globalXform){
- curXform = &prims[curPrim].xform;
- printf("Manipulating transformation for object %dn", curPrim);
- }else{
- curXform = &globalXform;
- printf("Manipulating global transformationn");
- }
- break;
- case '+': case '=':
- whereToStop++;
- glutPostRedisplay();
- break;
- case '-': case '_':
- whereToStop--;
- glutPostRedisplay();
- break;
- case 's':
- glutPostRedisplay();
- showSurfaces = !showSurfaces;
- break;
- case 'c':
- doCSG = ! doCSG;
- if(doCSG)
- glutDisplayFunc(redrawCSG);
- else
- glutDisplayFunc(redrawNoCSG);
- glutPostRedisplay();
- break;
- case ' ':
- showOnlyCurrent = !showOnlyCurrent;
- glutPostRedisplay();
- break;
- }
- }
- static int ox, oy;
- /* ARGSUSED */
- void button(int b, int state, int x, int y)
- {
- ox = x;
- oy = y;
- }
- void motion(int x, int y)
- {
- int dx, dy;
- dx = x - ox;
- dy = y - oy;
- ox = x;
- oy = y;
- switch(trackballMode) {
- case ROTATE:
- rotateTrackball(dx, dy, curXform->rotation);
- break;
- case SCALEX:
- curXform->scale[0] += (dx + dy) / 40.0f;
- if(curXform->scale[0] < 1/40.0)
- curXform->scale[0] = 1/40.0;
- break;
- case SCALEY:
- curXform->scale[1] += (dx + dy) / 40.0f;
- if(curXform->scale[1] < 1/40.0)
- curXform->scale[1] = 1/40.0;
- break;
- case SCALEZ:
- curXform->scale[2] += (dx + dy) / 40.0f;
- if(curXform->scale[2] < 1/40.0)
- curXform->scale[2] = 1/40.0;
- break;
- case TRANSLATEXY:
- curXform->translation[0] += dx / 40.0f;
- curXform->translation[1] -= dy / 40.0f;
- break;
- case TRANSLATEZ:
- curXform->translation[2] += (dx + dy) / 40.0f;
- break;
- }
- glutPostRedisplay();
- }
- void reshape(int width, int height)
- {
- glViewport(0, 0, width, height);
- winWidth = width;
- winHeight = height;
- resizeBuffers();
- glutPostRedisplay();
- }
- int mainMenu;
- void mainMenuFunc(int choice)
- {
- switch(choice)
- {
- case 1:
- doCSG = !doCSG;
- if(doCSG) {
- printf("CSG expression onn");
- glutDisplayFunc(redrawCSG);
- glutChangeToMenuEntry(1, "Turn off CSG", 0);
- }
- else {
- printf("CSG expression offn");
- glutDisplayFunc(redrawNoCSG);
- glutChangeToMenuEntry(1, "Turn on CSG", 0);
- }
- glutPostRedisplay();
- break;
- case 2:
- showSurfaces = !showSurfaces;
- if(showSurfaces) {
- printf("Transparent surfaces onn");
- glutChangeToMenuEntry(2, "(s) Don't show objects transparent in CSG", 2);
- }
- else {
- printf("Transparent surfaces offn");
- glutChangeToMenuEntry(2, "(s) Show objects transparent in CSG", 2);
- }
- glutPostRedisplay();
- break;
- }
- }
- void interestBufferFunc(int data)
- {
- char *s;
- bufferInterest = data;
- switch(data) {
- case COLOR:
- s = "color";
- break;
- case STENCILVALUES:
- s = "stencil values";
- break;
- case STENCILPLANES:
- s = "individual stencil plane converage";
- break;
- case DEPTH:
- s = "depth";
- break;
- }
- printf("Now displaying %s datan", s);
- glutPostRedisplay();
- }
- void csgMenuFunc(int data)
- {
- whichTree = data;
- glutPostRedisplay();
- }
- void whichObjectFunc(int data)
- {
- switch(data)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- curPrim = data;
- curXform = &prims[curPrim].xform;
- printf("Editing object %dn", data);
- break;
- case 4:
- curXform = &globalXform;
- printf("Editing global transformation %dn", data);
- break;
- }
- }
- void morphMenuFunc(int data)
- {
- switch(data) {
- case 0:
- prims[curPrim].draw = drawBox;
- glutPostRedisplay();
- break;
- case 1:
- prims[curPrim].draw = drawCylinder;
- glutPostRedisplay();
- break;
- case 2:
- prims[curPrim].draw = drawCone;
- glutPostRedisplay();
- break;
- case 3:
- prims[curPrim].draw = drawSphere;
- glutPostRedisplay();
- break;
- }
- }
- void helpFakeFunc(int d)
- {
- }
- int main(int argc, char **argv)
- {
- int bufferMenu;
- int csgMenu;
- int whichObjectMenu;
- int morphMenu;
- int helpFakeMenu;
- glutInitWindowSize(512,512);
- glutInit(&argc, argv);
- glutInitDisplayString("samples stencil>=3 rgb double depth");
- /* glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH|GLUT_RGBA); */
- (void)glutCreateWindow("csg using stencil");
- glutDisplayFunc(redrawNoCSG);
- glutKeyboardFunc(keyboard);
- glutSpecialFunc(special);
- glutMotionFunc(motion);
- glutMouseFunc(button);
- glutReshapeFunc(reshape);
- glGetIntegerv(GL_STENCIL_BITS, &stenSize);
- printf("%d bits of stencil available in this visualn", stenSize);
- printf("Hit 'S' to turn stencil on/offn");
- bufferMenu = glutCreateMenu(interestBufferFunc);
- glutAddMenuEntry("Color data", COLOR);
- glutAddMenuEntry("Stencil values", STENCILVALUES);
- glutAddMenuEntry("Coverage in each stencil plane", STENCILPLANES);
- glutAddMenuEntry("Depth data", DEPTH);
- csgMenu = glutCreateMenu(csgMenuFunc);
- glutAddMenuEntry("(1) obj 1 MINUS obj 2", 0);
- glutAddMenuEntry("(2) obj 2 MINUS obj 1", 1);
- glutAddMenuEntry("(3) obj 1 AND obj 2", 2);
- glutAddMenuEntry("(4) (obj 1 AND obj 2) MINUS (obj 3 or obj 4)", 3);
- whichObjectMenu = glutCreateMenu(whichObjectFunc);
- glutAddMenuEntry("Object 1 (blue)", 0);
- glutAddMenuEntry("Object 2 (peach)", 1);
- glutAddMenuEntry("Object 3 (green)", 2);
- glutAddMenuEntry("Object 4 (purple)", 3);
- glutAddMenuEntry("(g) Toggle between global and local", 4);
- morphMenu = glutCreateMenu(morphMenuFunc);
- glutAddMenuEntry("(F1) Box", 0);
- glutAddMenuEntry("(F2) Cylinder", 1);
- glutAddMenuEntry("(F3) Cone", 2);
- glutAddMenuEntry("(F4) Sphere", 3);
- helpFakeMenu = glutCreateMenu(helpFakeFunc);
- glutAddMenuEntry("Click the left mouse button and drag to manipulaten", 0);
- glutAddMenuEntry("Push 'r' to rotate like a trackballn", 0);
- glutAddMenuEntry("Push 't' to translate in the X-Y planen", 0);
- glutAddMenuEntry("Push 'T' to translate in the Z axisn", 0);
- glutAddMenuEntry("Push 'X' to scale in Xn", 0);
- glutAddMenuEntry("Push 'X' to scale in Yn", 0);
- glutAddMenuEntry("Push 'Z' to scale in Zn", 0);
- mainMenu = glutCreateMenu(mainMenuFunc);
- glutAddMenuEntry("(c) Turn on CSG", 1);
- glutAddMenuEntry("(s) Show objects transparent in CSG", 2);
- glutAddSubMenu("Buffer of interest", bufferMenu);
- glutAddSubMenu("Which CSG expression", csgMenu);
- glutAddSubMenu("Object for manipulation", whichObjectMenu);
- glutAddSubMenu("Turn current object into...", morphMenu);
- glutAddSubMenu("Help with moving and rotating:", helpFakeMenu);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- init();
- glutMainLoop();
- return 0;
- }