Path: cantaloupe.srv.cs.cmu.edu!ph From: ph+@cs.cmu.edu (Paul Heckbert) Newsgroups: comp.sys.sgi.graphics Subject: edge highlighting, stenedge.c (5/5) Date: 22 Nov 1996 21:38:19 GMT Organization: School of Computer Science, Carnegie Mellon /* Re: hidden line removal with filled, outlined polygons from http://www.sgi.com/Archive/comp.sys.sgi/graphics/1994/Jan/0216.html posted to comp.sys.sgi.graphics Kurt Akeley (kurt@cashew.asd.sgi.com) 20 Jan 1994 01:04:55 GMT A three-pass algorithm using the stencil buffer gets very nice results. Here's the Iris GL code. I have OpenGL code too if anyone is interested. cc -O2 -mips2 -o stenedge stenedge.c -lgl */ /**************************************************************************** Copyright 1991 by Silicon Graphics Incorporated, Mountain View, California. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Silicon Graphics not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ****************************************************************************/ /* * Kurt Akeley * December 1992 * * Use stencil to draw hidden-line and outlined images * Depress the middle mouse button to remove hidden lines * (by filling the cube's faces with background color). * Depress the left mouse button to outline the shaded polygons * (by filling the cube's faces with shaded color). * Depress the escape key to exit. * * Notes: * * 1. All lines are rendered single width * * 2. Exact regeneration of z values is not required, so * there are no dropouts. * * 3. Using the INVERT stencil operation allows the stencil * bits to be set and cleared using the same stencil mode. * As a result, only two stencil mode changes are required * per quadrilateral, rather than the three that would be * required otherwise. This improves the performance of * the hidden line loop substantially. */ #include #include #include #define MAXQUAD 6 #define LINECOLOR 0xffffffff #define BACKCOLOR 0 typedef float Vertex[4]; typedef Vertex Quad[5]; /* data to define the six faces of a cube */ Quad cubequads[MAXQUAD] = { 0,0,0,1, .8,0,0,1, .8,.8,0,1, 0,.8,0,1, 0,0,-1,0, 0,0,.8,1, .8,0,.8,1, .8,.8,.8,1, 0,.8,.8,1, 0,0,1,0, 0,0,0,1, .8,0,0,1, .8,0,.8,1, 0,0,.8,1, 0,-1,0,0, 0,.8,0,1, .8,.8,0,1, .8,.8,.8,1, 0,.8,.8,1, 0,1,0,0, 0,0,0,1, 0,0,.8,1, 0,.8,.8,1, 0,.8,0,1, -1,0,0,0, .8,0,0,1, .8,0,.8,1, .8,.8,.8,1, .8,.8,0,1, 1,0,0,0 }; /* global variables */ Quad* quads; float nullarray[1] = {LMNULL}; int dims = 2; /* routine declarations */ void addquad(int index, float x, float y, float z, Quad quad); void fill(Quad quad); void outline(Quad quad); main(int argc, char** argv) { int i; int leftmouse; int middlemouse; short dev,val; int x,y,z; int index; int totalquads; /* check for required capabilities */ if (getgdesc(GD_BITS_STENCIL) < 1) { fprintf(stderr,"stencil capability required and not present. abort\n"); exit(1); } /* read arguments */ if (argc > 1) dims = atoi(argv[1]); printf("dimensions = %d\n", dims); /* initialize graphics */ winopen("hidden"); RGBmode(); doublebuffer(); stensize(1); gconfig(); subpixel(TRUE); mmode(MVIEWING); perspective(900,1.0,0.5,5.0); translate(0.0,0.0,-2.2); lsetdepth(getgdesc(GD_ZMAX),0); /* I like clearing z to zero */ zfunction(ZF_GEQUAL); zbuffer(TRUE); qdevice(ESCKEY); qdevice(LEFTMOUSE); qdevice(MIDDLEMOUSE); swritemask(1); sclear(0); lmdef(DEFLMODEL,1,0,nullarray); lmdef(DEFLIGHT,1,0,nullarray); lmdef(DEFMATERIAL,1,0,nullarray); lmbind(LMODEL,1); lmbind(LIGHT0,1); /* create data */ totalquads = dims * dims * dims * MAXQUAD; quads = (Quad*)malloc(totalquads * sizeof(Quad)); index = 0; for (z=0; z < dims; z++) { for (y=0; y < dims; y++) { for (x=0; x < dims; x++) { for (i=0; i < MAXQUAD; i++) { addquad(index++,x,y,z,cubequads[i]); } } } } /* loop drawing the cubes */ while (1) { /* handle events */ while (qtest()) { dev = qread(&val); switch(dev) { case REDRAW: reshapeviewport(); sclear(0); break; case ESCKEY: exit(0); case LEFTMOUSE: leftmouse = val; break; case MIDDLEMOUSE: middlemouse = val; break; } } /* track the mouse */ pushmatrix(); rot(0.5 * getvaluator(MOUSEX),'y'); rot(0.5 * getvaluator(MOUSEY),'z'); /* clear the framebuffer and initialize the matrix */ czclear(BACKCOLOR,0); scale(1.5,1.5,1.5); translate(-0.5,-0.5,-0.5); scale(1.0/dims,1.0/dims,1.0/dims); if (leftmouse) { /* render outlined, shaded quadrilaterals */ cpack(0xff0000ff); stencil(TRUE,0,SF_ALWAYS,1,ST_INVERT,ST_INVERT,ST_INVERT); for (i=0; i