OpenGL ES Z axis not working

Member
Posts: 215
Joined: 2008.06
Post: #1
When moving my object around, the X and Y axes work fine, but moving my object in the Z direction does not change how it is drawn to the screen. It does not grow larger when at a higher Z value, and does not get smaller at a lower Z value. It simply disappears once it hits a clipping plane. Does this have something to do with the glOrtho() call I make when I draw? I'm pretty sure I have everything in place correctly, but here is my drawing code:

Code:
[EAGLContext setCurrentContext:context];
    
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -10.0f, 10.0f);
    
    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glLoadIdentity();
    
    glPushMatrix();
    glTranslatef([object x], [object y], [object z]);
    [object drawObjectVBO];
    glPopMatrix();
        
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];

Mac users swear by their computers, PC users swear at their computers. ~Unknown

iSayz
Quote this message in a reply
Member
Posts: 156
Joined: 2002.10
Post: #2
An orthographic view by definition does not have any sense of scale/depth associated with the Z axis as it is what is known as a parallel projection - i.e. parallel lines do not meet at a vanishing point, they just continue off in parallel to infinity. See http://en.wikipedia.org/wiki/Orthographic_projection for details.

If you want a top-down view with perspective you can use gluPerspective() so set up the projection, and gluLookAt() to place your camera on the Z axis looking at the origin.

Cheers

- Iain
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #3
IBethune Wrote:If you want a top-down view with perspective you can use gluPerspective() so set up the projection, and gluLookAt() to place your camera on the Z axis looking at the origin.

...at least, you could if they were included with OpenGL ES. Here's a similar alternative to gluPerspective() (from Matrix.c in my matrix tutorial):

Code:
struct Matrix {
  float m[16];
};
typedef struct Matrix Matrix;

void Matrix_loadIdentity(Matrix * matrix) {
    matrix->m[0] = 1.0;
    matrix->m[1] = 0.0;
    matrix->m[2] = 0.0;
    matrix->m[3] = 0.0;
    matrix->m[4] = 0.0;
    matrix->m[5] = 1.0;
    matrix->m[6] = 0.0;
    matrix->m[7] = 0.0;
    matrix->m[8] = 0.0;
    matrix->m[9] = 0.0;
    matrix->m[10] = 1.0;
    matrix->m[11] = 0.0;
    matrix->m[12] = 0.0;
    matrix->m[13] = 0.0;
    matrix->m[14] = 0.0;
    matrix->m[15] = 1.0;
}

Matrix Matrix_identity() {
    Matrix matrix;
    
    Matrix_loadIdentity(&matrix);
    return matrix;
}

void Matrix_multiply(Matrix * matrix1, Matrix m2) {
    Matrix m1, result;
    
    m1 = *matrix1;
    
    result.m[0]  = m1.m[0] * m2.m[0]  + m1.m[4] * m2.m[1]  + m1.m[8]  * m2.m[2]  + m1.m[12] * m2.m[3];
    result.m[1]  = m1.m[1] * m2.m[0]  + m1.m[5] * m2.m[1]  + m1.m[9]  * m2.m[2]  + m1.m[13] * m2.m[3];
    result.m[2]  = m1.m[2] * m2.m[0]  + m1.m[6] * m2.m[1]  + m1.m[10] * m2.m[2]  + m1.m[14] * m2.m[3];
    result.m[3]  = m1.m[3] * m2.m[0]  + m1.m[7] * m2.m[1]  + m1.m[11] * m2.m[2]  + m1.m[15] * m2.m[3];
    result.m[4]  = m1.m[0] * m2.m[4]  + m1.m[4] * m2.m[5]  + m1.m[8]  * m2.m[6]  + m1.m[12] * m2.m[7];
    result.m[5]  = m1.m[1] * m2.m[4]  + m1.m[5] * m2.m[5]  + m1.m[9]  * m2.m[6]  + m1.m[13] * m2.m[7];
    result.m[6]  = m1.m[2] * m2.m[4]  + m1.m[6] * m2.m[5]  + m1.m[10] * m2.m[6]  + m1.m[14] * m2.m[7];
    result.m[7]  = m1.m[3] * m2.m[4]  + m1.m[7] * m2.m[5]  + m1.m[11] * m2.m[6]  + m1.m[15] * m2.m[7];
    result.m[8]  = m1.m[0] * m2.m[8]  + m1.m[4] * m2.m[9]  + m1.m[8]  * m2.m[10] + m1.m[12] * m2.m[11];
    result.m[9]  = m1.m[1] * m2.m[8]  + m1.m[5] * m2.m[9]  + m1.m[9]  * m2.m[10] + m1.m[13] * m2.m[11];
    result.m[10] = m1.m[2] * m2.m[8]  + m1.m[6] * m2.m[9]  + m1.m[10] * m2.m[10] + m1.m[14] * m2.m[11];
    result.m[11] = m1.m[3] * m2.m[8]  + m1.m[7] * m2.m[9]  + m1.m[11] * m2.m[10] + m1.m[15] * m2.m[11];
    result.m[12] = m1.m[0] * m2.m[12] + m1.m[4] * m2.m[13] + m1.m[8]  * m2.m[14] + m1.m[12] * m2.m[15];
    result.m[13] = m1.m[1] * m2.m[12] + m1.m[5] * m2.m[13] + m1.m[9]  * m2.m[14] + m1.m[13] * m2.m[15];
    result.m[14] = m1.m[2] * m2.m[12] + m1.m[6] * m2.m[13] + m1.m[10] * m2.m[14] + m1.m[14] * m2.m[15];
    result.m[15] = m1.m[3] * m2.m[12] + m1.m[7] * m2.m[13] + m1.m[11] * m2.m[14] + m1.m[15] * m2.m[15];
    
    *matrix1 = result;
}

void Matrix_applyPerspective(Matrix * matrix, float fovY, float aspect, float zNear, float zFar) {
    Matrix perspectiveMatrix;
    float sine, cotangent, deltaZ;
    
    fovY = (degreesToRadians(fovY) / 2.0f);
    deltaZ = (zFar - zNear);
    sine = sin(fovY);
    if (deltaZ == 0.0f || sine == 0.0f || aspect == 0.0f) {
        return;
    }
    cotangent = (cos(fovY) / sine);
    
    Matrix_loadIdentity(&perspectiveMatrix);
    perspectiveMatrix.m[0] = (cotangent / aspect);
    perspectiveMatrix.m[5] = cotangent;
    perspectiveMatrix.m[10] = (-(zFar + zNear) / deltaZ);
    perspectiveMatrix.m[11] = -1.0f;
    perspectiveMatrix.m[14] = ((-2.0f * zNear * zFar) / deltaZ);
    perspectiveMatrix.m[15] = 0.0f;
    Matrix_multiply(matrix, perspectiveMatrix);
}

Matrix Matrix_perspective(Matrix matrix, float fovY, float aspect, float zNear, float zFar) {
    Matrix_applyPerspective(&matrix, fovY, aspect, zNear, zFar);
    return matrix;
}

void setPerspective(float fovY, float aspect, float zNear, float zFar) {
  Matrix matrix;
  
  matrix = Matrix_perspective(Matrix_identity(), fovY, aspect, zNear, zFar);
  glMultMatrixf(matrix.m);
}

With that, you can call setPerspective() the same way you'd call gluPerspective().
Quote this message in a reply
Member
Posts: 156
Joined: 2002.10
Post: #4
ThemsAllTook Wrote:...at least, you could if they were included with OpenGL ES.

My bad, didn't notice we were in the iPhone forum. The explanation still stands though.
Quote this message in a reply
Member
Posts: 144
Joined: 2004.07
Post: #5
For simplicity you could manually scale (glScale) the object based on it's depth value - make it smaller when it's further away or larger when it's close.
Quote this message in a reply
Member
Posts: 26
Joined: 2008.08
Post: #6
lightbringer Wrote:For simplicity you could manually scale (glScale) the object based on it's depth value - make it smaller when it's further away or larger when it's close.

That kinda defeats the purpose of an orthographic projection -- just use glFrustum()l.

In regards to the above link, note that OpenGL man pages are best read in Terminal for the simple reason that their web-counterparts aren't translated 100% correctly -- dividends, for example, are absent altogether in division.

For those that don't know, reading man pages is as simple as firing up Terminal and typing
Code:
man glFrustum
(for example) at the prompt. Use j to scroll down, k to scroll up, and q to quit.
Quote this message in a reply
Member
Posts: 26
Joined: 2008.08
Post: #7
Sorry in advance for double-posting, but I seem to recall having read that using OpenGL to handle matrix multiplication (and the like) is preferable to doing it with one's own code, for a number of reasons. One of which being (I would assume) that most OpenGL implementations take advantage of diagonal matrices and the like. Heck, some might have even been written in assembly for the sole reason of speed.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #8
Using OpenGL to handle matrix multiplication is almost certainly slower than doing it yourself. You pay all sorts of overheads that you don't with your own code.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #9
While OpenGL is designed specifically for this stuff, it can't read your mind, so it is forced to generalize the calculations to a degree (like any API). If you do the calcs yourself you'll know what situation you're in and can easily optimize for that (of course, you can always screw it up too, which I've been known to do myself).

As an easy example of where you could beat the GL: OpenGL always does 3 dimensional calculations. If you're only transforming in two then you can cut out a bunch right there. Or if you know what order you're doing your transforms, and/or don't need to stack them, you can cut out matrices altogether with a custom calculation. Simply put: No matter how much highly optimized assembly is built into the API for the general case, skipping all of it for a single add or multiply will utterly smoke it, if you know that's all you need for your particular transform.

Personally though, I prefer the easier approach of just letting the GL do it for me in the general case first. If there's a performance or usage issue discovered later, then I roll my own, which is fun too.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #10
The matrix stacks are deprecated/removed in newer versions of OpenGL, so sooner or later you're going to have to deal with it yourself.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #11
I hadn't heard that. Sounds pretty extreme to be cutting out essential convenience routines like matrix stacking wholesale. [edit] "essential" is probably too much, try "widely-used" instead.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #12
Not even "widely used" I think. As soon as your game has any complexity, the most you'll use is PushMatrix/PopMatrix/MultMatrix, and that's scarcely rocket science to replicate given you already have your own matrix multiplication Wink

They're convenient for small demos, but not much beyond that.
Quote this message in a reply
Moderator
Posts: 3,572
Joined: 2003.06
Post: #13
OneSadCookie Wrote:... the most you'll use is PushMatrix/PopMatrix/MultMatrix, and that's scarcely rocket science to replicate given you already have your own matrix multiplication Wink.

In fact, I *just* did that myself (for 3x3 2D matrix transforms) so I can testify that it is brain-dead simple to do. It's like a total of 60 lines of code, including embellishments for init/loadIdentity/push/pop. Oh, and then another 15 for transformVerts. Tack on another hundred for translate rotate scale and extra stuff and that's my entire 2D transform library. Definitely no rocket science required.

But still, I can't see having to copy/paste transform utilities into every stinkin little demo. And that would add a big notch of uncertainty to what beginners are using for their transforms too. Maybe the transform utilities will just be moved out of the core GL and into a utility library instead, like glu or something?
Quote this message in a reply
Member
Posts: 312
Joined: 2006.10
Post: #14
If the matrix stacks will be removed from OpenGL eventually will that include glLoadMatrix() meaning we'll have to transform all of our vertices ourselves?
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #15
Isn't this what hardware T&L was supposed to do? Seems kind of backwards.
Quote this message in a reply
Post Reply