[comp.sys.sgi] polymode

hofmann@mira.tat.physik.uni-tuebingen.de (Bernhard Hofmann) (04/29/91)

I'm having trouble with polymode(PYM_HOLLOW) on our VGX with alpha bitplanes.
The following program doesn't quite do what I think it should do.
I think it should draw, when in polymode(PYM_HOLLOW), only the red corner
and the outlines of the cube. What happens on our machine is that after
switching to PYM_HOLLOW the red and the green corners appear with all
three lines leading to them as well as all other lines of the outline,
except the righthand one. All lines that are drawn appear either thicker
or thinner when switching from polymode(OYM_LINE) to polymode(PYM_HOLLOW).
When you run the below program, press l or L to see the Cube drawn with
polymode(PYM_LINE) or h or H to see it drawn with polymode(PYM_HOLLOW).
This is only a sample program demonstrating the effect and therefore not
very carefully written.

******************************************************************************
#include <stdio.h>
#include <gl/gl.h>
#include <gl/device.h>


short *s3(short x, short y, short z);


float corners[8][3] = {
  {-0.5,-0.5,-0.5},
  {-0.5,-0.5,0.5},
  {-0.5,0.5,0.5},
  {-0.5,0.5,-0.5},
  {0.5,-0.5,-0.5},
  {0.5,-0.5,0.5},
  {0.5,0.5,0.5},
  {0.5,0.5,-0.5}
};

short *s3(short x, short y, short z) {
  static short w[3];
  w[0]=x; w[1]=y; w[2]=z;
  return w;
}


main() {
  short value;

  foreground();
  keepaspect(1,1);
  winopen("Cube");
  zbuffer(TRUE);
  zclear();
  doublebuffer();
  mmode(MVIEWING);
  ortho(-1.1,1.1,-1.1,1.1,-1.1,1.1);
  RGBmode();
  stensize(8);  /*  for polymode(PYM_HOLLOW) */
  lookat(0,0,0,1,1.1,1.2,0);
  gconfig();
  sclear(0);

  qdevice(KEYBD);
  qdevice(ESCKEY);



  makeobj(1);

  zclear();
  c3s(s3(0,0,0));
  clear();
  c3s(s3(255,80,0));

  bgnpolygon();
  c3s(s3(255,0,0));
    v3f(corners[0]);
  c3s(s3(255,80,0));
    v3f(corners[1]);
    v3f(corners[2]);
    v3f(corners[3]);
  endpolygon();
  bgnpolygon();
    v3f(corners[4]);
    v3f(corners[5]);
  c3s(s3(0,255,0));
    v3f(corners[6]);
  c3s(s3(255,80,0));
    v3f(corners[7]);
  endpolygon();
  bgnpolygon();
  c3s(s3(255,0,0));
    v3f(corners[0]);
  c3s(s3(255,80,0));
    v3f(corners[1]);
    v3f(corners[5]);
    v3f(corners[4]);
  endpolygon();
  bgnpolygon();
  c3s(s3(255,0,0));
    v3f(corners[0]);
  c3s(s3(255,80,0));
    v3f(corners[3]);
    v3f(corners[7]);
    v3f(corners[4]);
  endpolygon();
  bgnpolygon();
    v3f(corners[2]);
    v3f(corners[1]);
    v3f(corners[5]);
  c3s(s3(0,255,0));
    v3f(corners[6]);
  c3s(s3(255,80,0));
  endpolygon();
  bgnpolygon();
    v3f(corners[2]);
    v3f(corners[3]);
    v3f(corners[7]);
  c3s(s3(0,255,0));
    v3f(corners[6]);
  endpolygon();
  closeobj();

  while(qread(&value) != ESCKEY) {
    switch (value) {
    case 'h':
    case 'H':
      polymode(PYM_HOLLOW);
      stencil(TRUE,1,SF_EQUAL,1,ST_KEEP,ST_KEEP,ST_KEEP);
      sclear(0);
      gconfig();
      callobj(1);
      swapbuffers();
      break;
    case 'l':
    case 'L':
      polymode(PYM_LINE);
      stencil(FALSE,1,SF_EQUAL,1,ST_KEEP,ST_KEEP,ST_KEEP);
      gconfig();
      callobj(1);
      swapbuffers();
      break;
    }
  }

  gexit();
}
******************************************************************************

Thank you very much for any hints.

Bernhard Hofmann

hofmann@mira.tat.physik.uni-tuebingen.de

kurt@cashew.asd.sgi.com (Kurt Akeley) (05/01/91)

Before wading through your code, I thought I'd just send out a copy of
a simple program that uses hollow polygons and the stencil buffer to
render hidden-line images.  Perhaps this will clear things up.

-- Kurt

------------------------------- cut here ------------------------------

/****************************************************************************
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
 *	3 October 1990
 *
 *	Use hollow polygons to draw an outlined cube.
 *	Depress the middle mouse button to remove hidden lines
 *	    (by filling the cube's faces with background color).
 *	Depress the escape key to exit.
 *
 *	Warning: works on VGX models only (requires stencil and polymode)
 *
 *	Important notes:
 *
 *	    1.	The stencil bitplanes are cleared only once, because
 *		they are used only to draw hollow polygons, and each
 *		polygon drawn leaves the stencil buffer in the state
 *		that it found it.
 *
 *	    2.	All polygons are first drawn hollow, then (conditionally)
 *		filled with background color.  Hence the zfunction must
 *		be GREATER, not GEQUAL (so that lines that are not hidden
 *		are not erased).  The code can be rewritten to first fill,
 *		then outline, in which case the zfunction should be GEQUAL
 *		(so that lines that are not hidden are drawn).
 *
 *	    3.	The two stencil() calls should not be required, but are
 *		in release 3.3.0.  I'm not sure whether the 3.3.2 release
 *		eliminates this requirement.
 */

#include <gl/gl.h>
#include <gl/device.h>
#include <stdio.h>

#define MAXQUAD 6

typedef struct {
    float x,y,z,w;
} Vertex;

typedef struct {
    Vertex v[4];
} Quad;

/* data to define the six faces of a cube */
Quad quads[MAXQUAD] = {
    { {0,0,0,1}, {1,0,0,1}, {1,1,0,1}, {0,1,0,1}, },
    { {0,0,1,1}, {1,0,1,1}, {1,1,1,1}, {0,1,1,1}, },
    { {0,0,0,1}, {1,0,0,1}, {1,0,1,1}, {0,0,1,1}, },
    { {0,1,0,1}, {1,1,0,1}, {1,1,1,1}, {0,1,1,1}, },
    { {0,0,0,1}, {0,0,1,1}, {0,1,1,1}, {0,1,0,1}, },
    { {1,0,0,1}, {1,0,1,1}, {1,1,1,1}, {1,1,0,1}, },
};

main(argc,argv)
char *argv[];
{
    int i;
    short dev,val;

    /* check for required capabilities */
    if (getgdesc(GD_BITS_STENCIL) < 1) {
	fprintf(stderr,"stencil capability required and not present.  abort\n");
	exit(1);
    }

    /* initialize graphics */
    winopen("hollow.vgx");
    RGBmode();
    doublebuffer();
    stensize(1);
    gconfig();
    subpixel(TRUE);
    mmode(MVIEWING);
    perspective(900,1.0,1.0,5.0);
    translate(0.0,0.0,-2.2);
    zbuffer(TRUE);
    lsetdepth(0x7fffff,0);
    zfunction(ZF_GREATER);
    qdevice(ESCKEY);
    qdevice(MIDDLEMOUSE);
    sclear(0);

    /* loop drawing the cube */
    while (1) {

	/* handle events */
	while (qtest()) {
	    dev = qread(&val);
	    switch(dev) {
		case REDRAW:
		    reshapeviewport();
		    break;
		case ESCKEY:
		    exit(0);
	    }
	}
	pushmatrix();

	/* track the mouse */
	rot(0.5 * getvaluator(MOUSEX),'y');
	rot(0.5 * getvaluator(MOUSEY),'z');
	translate(-0.5,-0.5,-0.5);
	czclear(0,0);

	/* draw the lines as hollow polygons */
	polymode(PYM_HOLLOW);
	stencil(TRUE,1,SF_EQUAL,1,ST_KEEP,ST_KEEP,ST_KEEP);
	cpack(0xffffff);
	for (i=0; i<MAXQUAD; i++)
	    drawfilled(&quads[i]);
	polymode(PYM_FILL);
	stencil(FALSE,0,0,0,0,0,0);

	/* erase hidden lines with filled polygons */
	if (getbutton(MIDDLEMOUSE)) {
	    cpack(0x000000);
	    for (i=0; i<MAXQUAD; i++)
		drawfilled(&quads[i]);
	}
	swapbuffers();
	popmatrix();
    }
}

drawfilled(quad)
Quad *quad;
{
    /* fill the polygon */
    bgnpolygon();
    v3f(&(quad->v[0]));
    v3f(&(quad->v[1]));
    v3f(&(quad->v[2]));
    v3f(&(quad->v[3]));
    endpolygon();
}