matrix and pipeline confusion

Started by
5 comments, last by Zakwayda 18 years, 8 months ago
I've got a little problem and I think it involves the way I'm using matrix stacks, so if someone could help me understand how stacks are used ... If I push a matrix on to a stack, is it like moving a transparent piece of paper (with a drawing on it) out of the way and making another drawing, and when I'm finished with the current drawing I pop the previous matrix and it's like overlaying the original transparent drawing on top of the current one so I see both objects now? Why not draw something, call loadIdentity(), then draw the other? If I only draw one object in my scene, will I really need to push and pop matrices? Another question I have is, if the transformation pipeline multiplies a vertex against the modelview matrix first, then the projection matrix (as I understand it, that's the order things are done in) ... then why do I see so many examples of calls in display methods (or renderScene, etc...) that do operations on the GL_PROJECTION matrix first, then the GL_MODELVIEW matrix afterwards ... this really confuses me. How does it work if a programmer calls these matrices in the order he wants, yet opengl calls them in a different order? Any help much appreciated.
Advertisement
You don't really need to call glPop() or glPush(), but it's useful when things get complex.


Let's say we have some object boo and far on a table, and their location is known only as distance to the edge of the table.
glPush();  glTranslate(edge of table);     glPush();       glTranslate(foo);       Draw(foo)     glPop();     glPush();       glTranslate(bar);       Draw(bar);     glPop();glPop();
There, we skipped a whole step drawling 'bar', we don't need to glTranslate to the endge of the table twice, saving a whole step. This is pretty useful when you get into model loading, where you need to translate several times to reach a "root".

When we pop the second time, we know we're back to the original untouched coordnates, so we can add another translate and move the the table around without effecting bar and foo, they're stil be fine.

However, your solution will work until you start getting more advance.
~
Now with the GL_MODELVIEW and the GL_PROJECTION . The GL_MODELVIEW gets changed a lot, as we move through the world, while the GL_PROJECTION usually remains constant. We want the world to look about the same all the time(have the same prospective), but we don't want our objects to be in the same place all the time. [smile] It makes sense to make the GL_PROJECTION how we want it when we start the program and leave it alone for the rest of the program.
I may repeat some of what Binomine said, but...

You're right that projection is applied last. I believe OpenGL maintains the projection and 'modelview' matrices separately, and when a vertex is transformed, the modelview matrix is applied, and then the projection matrix. The order in which they're applied is unrelated to the order in which you set them up, so you can set the projection matrix up first if you want. As I think has already been said, the projection matrix is usually set only once per frame, and often only once, period, so it makes sense to do it first.

Another thing that might confuse you is that OpenGL uses column vectors, and therefore transformations are applied from right to left (bottom to top in code). So this:

glLoadIdentity();
glTranslatef(100, 0, 0);
glRotatef(y, 0, 1, 0);
glRotatef(x, 1, 0, 0);

First rotates about the x axis, then rotates about the y axis, and then translates, the opposite of what you might expect.
Quote:Original post by jykAnother thing that might confuse you is that OpenGL uses column vectors, and therefore transformations are applied from right to left (bottom to top in code).


Now this I am very interested in understanding better. What is this called? Or where can I find more info detailing this?

Thanks for ya'lls replies.

Hello,

The OpenGL matrix stack is a way to handle transformation hierarchy, as Binomine said.

What you have seen in the examples is that the projection matrix was set first, but this not affect the matrix evaluation order in the pipeline.

OpenGL is a state machine, so you can only change states. The evaluation order of those states is determined by the "fixed pipeline". Actually, you could override the default pipeline behavior using vertex and pixel shaders.

Really, the modelview and projection matrices are compounded together, through matrix multiplication, in a "modelviewprojection matrix", so the vertex is evaluated against one single matrix.

This is a very simple vertex program for illustrating what I said:


uniform float4x4 modelViewProj : state.matrix.mvp;

void main( float4 pos : POSITION,
out float4 oPos : POSITION)
{

oPos = mul(modelViewProj, pos);
}


In the previous example an initial (input) vertex position 'pos' is transformed by the modelviewprojection matrix into the final (output) position 'oPos'.

Regarding to row major or column major, it is only a notational convention.
In OpenGL the matrix values are disposed in the following way:

float mv[16] = { r11,r12,r13,0,
r21,r22,r23,0,
r31,r32,r33,0,
tx ,ty ,tz ,1
}

"Post multiplying with column major matrices produces the same result as pre-multiplying with row major matrices". That means this:

v : vertex
M: modelview matrix
MT: transposed modelview matrix

v*M = MT*v
Lord CiriuzAquadize Studios
I didn't fully read all of the posts so forgive me if I'm repeating something.. The projection matrix is used specifically to set up the projection (hence the name), so think of it as the lens of the camera. You can use the Projection Matrix to make a 'wide angle' lens, or whatever. You only ever need to "install" one lens on a camera before you use it; likewise you only really need to set up the projection matrix once, in most cases.

The Modelview Matrix is used to set up the model or the view.....that is, you can think of it as the matrix that controls the orientation and position of the "camera" through which you're viewing the scene, or you can think of it as the orientation of the model.

I'm not sure if I said that clearly, but think of it like this: There are two ways to visualize what the modelview matrix is doing. First, pretend you have a camera sitting in space, in a fixed location. It doesn't move or rotate. If you modify the modelview matrix, then you can think of the matrix as modifying the orientation and position of the object that the fixed camera is pointing at. In exactly the same way, you can think of it as moving the camera, and leaving the model exactly where it is, untouched. That's why it's called the Model+View matrix.

The matrix stack stores copies of your transformation matrices (there are two separate stacks for the projection and modelview matrices, respectively), so that you can compose transformations. That is, say you want to draw a tank with a free-rotating turret. The body of the tank might be pointed one way, and the turret can rotate a different way. You might have 2 orientation matrices, one for the body and one for the turret.

Your code might look something like this:

glMatrixMode(GL_PROJECTION);
// .....set up your projection stuff, e.g. view frustum

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glPushMatrix();
glTranslatefv(bodyPos); // assume bodyPos is a float array
glRotatefv(bodyRot); // assume bodyRot is a float array
tank.drawBody(); // contains code to draw body
glPushMatrix();
glTranslatefv(turretPosRelativeToBody); // RELATIVE TO BODY!!
glRotatefv(turretRotRelativeToBody); // RELATIVE TO BODY!!
tank.drawTurret();
glPopMatrix();
glPopMatrix();

I wrote this off the top of my head, so it may contain errors, but hopefully you get the idea.
Quote:Now this I am very interested in understanding better. What is this called? Or where can I find more info detailing this?
Briefly, you can represent an N-dimensional vector as either a 1xN or Nx1 matrix; the former is referred to as a row vector and the latter as a column vector, for obvious reasons.

Due to the rules of matrix multiplication, a row vector can only be multiplied to the left of a matrix, and a column vector only to the right. With row vectors, a series of matrix multiplications might look like this:

v' = ((v*M0)*M1)*M2 = v*(M0*M1*M2)

With column vectors, you would instead have:

v' = M0*(M1*(M2*v)) = (M0*M1*M2)*v

You can see that with row vectors, the order in which the matrices are applied to the vector is 012, or left to right; with column vectors, it is 210, or right to left. OpenGL uses column vectors and so the order is right to left, which translates to 'bottom to top' in code.

'Hope that helps.

This topic is closed to new replies.

Advertisement