2 glTranslatef in 1 glPushMatrix !

Started by Yuri6037, January 04, 2015, 18:42:19

Previous topic - Next topic

Yuri6037

Hello,

I'm trying to solve a bug of my 2D Game Engine i made a long time ago, because i need it again. So this bug is simple : "Rotation system is completely broken" !

So basicaly to make a rotation on an object (Triangle, Quad, ...), i need to push matrix and pop matrix because otherwise the glRotatef(-rotation, 0, 0, 1) will rotate the whole screen witch is not what i'm searching for.

So i used a simple matrix to translate only the object to it's coords x and y. But again a problem comes, if i wan't to rotate the object not in the (0, 0) corner but in the center, then i can't because i need 2 glTranslatef in one push matrix, witch seams to be impossible because one of the glTranslatef seams to be ignored.

Also i tried many ways, here is my last try, pleasy look at it :
//objectWidth/Height means the width and the height of my QUAD/TRIANGLE/...
//objectRotation is the desired rotation of this QUAD/TRIANGLE/...
glPushMatrix()
glTranslatef(-(objectWidth / 2), -(objectHeight / 2), 0) // first translate to the rotation points for rotating
glRotatef(objectRotation, 0, 0, 1)
glPushMatrix()
glTranslatef(finalObjectX, finalObjectY, 0) // second translate to the desired object position
/* RENDERING STUFF HERE (glBegin, glEnd) */
glPopMatrix()
glPopMatrix()

quew8

So you are misunderstanding what the glPushMatrix() and glPopMatrix() calls do. OpenGL has a stack of matrices, I'm guessing you aren't sure what a stack is.

Imagine it like a physical "stack" of matrices. So you have one matrix on the floor and on top of it there is another matrix and on top of that there is another matrix and so on (the number of matrices depends on the implementation but I think at least 16 is the standard). But we start off with just one matrix. Now all of the matrix transform functions (ie glTranslate(), glRotate(), glLoadMatrix(), glLoadIdentity() etc) operate on the matrix on the top of the stack. And OpenGL transforms geometry based on the matrix on the top of the stack. We call this the "current" matrix.

Now what glPushMatrix() does is to duplicate the matrix currently on top and put the new one on top. This new matrix then becomes the current matrix and so any other matrix transform calls operate on this duplicate. Then what glPopMatrix() does is to take the top matrix off and discard it. So the matrix beneath it becomes the current matrix.

So lets take a look at your code with this new knowledge. Essentially the second (inner) glPushMatrix()/glPopMatrix() pair is completely useless and does nothing.

Actually there is a far simpler solution to what you are trying to do. Essentially to rotate something around a different origin. You translate to the rotation's origin, rotate, then translate back to the original origin. And a helpful hint, you probably want to be translating the object before you rotate it. So your code should look like this:

glPushMatrix();
glTranslatef(finalObjectX, finalObjectY, 0); //Translate object to position
glTranslatef(-(objectWidth / 2), -(objectHeight / 2), 0); //Translate to origin of rotation (relative)
glRotatef(objectRotation, 0, 0, 1); //Rotate
glTranslatef((objectWidth / 2), (objectHeight / 2), 0); //And translate back to actual position
//Render Object.
glPopMatrix();


And there is an obvious optimization we can make here whenever we see two glTranslate() calls directly after one another.

glPushMatrix();
glTranslatef(finalObjectX-(objectWidth / 2), finalObjectY-(objectHeight / 2), 0); //Translate object to position offset by origin of rotation
glRotatef(objectRotation, 0, 0, 1); //Rotate
glTranslatef((objectWidth / 2), (objectHeight / 2), 0); //And translate back to actual position
//Render Object.
glPopMatrix();


Hope I've helped.