From: ulbricht@milton.u.washington.edu (Craig Ulbricht)
Subject: Re: z-buffering question
Organization: University of Washington
Distribution: usa
Date: Sun, 23 Aug 1992 20:10:32 GMT




Z-Buffering problems with overlaying lines on polygons!


    I've looked at this problem a few times in the past year and half and
I think I've FINALLY come up with a solution that is virtually free, 
both computationally and graphically.  There are other solutions out there
that require you to output your polygon data twice, so you loose the speed of
tmeshes.  I can't afford this due to large data sets I'm using.
This solution has the same visual results as the slower methods but 
with out the cost of speed.
    I've tried your idea before but have also failed.  This time, after
getting to know the perspective matrix, as sgi implements it, I found a
new way (to me atleast) to implement this same idea.  Frankly, this is a total
hack yet without absolute understanding, BUT, a hack that works. So, with
minimal explanation I'll just give you an example of what I came up with.  

    The following code is extracted from a C++ module which explains the
    comment notation and the creation of variables in the middle of the funtion.
    If your programming in C (not C++) it will be trivial to rearrange the 
    code so it will work.


    // get the current matrix mode so it can be preserved
    long om=getmmode();
    // set the matrix mode so you can opperate on the perspective matrix
    mmode(MPROJECTION);
    // get the matrix
    Matrix m;
    getmatrix(m);
    // get the "near-translation" entry of the matrix so it can be preserved
    float nn=m[3][2];
    // get the zbuffer range of your system
    long zmax=getgdesc(GD_ZMAX);
    long zmin=getgdesc(GD_ZMIN);
    // calculate the necessary world translation so when the data is 
    // scaled into the zbuffer it will be offset by ~one step in the zbuffer
    float nna=(float)((double)(view_win_info->far-view_win_info->near)/(double)(zmax-zmin));
    // subtract this from the near-translation entry
    float na=nn-nna;
    // put the new near-translation value into the matrix
    m[3][2]=na;
    // put the modified matrix back on the projection matrix stack
    loadmatrix(m);
    // reset the matrix mode
    // this step seems to be necessary for yet unknown reasons
    mmode(om);

    //
    // draw overlaying lines here
    //

    // set the matrix mode so you can opperate on the perspective matrix again
    mmode(MPROJECTION);
    // restore the original value of the near-translation entry
    m[3][2]=nn;
    // put the restored matrix back on the projection matrix stack
    loadmatrix(m);
    // and finally, restore the matrix mode
    mmode(om);



A few related comments.

Essentially, your just translating your data directly at your eye a little bit.
But, actually your moving your near-far clipping space without officially
telling the graphics engine.

This particular solution requires you to be working in multi matrix mode.

You may wish to play with a multiple of this step (nna), but I have found that
anything much larger than a factor of two causes lines to start coming 
through the scene where they should not.

I have also played with the zfunction() setting with no success.  I suspect
the geometry engine uses reduced floating point (floats with less significant
digits than your floating point data), so even though the z-test ZF_LEQUAL
should work, it doesn't.


Have fun!


Craig Ulbricht		
ulbricht@u.washington.edu
Cooperative for Forest-Systems Engineering
University of Washington