[comp.sys.sgi] Hollow Polygon implementation

ghelms@hellfire.csd.sgi.com (Gretchen Helms) (09/29/90)

The following is my implementation of Kurt Akeley's
article in the IRIS Universe regarding hollow polygons.
Object is a cube rather than a sphere as it takes less
code to implement.  Read the comments.

-----------------------mangle here-----------------------
/*  hollocube.c
    Sample code for creating an object made up of
    hollow polygons, as referenced in Kurt Akeley's
    article "The Hidden Charms of Z-Buffer", IRIS
    Universe issue number 11.
    Implemented by G. "Murdock" Helms, SGI, 8/2/90.
    Final revision 9/28/90.
    Compile with cc hollocube.c -o hollocube -lgl_s
    DOES NOT RUN ON NON-GT/GTXS AS PER ARTICLE.
*/

/*  include the usual libs */
#include "math.h"
#include "gl.h"
#include "device.h"

main()
{
  short attached;	/* usual queue stuff */
  short value;	
  int dev,val;
  float box[8][3];	/* this is needed for building the walls of the cube */
  float width;		/* shamelessly stolen from Intro to Graphics */
 
  foreground(); 		/* you can run Edge on this if you like */
  initialize(box, &width);	/* set up the vertices of the walls */

  drawscene(box, &width);	/* do drawing things */

  while (TRUE)  		/* loop until program is killed */
   {		
    while (qtest()||!attached)  /* do the usual queue stuff */
     {
      dev=qread(&value);
      if (dev==ESCKEY)
       {
       exit(0); 		/* can kill with esc key */
       }
      if (dev==REDRAW)
       {
       reshapeviewport();
       drawscene(box, &width); /* yes, you can move the window around */
       }
      else if (dev==INPUTCHANGE)
	   attached=value;
     }		/* end while qtest */
   }		/* end while true */
}  /* end main */


drawscene(box, width)		/* simple draw routine */
float box[8][3];
float width;
{

  czclear(0,0);
  drawbeam(box);
  swapbuffers();
  rot(10,'x');		/* need to rotate to show off qualities */
  czclear(0,0);		/* wasn't apparent if viewed straight-on */
  drawbeam(box);
  swapbuffers();
  rot(20,'y');
  czclear(0,0);
  drawbeam(box);
  swapbuffers();
}	/* end drawscene */


initbeam (x, y, z, point)	/* define the values for the vertices */
register float x, y, z, point[][3];
{
  point[0][0] = point[3][0] = point[4][0] = point[5][0]  = -x/2.0;
  point[1][0] = point[2][0] = point[6][0] = point[7][0]  = x/2.0;
  point[4][1] = point[5][1] = point[6][1] = point[7][1]  = -y/2.0;
  point[0][1] = point[1][1] = point[2][1] = point[3][1]  = y/2.0;
  point[2][2] = point[3][2] = point[5][2] = point[7][2]  = -z/2.0;
  point[0][2] = point[1][2] = point[4][2] = point[6][2]  = z/2.0;

}


/* What follows are a set of small functions that
 * follow the descriptions in the zbuffer article,
 * in the order they appear and are used.
 */


setzbuff() 			/* set up Zbuffer with reverse mapping */
{
  zbuffer(TRUE);
  lsetdepth(0x7fffff,0x000000);
  zfunction(ZF_GEQUAL);
}  /* end setzbuff */


disablp() 			/* disable polygon pixels */
{
  zbuffer(FALSE);
  backbuffer(FALSE);
  zdraw(TRUE);
  wmpack(0x800000);
  cpack(0x800000);
}  /* end disablep */


enablep() 			/* enable pixels on perimeter */
{
  cpack(0x000000);
  linewidth(2);
}  /* end enablep */


fillperim() 			/* fill poly (which actually only fills perim)*/
{
  zbuffer(TRUE);
  backbuffer(TRUE);
  zdraw(FALSE);
  wmpack(0xffffffff);
  cpack(0x000000FF);
}  /* end fill perim */


clearhollow() 			/* clear things up so no munging takes place */
{
  zbuffer(FALSE);
  backbuffer(FALSE);
  zdraw(TRUE);
  wmpack(0x800000);
  cpack(0x000000);
}  /* end clearhollow */


resethollow() 			/* reset states */
{
  zbuffer(TRUE);
  backbuffer(TRUE);
  zdraw(FALSE);
  wmpack(0xffffffff);
}  /* end resethollow */


drawbeam (point)		/* now let's draw. */
register float point[][3];
{
/* draw bottom facing polygon */
  disablp();
  bgnpolygon();
    v3f( point[4] );
    v3f( point[6] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  enablep();
  bgnclosedline();
    v3f( point[4] );
    v3f( point[6] );
    v3f( point[7] );
    v3f( point[5] );
  endclosedline();
  fillperim();
  bgnpolygon();
    v3f( point[4] );
    v3f( point[6] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[4] );
    v3f( point[6] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  resethollow();

	/*  draw left facing polygon	*/
  disablp();
  bgnpolygon();
    v3f( point[3] );
    v3f( point[0] );
    v3f( point[4] );
    v3f( point[5] );
  endpolygon();
  enablep();
  bgnclosedline();
    v3f( point[3] );
    v3f( point[0] );
    v3f( point[4] );
    v3f( point[5] );
  endclosedline();
  fillperim();
  bgnpolygon();
    v3f( point[3] );
    v3f( point[0] );
    v3f( point[4] );
    v3f( point[5] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[3] );
    v3f( point[0] );
    v3f( point[4] );
    v3f( point[5] );
  endpolygon();
  resethollow();

	/*  draw right facing polygon	*/
  disablp();
  bgnpolygon();
    v3f( point[2] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[7] );
  endpolygon();
  enablep();
  bgnclosedline();
    v3f( point[2] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[7] );
  endclosedline();
  fillperim();
  bgnpolygon();
    v3f( point[2] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[7] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[2] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[7] );
  endpolygon();
  resethollow();

	/*  draw top facing polygon	*/
  disablp();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[2] );
    v3f( point[3] );
  endpolygon();
  enablep();
  bgnclosedline();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[2] );
    v3f( point[3] );
  endclosedline();
  fillperim();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[2] );
    v3f( point[3] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[2] );
    v3f( point[3] );
  endpolygon();
  resethollow();

	/*  draw front facing polygon   */
  disablp();
  bgnpolygon();
    v3f( point[3] );
    v3f( point[2] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  enablep();
  bgnclosedline();
    v3f( point[3] );
    v3f( point[2] );
    v3f( point[7] );
    v3f( point[5] );
  endclosedline();
  fillperim();
  bgnpolygon();
    v3f( point[3] );
    v3f( point[2] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[2] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();
  resethollow();
  
	/*  draw back facing polygon	*/
  disablp();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[4] );
  endpolygon(); 
  enablep();
  bgnclosedline();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[4] );
  endclosedline();   
  fillperim();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[4] );
  endpolygon();
  clearhollow();
  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[4] );
  endpolygon();
  resethollow();

/* now we have to draw the cube solid inside all this stuff */
/* cuz if we don't it looks just like a normal wireframe!  */

  zfunction (ZF_GREATER);
  cpack(0x00000000);

  bgnpolygon();
    v3f( point[4] );
    v3f( point[6] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();

  bgnpolygon();
    v3f( point[3] );
    v3f( point[0] );
    v3f( point[4] );
    v3f( point[5] );
  endpolygon();

  bgnpolygon();
    v3f( point[2] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[7] );
  endpolygon();

  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[2] );
    v3f( point[3] );
  endpolygon();

  bgnpolygon();
    v3f( point[3] );
    v3f( point[2] );
    v3f( point[7] );
    v3f( point[5] );
  endpolygon();

  bgnpolygon();
    v3f( point[0] );
    v3f( point[1] );
    v3f( point[6] );
    v3f( point[4] );
  endpolygon();

}

initialize(box, width)		/* stuff the startup stuff here */
register float box[8][3];	/*  The eight vertices of the beam  */
register float *width;
{
    float aspect,x,y;		/* variables to perspective function */
    int gid;			
    register float height, length;  /* needed for square initialization */

    prefposition(0, XMAXSCREEN/3, 0, YMAXSCREEN/3); 
    gid = winopen ("Hollow Polygons");    /* get the window id and name it */

    RGBmode();			/* I like c3i calls, no map dependencies */
    lsetdepth(0,0x7fffff); 	/* initialize zbuffer near and far planes */
    overlay(2);
    doublebuffer();
    gconfig();			/* configure the hardware */

    shademodel (FLAT);
    qdevice (ESCKEY);		/* queue all these items */
    qdevice (REDRAW);
    qdevice (INPUTCHANGE);
    qenter (REDRAW, gid);

    x = (float) XMAXSCREEN;	/* set variables to perspective */
    y = (float) YMAXSCREEN;
    aspect = x/y;
    perspective (450,aspect, 0.1,100.0);  /* one viewing method */
    polarview (5.0, 0, 0, 0);	/* another viewing method */
    
    *width = 2.0; height = 2.0; length = 2.0;  /* static info for size of sqr */
    initbeam (*width, height, length, box);    /* init square */

    setzbuff();
}
-----------------------mangle here-----------------------

--
G. "Murdock" Helms				Is it so frightening	
Silicon Graphics				to have me at your shoulder?
Product Support Engineer			Thunder and lightning
ghelms@sgi.sgi.com				couldn't be bolder.