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?
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.
ok but both have basically the same effect - or is there anything i should take care of?
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.
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).
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?
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:
1 | void 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 | |
11 | void 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).
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.
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?
The clues are in the man pages:
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.
Camera - you're doing it wrong
{"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"}
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?
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).
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.
The OpenGL standard specifies initial values for a number of its variables, specifically:
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
if i want to rotate two objects with different angles
and
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.