Depth Sorting Polygons
I am using a lot of blended (semitransparent) polygons and thus need to draw them from back to front for my scene to appear correct. I am having a lot of trouble getting this to work, basically my code goes like this:
glViewport(...);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(...);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
gluLookAt([CameraPosition getVectorX], [CameraPosition getVectorY], [CameraPosition getVectorZ], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(cameraRotation, 0.0, 1.0, 0.0);
/* Draw primitives... */
/* Then, to get primitive distances: */
GLdouble m[16];
glGetDoublev(GL_MODELVIEW_MATRIX, m);
/* For each vertex in the primitive: */
matrixVertexMultiply(m, &x, &y, &z);
/* Matrix multiply code: */
 (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z
/* Multiplies hte vertex (x,y,z) by the matrix pointed to by sourceMatrix. */
{
float a11 = sourceMatrix[ 0], a12 = sourceMatrix[ 1], a13 = sourceMatrix[ 2], a14 = sourceMatrix[ 3];
float a21 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a23 = sourceMatrix[ 6], a24 = sourceMatrix[ 7];
float a31 = sourceMatrix[ 8], a32 = sourceMatrix[ 9], a33 = sourceMatrix[10], a34 = sourceMatrix[11];
float tx = *x;
float ty = *y;
float tz = *z;
*x = a11 * tx + a12 * ty + a13 * tz + a14;
*y = a21 * tx + a22 * ty + a23 * tz + a24;
*z = a31 * tx + a32 * ty + a33 * tz + a34;
} /*  (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z */
This should give me where each transformed point is (given the current MODELVIEW matrix)  I then calculate the distance from this transformed point to my 'camera' location (using sqrt((x2x1)^2 + (y2y1)^2 + (z2z1)^2)) to get the distance from the 'camera' for each point. The distances of all the points in a primitive are then averaged to get an average distance to the primitive. This is the value that I am depth sorting with but I keep getting unexpected results depending on the rotations being used (sometimes it draws in the correct order and looks fine as in the case of xaxis rotations but it does not draw in the correct order for other rotations). What am I missing? Do I need to multiply the camera location by the current matrix as well? Do I need to multiply the projection matrix somewhere?
Basically, given a list of vertices in a primitive, a 'camera' location (as defined by gluLookAt), and the current transformation matrices, I need to compute the distance to the 'camera'. Any suggestions as to what I'm doing wrong or a better way of doing this would be greatly appreciated. Is there a good depth sort tutorial or some nice example code that resembles what I need out there? Thnaks in advance,
thaeez
glViewport(...);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(...);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
gluLookAt([CameraPosition getVectorX], [CameraPosition getVectorY], [CameraPosition getVectorZ], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(cameraRotation, 0.0, 1.0, 0.0);
/* Draw primitives... */
/* Then, to get primitive distances: */
GLdouble m[16];
glGetDoublev(GL_MODELVIEW_MATRIX, m);
/* For each vertex in the primitive: */
matrixVertexMultiply(m, &x, &y, &z);
/* Matrix multiply code: */
 (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z
/* Multiplies hte vertex (x,y,z) by the matrix pointed to by sourceMatrix. */
{
float a11 = sourceMatrix[ 0], a12 = sourceMatrix[ 1], a13 = sourceMatrix[ 2], a14 = sourceMatrix[ 3];
float a21 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a23 = sourceMatrix[ 6], a24 = sourceMatrix[ 7];
float a31 = sourceMatrix[ 8], a32 = sourceMatrix[ 9], a33 = sourceMatrix[10], a34 = sourceMatrix[11];
float tx = *x;
float ty = *y;
float tz = *z;
*x = a11 * tx + a12 * ty + a13 * tz + a14;
*y = a21 * tx + a22 * ty + a23 * tz + a24;
*z = a31 * tx + a32 * ty + a33 * tz + a34;
} /*  (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z */
This should give me where each transformed point is (given the current MODELVIEW matrix)  I then calculate the distance from this transformed point to my 'camera' location (using sqrt((x2x1)^2 + (y2y1)^2 + (z2z1)^2)) to get the distance from the 'camera' for each point. The distances of all the points in a primitive are then averaged to get an average distance to the primitive. This is the value that I am depth sorting with but I keep getting unexpected results depending on the rotations being used (sometimes it draws in the correct order and looks fine as in the case of xaxis rotations but it does not draw in the correct order for other rotations). What am I missing? Do I need to multiply the camera location by the current matrix as well? Do I need to multiply the projection matrix somewhere?
Basically, given a list of vertices in a primitive, a 'camera' location (as defined by gluLookAt), and the current transformation matrices, I need to compute the distance to the 'camera'. Any suggestions as to what I'm doing wrong or a better way of doing this would be greatly appreciated. Is there a good depth sort tutorial or some nice example code that resembles what I need out there? Thnaks in advance,
thaeez
It really depends on the way your scene manages polygons, but when I have a lot of blended polygons, I start by drawing all the opaque polygons, then I disable writting to the depth buffer before drawing the blended polygons. That way, depth sorting is not necessary at all.
on another note, for your problem, when you get the modelview matrix, you get a trasposed matrix. So, you should use a transposed matrix ( with GL_ARB_transpose_matrix ), or change
To:
Just my 2 cents.
on another note, for your problem, when you get the modelview matrix, you get a trasposed matrix. So, you should use a transposed matrix ( with GL_ARB_transpose_matrix ), or change
Code:
float a11 = sourceMatrix[ 0], a12 = sourceMatrix[ 1], a13 = sourceMatrix[ 2], a14 = sourceMatrix[ 3];
float a21 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a23 = sourceMatrix[ 6], a24 = sourceMatrix[ 7];
float a31 = sourceMatrix[ 8], a32 = sourceMatrix[ 9], a33 = sourceMatrix[10], a34 = sourceMatrix[11];
To:
Code:
float a11 = sourceMatrix[ 0], a21 = sourceMatrix[ 1], a31 = sourceMatrix[ 2], a41 = sourceMatrix[ 3];
float a12 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a32 = sourceMatrix[ 6], a42 = sourceMatrix[ 7];
float a13 = sourceMatrix[ 8], a23 = sourceMatrix[ 9], a33 = sourceMatrix[10], a43 = sourceMatrix[11];
Just my 2 cents.
 Sohta
Thanks for the help Sohta, your suggestion fixed my problem and surely saved me many, many hours  I can now rotate on any axis and correctly determine draw order (kind of...). The problem that I am still having is when a number of primitives are lined up horizontally or vertically and the rotations are such that an entire row of primitives have the same Z value after multiplying their points through the current MODELVIEW matrix. In this situation, the top to bottom (when dealing with a vertical row) or the left to right (when dealing with a horizontal row) draw order is not always correct  they all have the same Z value and I need to draw the furthest from the camera, not simply the furthest Z distance. Anyways, to get this value, it's still not really clear to me if I need to consider:
a: MODELVIEW matrix ONLY...
b: PROJECTION & MODELVIEW matrix (multiply point through projection, then through modelview matrix)
c: MODELVIEW & PROJECTION matrix (multiply point through modelview, then through projection matrix)
or
d: none of the above: specify please _______________. =)
Again, I am using:
gluPerspective(); /* Set up a perspective 3D view */
gluLookAt(); /* Position the camera. */
When depth sorting, do you guys use averageZ, minZ, or maxZ  what are the pros and cons to using these different methods. How do I compute the distance form the transformed point to 'camera' point as specified in gluLookAt()? Thanks again for the help, and sorry for so many questions...
Oh yeah, Sohta, you were suggesting that depth sorting is not necessary if you draw opaque polys first, then blended ones with the depth buffer read only. This works most of the time, but draw order is still important when considering many semitransparent polygons and a readonly depth buffer (red glass in front of blue glass looks different that the opposite combination). Of course, one can remedy this by using an additive blending function, but in my humble opinion, these blending functions only look realistic when used with special effects such as explosions, fire, etc. This leaves us with a lot of manual depth sorting to do (all polys that use blending...) if we want the transparent polys behind other transparent polys to be drawn correctly.
Thanks again and sorry for the long reply,
thaeez
a: MODELVIEW matrix ONLY...
b: PROJECTION & MODELVIEW matrix (multiply point through projection, then through modelview matrix)
c: MODELVIEW & PROJECTION matrix (multiply point through modelview, then through projection matrix)
or
d: none of the above: specify please _______________. =)
Again, I am using:
gluPerspective(); /* Set up a perspective 3D view */
gluLookAt(); /* Position the camera. */
When depth sorting, do you guys use averageZ, minZ, or maxZ  what are the pros and cons to using these different methods. How do I compute the distance form the transformed point to 'camera' point as specified in gluLookAt()? Thanks again for the help, and sorry for so many questions...
Oh yeah, Sohta, you were suggesting that depth sorting is not necessary if you draw opaque polys first, then blended ones with the depth buffer read only. This works most of the time, but draw order is still important when considering many semitransparent polygons and a readonly depth buffer (red glass in front of blue glass looks different that the opposite combination). Of course, one can remedy this by using an additive blending function, but in my humble opinion, these blending functions only look realistic when used with special effects such as explosions, fire, etc. This leaves us with a lot of manual depth sorting to do (all polys that use blending...) if we want the transparent polys behind other transparent polys to be drawn correctly.
Thanks again and sorry for the long reply,
thaeez
Possibly Related Threads...
Thread:  Author  Replies:  Views:  Last Post  
SLOW performance drawing multiple polygons per frame with stencil buffer  clam61  7  9,749 
Apr 27, 2013 11:53 AM Last Post: clam61 

bad depth sorting in Cocoa OpenGL  aldermoore  2  5,922 
Dec 30, 2008 03:07 PM Last Post: ThemsAllTook 

Depthfirst sorting  cecilkorik  8  7,147 
Oct 18, 2007 12:26 PM Last Post: OneSadCookie 

antialiasing polygons  honkFactory  37  23,450 
Apr 3, 2006 09:19 AM Last Post: akb825 

n00b question: getting rid of lines along edges of polygons  Andrew  2  3,838 
Jun 5, 2005 05:57 PM Last Post: Andrew 