/* haloed.c - by Tom McReynolds, SGI */ /* Draw haloed lines. */ #include #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., 16, 16); } enum {FILL, WIRE, HALO, OFFSET_HALO, BACKFACE_HALO, TOGGLE}; int rendermode = FILL; void (*curobj)(void) = cone; void menu(int mode) { if(mode == TOGGLE) if(curobj == cone) curobj = torus; else curobj = cone; else rendermode = mode; 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; } GLfloat viewangle; 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 FILL: curobj(); break; case WIRE: glDisable(GL_DEPTH_TEST); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glLineWidth(3.f); curobj(); glLineWidth(1.f); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_DEPTH_TEST); break; case HALO: /* draw wide lines into depth buffer */ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glLineWidth(9.f); curobj(); /* draw narrow lines into color with depth test on */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glLineWidth(3.f); glDepthFunc(GL_LEQUAL); curobj(); glDepthFunc(GL_LESS); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); break; case OFFSET_HALO: /* draw wide lines into depth buffer */ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glLineWidth(9.f); curobj(); /* draw narrow lines into color with depth test on */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glLineWidth(3.f); #if GL_EXT_polygon_offset glEnable(GL_POLYGON_OFFSET_EXT); glPolygonOffsetEXT(-.5f, -.02f); #endif glDepthFunc(GL_LEQUAL); curobj(); glDepthFunc(GL_LESS); #if GL_EXT_polygon_offset glDisable(GL_POLYGON_OFFSET_EXT); #endif glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glLineWidth(1.f); break; case BACKFACE_HALO: /* cheat: only works on single non-intersecting obj */ /* draw wide lines into depth buffer */ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glLineWidth(3.f); curobj(); /* mask out borders of objects with wide gray lines */ glCullFace(GL_BACK); glLineWidth(9.f); glDisable(GL_LIGHTING); glColor3f(.7f, .7f, .7f); curobj(); /* draw front face narrow lines without depth test */ glEnable(GL_LIGHTING); glLineWidth(3.f); glDisable(GL_DEPTH_TEST); curobj(); /* clean up */ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glLineWidth(1.f); break; } glPopMatrix(); glutSwapBuffers(); if(glGetError()) printf("oops! Bad gl command!\n"); } /* 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("haloed lines"); glutDisplayFunc(redraw); glutKeyboardFunc(key); glutSpecialFunc(special); glutCreateMenu(menu); glutAddMenuEntry("Filled Object", FILL); glutAddMenuEntry("Wireframe", WIRE); glutAddMenuEntry("Haloed Wireframe", HALO); glutAddMenuEntry("Pgon Offset Haloed Wireframe", OFFSET_HALO); glutAddMenuEntry("Backface Haloed Wireframe", BACKFACE_HALO); glutAddMenuEntry("Toggle Object", TOGGLE); glutAttachMenu(GLUT_RIGHT_BUTTON); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glClearColor(.7f, .7f, .7f, .7f); 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., 25., 8, 1); gluCylinder(cone, 25., 0., 60., 8, 8); 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. */ }