Am I using depth testing incorrectly or something?

Jones
Unregistered
 
Post: #1
I've been writing a frame of reference system similar to that from glTools. I do this to better understand how it works. It's pretty clear to me. There *are* some bits I still don't get, I can't seem to make the connection from the code to other references on 3D rotation.

Anyways I was testing some of the code when I noticed a bug. I could move the "camera" left and right but not forwards and backwards without trouble. At first I figured I'd messed up something when re-writing the code, and although mine was a little different (fixed some stuff in glTools that produced the wrong results...) the changes I had made were not the cause of the problem. (I tested.)

So then I try the same scene while using the original glTools, and *it* suffers the same problem too. Then I try a plain old:

Code:
case 119:    //    w, 0x0077
            trans += 0.1;
            glutPostRedisplay();
            break;

In my key detection code. After tapping 'w' a few times the box I'd been using did not seem to get closer or go farther away. I then held w down for maybe... 5 seconds. The box vanished! So I held 's' (backwards) down for another 5 seconds... The box was back!

So I thought to myself... "Hmm, maybe this is happening because the box *and* the camera are at 0.0, 0.0, 0.0 in 3D space". So I moved the box's starting point to [0.0, 0.0, -2.0] and started the project up again. The box started at the exact same spot. Eh? I tried moving with the 'w' key. This time it took roughly *twice* the time to make the box vanish as it did before. (So about 10 seconds.) Even though it had not appeared to be any farther away.

I then positioned the box at -3.0 on the Z axis. It didn't appear at startup, but holding the 'w key made the box appear after a certain amount of time.

You must understand that the box is not moving incrementally, it just comes and goes out of existence after I hold the 'w' or 's' keys for a certain amount of time.

I don't think it's my usage of gluPerspective that's wrong, but for reference here it is:

Code:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, width / height, 0.0, 100.0);

This is strange because in another project I do the exact same simple camera movement (the movement with simple position addition) and it works fine. The only difference in this case is that the object being rendered is *way* *way* bigger than a simple glut cube. (256.0 standard GL units by 256.0 GL units).

I have depth testing enabled, and clear depth is set to 1.0. Could it be breaking or something?

I'm kinda stumped, what could cause this?

Thanks!
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #2
You absolutely cannot set the zNear argument of gluPerspective to <= 0. Set it to 0.1f and that should help. Don't try to go any smaller than that.
Quote this message in a reply
Jones
Unregistered
 
Post: #3
Frogblast Wrote:You absolutely cannot set the zNear argument of gluPerspective to <= 0. Set it to 0.1f and that should help. Don't try to go any smaller than that.

I'll try it and see if it helps. Could you explain why this is, maybe?

Thanks!

EDIT:

Holy moly. For the first time I'm seeing things in *proper* not half-flat 3D. I thought that's the way it was meant to look for the longest time, but now I'm seeing the truth.

FrogBlast, you have liberated me. You have my eternal thanks. Smile Rasp
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #4
gluPerspective man page Wrote:Depth buffer precision is affected by the values specified for zNear and zFar. The greater the ratio of zFar to zNear is, the less effective the depth buffer will be at distinguishing between surfaces that are near each other. If r = zFar/zNear, roughly log2® bits of depth buffer precision are lost. Because r approaches infinity as zNear approaches 0, zNear must never be set to 0.
It's the way the perspective math works.
Quote this message in a reply
Jones
Unregistered
 
Post: #5
ThemsAllTook Wrote:It's the way the perspective math works.

The reason I was going it the other way was because in the OpenGL Super Bible they use glFrustum with 0.0 as the near value, which confused me.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
The glFrustum man page says the same thing. Sounds like an error on their part.
Quote this message in a reply
Jones
Unregistered
 
Post: #7
Ok, here's another bit of code I'm having trouble with. It's based on the glTools code for building a rotation matrix that rotates around an arbitrary axis.

I've rewritten in, and made some changes, but nothing that should affect the way it works. I've also added some notes to try and help myself understand it. I worked through it by hand and made myself a matrix with it that actually *did* perform a 36.0Ëš rotation successfully, but when I try to use it for camera math like GLT does it bugs out.

Code:
//    Do a rotation on an arbitrary axis.
    void mRotationA(float angle_deg, float x, float y, float z, float *matr) {
    
        //    Execute a check looking for a zero vector...
        if ((x == 0.0) && (y == 0.0) && (z == 0.0)) {
            mLoadIdentity(matr);
            return;
        }
    
        float mag;    //    Axis (vector) length.
        float sRes;    //    Result of sin operation.
        float cRes;    //    Result of cos operation.
                    //    Note on cos result: Placed in axis's main "value"
                    //    (for x that's the first, for y the second...) in
                    //    the matrix.
        float omc;    //    1.0 - cRes.
        
        //    Holders for the squares of x, y and z.
        float x_sq, y_sq, z_sq;
        
        //    These make the loop (of sorts) that connects that axis' in
        //    the matrice.
        //    How they should be placed:
        //        Starting in third column in the first row with Y, keep
        //        moving one axis type forward (so y... z... x sines) and
        //        moving one column forward, skipping the fourth.
        //    
        //        For negatives it's the same, but starts at z in the first
        //        row.
        float x_sRes, y_sRes, z_sRes;
        
        //    For storing multiplications.
        float x_by_y, y_by_z, z_by_x;
        
        //    Scale down the vector.
        mag = (float)sqrt(x*x + y*y + z*z);
        x /= mag;
        y /= mag;
        z /= mag;

        //    Get sin and cos values. (Uses radians, not degrees.)
        sRes = (float)sin((angle_deg * 3.14159265) / 180.0);
        cRes = (float)cos((angle_deg * 3.14159265) / 180.0);
        omc = 1.0f - cRes;
        
        //    Multiplication. (First squares, then others and sines.)
        x_sq = x * x;
        y_sq = y * y;
        z_sq = z * z;
        
        x_by_y = x * y;
        y_by_z = y * z;
        z_by_x = z * x;
        
        x_sRes = x * sRes;
        y_sRes = y * sRes;
        z_sRes = z * sRes;
        
        //    Start with the identity matrix.
        mLoadIdentity(matr);
        
        //    We start with the row of x values.
        matr[0] = (omc * x_sq) + cRes;    //    X of X uses cos.
        matr[4] = (omc * x_by_y) - z_sRes;
        matr[8] = (omc * z_by_x) + y_sRes;
        matr[12] = 0.0f;
    
        //    Then y values...
        matr[1] = (omc * x_by_y) + z_sRes;
        matr[5] = (omc * y_sq) + cRes;    //    Y of Y uses cos.
        matr[9] = (omc * y_by_z) - x_sRes;
        matr[13] = 0.0f;
        
        //    Finally, Z numbers.
        matr[2] = (omc * z_by_x) - y_sRes;
        matr[6] = (omc * y_by_z) + x_sRes;
        matr[10] = (omc * z_sq) + cRes;    //    Z of Z uses cos.
        matr[14] = 0.0f;
        
        //    Note: If you look at the above blocks, whichever directions
        //    we are *not* dealing with use the *others* sin result.
        //    So when we're dealing with z value, sin(y) is in the x axis,
        //    and sin(x) is in the y axis.

        //    Done, I guess. :]
    }

What glTools does it it builds a matrix like this and then applies it to the frame of reference vectors to rotate them. I added a another layer, it's just a simple vector rotation command:

Code:
//    Rotate a vector.
    //    Degrees! Degrees! Not Radians!
    void vRotate(float *input, float angle, float x, float y, float z, float *result) {
    
        //    Build a rotation matrix.
        float m_temp[16];
        mRotationA(angle, x, y, z, m_temp);
        
        //    Effectuate the transformation equations.
        result[0] = m_temp[0] * input[0] + m_temp[4] * input[1] + m_temp[8] *  input[2];
        result[1] = m_temp[1] * input[0] + m_temp[5] * input[1] + m_temp[9] *  input[2];
        result[2] = m_temp[2] * input[0] + m_temp[6] * input[1] + m_temp[10] * input[2];
    
    }

Nothing that should screw up there. Finally the top layer. Just a command that uses the vector rotation function to rotate the camera view.

Code:
//    Look left or right. (Typically.)
    //    angle_deg = rotation in degrees.
    void FRAME_REF::RotateY(float angle_deg) {
        
        //    Some frame libs like glTools use rot matrices.
        //    I decided to eliminate that layer. (Actually just
        //    hide it...)
        float result_vect[3];
        vRotateV(vTarg, angle_deg, vUp, result_vect);
        
        //    Put that in it's space.
        vCopy(result_vect, vTarg);
        
        //    El fin!
    }

Nothing spectacular in that function either. Anyways here's what's funny.

If I tap my rotate left or right key, both of which call the RotateY function which small amounts like 0.01 or 0.001 everything on the screen vanishes and does not reappear even if I tap the opposite rotation key. I cant get anything to reappear. It's the strangest thing.

For reference, here's a list of stuff I changed from the glTools version of reference frames:

1) Mine is a class.
2) glTools starts the target vector at -1.0 z, mine is 1.0.
3) glTools inverses the target vector when applying the frame of reference like a camera. The inverted target is placed in the matrix and used to calculate the "right-left" vector. Mine places it in the matrix, but does *not* use the inverted vector when calculating the "left-right" vector.

I'm pretty sure 3) is not the problem. I tested this by including an option to use a gluLookAt call rather than my code. I am currently use gluLookAt, and I'm pretty sure it's not broken. Rasp

I'm guessing the root of the problem is misuse of the matrix rotation function, although I'm not sure how. Care to shed some light on the issue?

EDIT: glTools works for rotation... Hmm, I think I'm on to something. Check back later.
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #8
Jones Wrote:I'll try it and see if it helps. Could you explain why this is, maybe?

Thanks!

EDIT:

Holy moly. For the first time I'm seeing things in *proper* not half-flat 3D. I thought that's the way it was meant to look for the longest time, but now I'm seeing the truth.

FrogBlast, you have liberated me. You have my eternal thanks. Smile Rasp

You want to avoid setting zNear to be extremely small, as that will significantly limit the amount of depth precision available to you. The absolute values of zNear and zFar are not so important, but the order of magnitude difference between them is. ie, dividing zNear by 10 will cost you as much precision as multiplying zFar by 10.

So, changing zNear from 0.1 to 0.00001 will cost you quite a bit. At this point, you should be able to imagine what happens when zNear grows smaller and smaller as it approaches 0.0.
Quote this message in a reply
Marjock
Unregistered
 
Post: #9
Just for the record, if you're having errors in your code I'd check the SuperBible's reference section on the topic against the man pages. I recently got caught out by a nasty error in the SuperBible to do with glDrawElements.

:-)

-Mark
Quote this message in a reply
Jones
Unregistered
 
Post: #10
Marjock Wrote:Just for the record, if you're having errors in your code I'd check the SuperBible's reference section on the topic against the man pages. I recently got caught out by a nasty error in the SuperBible to do with glDrawElements.

:-)

-Mark

It is a lesson we both share now. Rasp
Quote this message in a reply
Jones
Unregistered
 
Post: #11
I fixed my problem. My vCopy function basically did this:

Code:
output[0] = input[0];
output[1] = input[1];
output[2] = input[1];

I could slap myself.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Depth Buffer / Testing basic question... WhatMeWorry 5 6,437 Nov 18, 2005 12:50 AM
Last Post: arekkusu
  depth testing, rendering, and fake shadows MarkJ 8 3,763 Oct 6, 2005 03:43 PM
Last Post: akb825
  Depth Testing not working Feanor 8 4,397 Jan 16, 2005 12:57 PM
Last Post: recursivejon