Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » glLoadIdentity vs glPushMatrix/glPopMatrix

This thread is locked; no one can reply to it. rss feed Print
glLoadIdentity vs glPushMatrix/glPopMatrix
Frank Drebin
Member #2,987
December 2002
avatar

ok so i'm pretty new to opengl...
if i want to rotate two objects with different angles i have to call either glLoadIdentity after the first rotation or i have to call glPopMatrix, rotate and glPushMatrix for each object...
so wich one to use?

amber
Member #6,783
January 2006
avatar

Push and pop.

That way, if you decide you want the whole rotation to be part of a more complicated system that's also moving around and rotating, you don't have to redo everything. :)

Frank Drebin
Member #2,987
December 2002
avatar

ok but both have basically the same effect - or is there anything i should take care of?

Thomas Harte
Member #33
April 2000
avatar

They don't have the same effect.

glLoadIdentity replaces the current matrix with the identity matrix.

glPushMatrix pushes the current matrix onto a stack. You can then pull the top matrix off the stack and make it the current one later using glPopMatrix.

Those are only the same if:

  • your camera is always fixed at (0, 0, 0) looking along z

  • all of your models are single, rigid shapes

  • you loaded your matrix stack with the identity in the first place

Or if you're doing lots of unnecessary arithmetic yourself on the CPU, making your code more complicated and your application less speedy.

SiegeLord
Member #7,827
October 2006
avatar

Quote:

glPushMatrix pushes the current matrix onto a stack.

To make that more clear, the current matrix is not affected by this at all. glPushMatrix simply makes a copy that you can retrieve later on with glPopMatrix. You still will have your old transformation matrix as your current matrix that still has to be cleared to an identity matrix. Thus, you need to call glLoadIdentity regardless (at least once, as Thomas Harte's third bullet suggests).

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

Frank Drebin
Member #2,987
December 2002
avatar

Quote:

Thus, you need to call glLoadIdentity regardless (at least once, as Thomas Harte's third bullet suggests).

don't get it... i have to call glLoadIdentity() once at least?

Thomas Harte
Member #33
April 2000
avatar

Quote:

don't get it... i have to call glLoadIdentity() once at least?

I'm sorry, I'm probably about to repeat a whole bunch of information you already know. I don't mean to be patronising, I'm just not sure exactly how to answer otherwise.

OpenGL has two matrix stacks that affect how geometry is mapped from 3d space to your screen — PROJECTION and MODELVIEW.

When you tell OpenGL to process geometry (through glVertex3f, vertex arrays or any other method) it first applies the MODELVIEW matrix. That matrix acts to position your model relative to the camera. So changes to MODELVIEW are often used to move the camera, move the object or both.

It then applies PROJECTION as part of the process of projecting your geometry onto the 2d screen. Changes to PROJECTION are commonly used to do things such as change the aspect ratio or the centre of projection of the output image — e.g. if you have a view into your world occupying the entire screen then you probably want different settings than if you have two player split screen.

The OpenGL stack mechanisms don't really care about when you start or finish drawing your image. Their state only changes when you explicitly change it.

So, a common way of doing things for a game looks like this:

1void FunctionRunWhenProgramStarts()
2{
3 glMatrixMode(GL_PROJECTION); // signal that I want to work with the projection stack
4 glLoadIdentity(); // make sure that the projection stack doesn't already have anything on it
5 gluPerspective(whatever I want); // set up a normal perspective projection
6 
7 glMatrixMode(GL_MODELVIEW); // the rest of my app will only change MODELVIEW
8 glLoadIdentity(); // make sure that the modelview stack doesn't already have anything on it
9}
10 
11void FunctionToDrawAFrame()
12{
13 // modelview is still the active stack, because I never that setting
14 glPushMatrix(); // push current matrix up one, because I'm about to do a bunch of stuff that shouldn't remain active after the end of this function
15 
16 /* position camera - whatever code you want, this is just an example */
17 glTranslatef(cameraX, cameraY, cameraZ);
18 glRotatef(cameraAngle, 0, 1, 0);
19 
20 /* draw all objects */
21 for(all objects)
22 {
23 glPushMatrix(); //we don't want each object to move the camera...
24 
25 glTranslatef(objectX, objectY, obectZ);
26 glRotatef(objectAngle, 0, 1, 0);
27 
28 DrawObject(); // whatever method you use to draw your object
29 
30 glPopMatrix(); //restore unaffected camera for next object
31 }
32 
33 glPopMatrix(); // restore view prior to movement by this camera
34}

The general rule people program to when using OpenGL is "leave everything in the state it was before I did this operation". The way you do that is to backup the state (in this case, using glPushMatrix), do whatever you have to in order to achieve your operation, then restore the original state (using glPopMatrix).

Arthur Kalliokoski
Second in Command
February 2005
avatar

http://www.opengl.org/resources/faq/technical/transformations.htm

They said:
9.020 How do I transform only one object in my scene or give each object its own transform?

OpenGL provides matrix stacks specifically for this purpose. In this case, use the ModelView matrix stack.

A typical OpenGL application first sets the matrix mode with a call to glMatrixMode(GL_MODELVIEW) and loads a viewing transform, perhaps with a call to gluLookAt().More information is available on gluLookAt().

Then the code renders each object in the scene with its own transformation by wrapping the rendering with calls to glPushMatrix() and glPopMatrix(). For example:

glPushMatrix(); glRotatef(90., 1., 0., 0.); gluCylinder(quad,1,1,2,36,12); glPopMatrix();

The above code renders a cylinder rotated 90 degrees around the X-axis. The ModelView matrix is restored to its previous value after the glPopMatrix() call. Similar call sequences can render subsequent objects in the scene.

They all watch too much MSNBC... they get ideas.

Frank Drebin
Member #2,987
December 2002
avatar

hmmm i still don't understand why i have to call something like glMatrixMode() or glLoadIdentity before using glPushMatrix/glPopMatrix. atm i only set up the screen coordinates to "allegro-coordinates" through glOrtho(0,640,480,0,-1,1) at the start of my programm and then everything works fine without these function mentioned before. do i really need to call something like these before?

Thomas Harte
Member #33
April 2000
avatar

The clues are in the man pages:

glOrtho man page said:

multiply the current matrix by an orthographic matrix

So, what will your matrix stack look like if you only call glOrtho? The answer is: you don't know. Because you don't know what was originally on the stack. It sounds like it's the identity on your particular, current OpenGL implementation. Is it on mine? Who knows. If you weren't too lazy to write the 17 extra characters "glLoadIdentity();" then I don't suppose it would matter much.

Similarly, what do you think happens next when you pass geometry to OpenGL? It goes through MODELVIEW and then PROJECTION. So what's the end result? Again - you couldn't quite be bothered to load the identity matrix to MODELVIEW, so you don't know. It could easily vary from driver to driver.

"It works on my computer" is the absolute worst justification for using a particular set of code. If you aren't willing to program according to the specifications of the API you're using then don't be surprised when your program doesn't work on other people's computers. Or even necessarily your own, unless you keep everything about your software installation exactly as it is now.

Leniuch
Member #5,175
October 2004
avatar

Camera - you're doing it wrong :P

{"name":"photo5av.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/b\/bbee34fd8702e56e2ea7dff8f1cc0aae.jpg","w":500,"h":434,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/b\/bbee34fd8702e56e2ea7dff8f1cc0aae"}photo5av.jpg

Frank Drebin
Member #2,987
December 2002
avatar

ah ok i think now i got it:
so i can't rely on that these both matrixes are "initiallized" automatically so i have to reset it on my own once through calling

glMatrixMode(GL_PROJECTION);
glLoadIdentity(); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();

it's like initializing an integer cause i don't know what number it actually holds if uninitiallized, right?

Archon
Member #4,195
January 2004
avatar

I jumped in here a little late.

An easy way to remember the transformations: think of the Modelview matrix as the world, the Projection matrix as a kaleidoscope/glasses and the Viewport as your visual spectrum (2D screen).

Quote:

it's like initializing an integer cause i don't know what number it actually holds if uninitiallized, right?

I suppose that you could think of it like that. It adds certainty in the end.

Elias
Member #358
May 2000

The OpenGL standard specifies initial values for a number of its variables, specifically:

OpenGL 2.0 specs said:

MODELVIEW_MATRIX Identity
PROJECTION_MATRIX Identity

So as long as your drivers are not broken, you can rely on it. But since drivers usually are broken, and since you might change your code to modify the matrix elsewhere, I still would agree that calling glLoadIdentity() is a good idea :)

--
"Either help out or stop whining" - Evert

Arthur Kalliokoski
Second in Command
February 2005
avatar

Quote:

if i want to rotate two objects with different angles

and

Quote:

hmmm i still don't understand why i have to call something like glMatrixMode() or glLoadIdentity before using glPushMatrix/glPopMatrix.

I understood the first quote to mean objects that were created in object space, i.e. you created them at 0,0,0 in your modeler (so you didn't have to "move" maybe a hundred virtual meters in your 3d modeler to get to it upon file load). So when you need to "move" that object to the appropriate position in your world you don't want to move everything else along with it. Thus, glPushMatrix() and glPopMatrix().

as for the second quote...
Unless you keep very good track of which matrix mode you're in when you move your objects, using glPushMatrix() will possibly push the wrong stack. I messed up like this just last week rewriting my text code in glOrtho(). AFTER you've pushed your matrix, THEN call glLoadIdentity(), just like you need to initialize local auto variables in C.

They all watch too much MSNBC... they get ideas.

Go to: