/* silhouette.c - by Tom McReynolds, SGI */ /* Doing Silhouette Edges with stencil */ #include #include #include enum { CONE = 1 }; /* Draw a cone */ void cone(void) { glPushMatrix(); glTranslatef(0.f, 0.f, -30.f); glCallList(CONE); glPopMatrix(); } /* Draw a torus */ void torus(void) { glutSolidTorus(10., 20., 20, 20); } enum { SIL, OBJ, SIL_AND_OBJ, TOGGLE }; int rendermode = OBJ; void (*curobj) (void) = cone; void menu(int mode) { switch (mode) { case SIL: case OBJ: case SIL_AND_OBJ: rendermode = mode; break; case TOGGLE: if (curobj == cone) curobj = torus; else curobj = cone; break; } glutPostRedisplay(); } int winWidth = 512; int winHeight = 512; /* used to get current width and height of viewport */ void reshape(int wid, int ht) { glViewport(0, 0, wid, ht); winWidth = wid; winHeight = ht; glutPostRedisplay(); } GLfloat viewangle; void drawsilhouette(void) { int i; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glDisable(GL_DEPTH_TEST); /* so the depth buffer doesn't change */ for (i = -1; i < 2; i += 2) { /* set stencil around object */ glViewport(i, 0, winWidth + i, winHeight); curobj(); } for (i = -1; i < 2; i += 2) { glViewport(0, i, winWidth, winHeight + i); curobj(); } /* cut out stencil where object is */ glViewport(0, 0, winWidth, winHeight); glStencilFunc(GL_ALWAYS, 0, 0); curobj(); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 1); glDisable(GL_LIGHTING); glColor3f(1.f, 0.f, 0.f); /* draw silhouette red */ glRotatef(-viewangle, 0.f, 1.f, 0.f); glRecti(-50, -50, 50, 50); glRotatef(viewangle, 0.f, 1.f, 0.f); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); } void redraw(void) { /* clear stencil each time */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glPushMatrix(); glRotatef(viewangle, 0.f, 1.f, 0.f); switch (rendermode) { case SIL: drawsilhouette(); break; case SIL_AND_OBJ: drawsilhouette(); curobj(); break; case OBJ: curobj(); break; } glPopMatrix(); glutSwapBuffers(); } /* animate scene by rotating */ enum { ANIM_LEFT, ANIM_RIGHT }; int animDirection = ANIM_LEFT; void anim(void) { if (animDirection == ANIM_LEFT) viewangle -= 1.f; else viewangle += 1.f; glutPostRedisplay(); } /* ARGSUSED1 */ /* special keys, like array and F keys */ void special(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: glutIdleFunc(anim); animDirection = ANIM_LEFT; break; case GLUT_KEY_RIGHT: glutIdleFunc(anim); animDirection = ANIM_RIGHT; break; case GLUT_KEY_UP: case GLUT_KEY_DOWN: glutIdleFunc(0); break; } } /* ARGSUSED1 */ void key(unsigned char key, int x, int y) { switch (key) { case 'a': viewangle -= 10.f; glutPostRedisplay(); break; case 's': viewangle += 10.f; glutPostRedisplay(); break; case '\033': exit(0); } } int picked_object; int xpos = 0, ypos = 0; int newxpos, newypos; int startx, starty; int main(int argc, char **argv) { static GLfloat lightpos[] = {25.f, 50.f, -50.f, 1.f}; static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f}; GLUquadricObj *cone, *base; glutInit(&argc, argv); glutInitWindowSize(512, 512); glutInitDisplayMode(GLUT_STENCIL | GLUT_DEPTH | GLUT_DOUBLE); (void) glutCreateWindow("silhouette edges"); glutDisplayFunc(redraw); glutKeyboardFunc(key); glutSpecialFunc(special); glutReshapeFunc(reshape); glutCreateMenu(menu); glutAddMenuEntry("Object", OBJ); glutAddMenuEntry("Silhouette Only", SIL); glutAddMenuEntry("Object and Silhouette", SIL_AND_OBJ); glutAddMenuEntry("Toggle Object", TOGGLE); glutAttachMenu(GLUT_RIGHT_BUTTON); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightpos); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); /* make display list for cone; for efficiency */ glNewList(CONE, GL_COMPILE); cone = gluNewQuadric(); base = gluNewQuadric(); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, cone_mat); gluQuadricOrientation(base, GLU_INSIDE); gluDisk(base, 0., 15., 32, 1); gluCylinder(cone, 15., 0., 60., 32, 32); gluDeleteQuadric(cone); gluDeleteQuadric(base); glEndList(); glMatrixMode(GL_PROJECTION); glOrtho(-50., 50., -50., 50., -50., 50.); glMatrixMode(GL_MODELVIEW); glutMainLoop(); return 0; /* ANSI C requires main to return int. */ }