PDA

View Full Version : world rotation v. body rotation



cosmicGirl
02-17-2003, 09:59 AM
how do you guys implement them?
any useful links?

thanks

nexusone
02-17-2003, 04:21 PM
Variables work nice..


world.x
world.y
world.z
world.rotation_x
world.rotation_y
world.rotation_z


object.x
object.y
object.z
object.rotation_x
object.rotation_y
object.rotation_z

rIO
02-18-2003, 12:47 AM
Always keep in mind that you aren't rotating objects, you are rotating coordinate systems.

glLoadIdentity();
ApplyWorldMatrix();
DrawWorld();

glPushMatrix();
ApplyObject1Matrix(); //remember object matrix is still active here if you don't need it just load identity matrix
DrawObject1();
glPopMatrix();

glPushMatrix();
ApplyObject2Matrix();
DrawObject2();
glPopMatrix();

this is how it works...

cosmicGirl
02-18-2003, 07:14 PM
thanks guys
that was useful

cosmicGirl
03-03-2003, 12:59 PM
correct me if i am wrong but as i understand it it goes like this:

in order to make an object rotate around its axis i have to use glPopMatrix() till i get the object's coords to coincide the world coords, then perform the rotation, and then to multiply by all the transformations that were done prior to rotation.
in other words: premultiply!!!

is this right?

HalcyonBlaze
03-03-2003, 01:44 PM
WHOA hold on there! You have it REALLY close...but do not go applying glPopMatrix() without already having a glPushMatrix(). They work in pairs. glPushMatrix() and then a glPopMatrix(). If you called a glPopMatrix() first....say goodbye to any and all transforms you had applied to your world. OpenGL may have some form of error checking for that, but you need to call them in pairs.

A glPushMatrix() call pushes the current transformation matrix down one level and puts an identity matrix on top. Because of that, all other transforms before do not affect the object. Therefore, it will spin about it's own center because the transform to get it out to where it is lies in the matrix one below that.

- Halcyon

cosmicGirl
03-03-2003, 02:35 PM
thanks blaze,
[B]WHOA hold on there! You have it REALLY close...but do not go applying glPopMatrix() without already having a glPushMatrix().
They work in pairs. glPushMatrix() and then a glPopMatrix().

yeah i meant that(to use them in pairs) sorry i wasnt clear. http://www.opengl.org/discussion_boards/ubb/smile.gif

A glPushMatrix() call pushes the current transformation matrix down one level and puts an identity matrix on top. Because of that, all other transforms before do not affect the object. Therefore, it will spin about it's own center because the transform to get it out to where it is lies in the matrix one below that.

i am confused here.....
i have always thought that glRotate will rotate the object (regardless of its position) around the world coords..right???
thats why to make in spin around its own coords i have to remember all the transformations, then make the world and object coords coincide, and then perform the remembered transformations.

am i being clear?? or correct for that matter?
thanks

jenny

Miguel_dup1
03-03-2003, 04:00 PM
Well, you have the idea, but you have it a bit confused. I know it is a bit difficult to get.

You will probably see the concepts if we talk about spaces (coordinate system)... For example, you have texture space, you have object space, you have world space...
Well, glPushMatrix, and its partner in crime, glPopMatrix allow you to apply transformations to different spaces without affecting other objects spaces... What I mean is that transformation are cumulative. So if you rotate an Object A 45 degrees, and then you rotate Object B 45 degrees, without glPushMatrix() glLoadIdentity() glPopMatrix(), your Object B will end up rotating 90 degrees. So if you want to rotate Object A 45 degrees and Object B 45 degrees, you would do:

glPushMatrix()
glLoadIdentity()
glRotate( .... )
DrawObject( A )
glPopMatrix()

glPushMatrix()
glLoadIdentity()
glRotate( .... )
DrawObject( B )
glPopMatrix()

If you dont use the glPush glLoadIdentity and glPop, you will end up rotating Object B 90 degress instead because the current matrix still has those 45 degrees from the previous rotation...

The different spaces have different purposes of course. You normally draw objects in object space, which is the MODELVIEW matrix. The PROJECTION matrix would be the world matrix. So vertices are multiplied by the MODELVIEW matrix to get eye coordinates, which are then multiplied with the PROJECTION matrix to get clipping coordinates, which go under perspective division and viewport to get screen coordinates... Sigh.

An object rotates arounds its own space, but it is then multiplied with the PROJECTION matrix. This is why you need to bring the object to the origin of the world space (make the object and world space coincide) and apply rotation. Otherwise your rotation will be off.

I hope this clarified your doubts...

Miguel Castillo

Miguel_dup1
03-03-2003, 04:06 PM
Something you also need to know is that there is no real difference if you translate or rotate the object or the world because they will produce the same effect. The only difference is that they are inverse transformation of each other. You rotate your object to the left, you get the same effect by rotating your world to the right.

http://www.opengl.org/discussion_boards/ubb/smile.gif

yakuza
03-03-2003, 06:15 PM
A glPushMatrix() call pushes the current transformation matrix down one level and puts an identity matrix on top.

Just wanted to clarify so cosmicGirl isn't mislead: the current matrix is copied onto the stack, not the identity matrix.

http://www.3dlabs.com/support/developer/GLmanpages/glpushmatrix.htm

glPushMatrix pushes the current matrix stack down by one, duplicating the current matrix. That is, after a glPushMatrix call, the matrix on top of the stack is identical to the one below it. glPopMatrix pops the current matrix stack, replacing the current matrix with the one below it on the stack. Initially, each of the stacks contains one matrix, an identity matrix.

HalcyonBlaze
03-04-2003, 06:04 AM
Wait now i'm confused http://www.opengl.org/discussion_boards/ubb/biggrin.gif. If you put an exact copy of the previous matrix on the top of the stack, wouldn't the transformations in the glPushMatrix()/glPopMatrix() pair be the exact same as if you excluded them? The only difference i see of including them is that the transformations are not saved. I mean if you translate the scene back by 5 units and do a glRotate on a cube, you would have it spin on a circle with a radius of 5. With a glPushMatrix() and glPopMatrix(), you should still be rotating around on a circle with a radius of 5 units right? I mean it's the same thing. Only thing is that once you're done, the rest of the code isn't affected. But i don't understand how all of the sudden with a glPushMatrix()/glPopmatrix(), you have a cube spinning about the center if it had the same transformation matrix as before?

- HalcyonBlaze

Thanks for you help on this to those who reply! This stuff is like a brick wall in learning opengl....once you get past this, things just start flowing for a while. Really understanding and getting comfortable with trasforms takes a while.

cosmicGirl
03-04-2003, 09:14 AM
ok......man am i ever confused now.
is there a place where i can get tutorials that explain this kind of thing? or should i just play around with opengl?

anyhow...what i am trying to do is make the object rotate around its own axis. In the beginning of the application i have object centred at the origin so that the world's coincide with obejct coords but after i scale/rotate/translate it they dont anymore.
If after i have transformed it say 5 units to the left i simply apply glRotate it will rotate around the (0,0,0) and not around its own axis like i want it to which is why i bring the object back to the origin ( remembering all the transformation done to it) apply rotation around x y or z and then apply all the tranformaions again so that the obejct will be drawn at the correct position in space ....

am i confusing ????

Deiussum
03-04-2003, 09:32 AM
Yakuza is correct about the how the push/pop works. If it didn't work like that you couldn't have parent/child relationships. Take for example a solar system. You can do something like so.




glTranslate(location of sun);

foreach planet
{
glPushMatrix();
glRotate(planets orbit);
glTranslate(planets distance from sun)
foreach moon in planet.moons
{
glPushMatrix();
glRotate(moon's orbit around planet)
glTranslate(moon's distance from planet);
glPopMatrix();
}
glPopMatrix();
}


The reason this works is BECAUSE the matrix stays the same as it was originally after the glPushMatrix. If it didn't, the moon would get positioned relative to the sun instead of the position of the planet.

The glPopMatrix will then return the matrix to the state it was in at the time of the corresponding glPushMatrix(), thus removing the effects of the transformations of the previous moon and/or planet

Deiussum
03-04-2003, 09:37 AM
I think you just need to understand how the matrix math works to understand your problem cosmicGirl.

There are a couple of ways you can think about the order of matrix operations. I like to think of it in terms of world coordinates. When you think of it this way you need to realize that due to the properties of the matrix math, the last matrix operation done is actually the first thing done.

So... say you want to rotate your model first and then translate it. You need to do the translate FIRST.

glTranslate();
glRotate();
drawModel();

The rotate is actually what will appear to be done first so if your model is centered around 0,0,0 it will be rotated around that and then translated.

If you did it the opposite order

glRotate();
glTranslate();
drawModel();

You now are effectively translating first, and then rotating around the origin of the world.

The Red Book has a fairly decent chapter explaining some of these things. I don't have any links offhand, but a google search should turn up a lot of places you can find a downloadable copy of that.

cosmicGirl
03-04-2003, 10:05 AM
^^^ thanks a bunch.
i know that the order is reverse.


in my application, the point is for a user to be able to transform a model with a mouse, so say a use has already translated in 4 units to the right and now he wants it to rotate around its y-axis.....which is why i need to remember this translation ....
so what i am planning to do is to bring it back to the origin, rotate it around the worlds y-axis, and then translate it.
am i correct? of course the translation will be pushed to be remembered, but my point is that the rotation will be done first...
anyhow i am just gonna get home and plaey aroundwith it, i think its the best way..
thanks guys http://www.opengl.org/discussion_boards/ubb/smile.gif

cosmicGirl
03-04-2003, 10:09 AM
actually, i have one more question:

glRotate will rotate the object around the world's coords right????

Deiussum
03-04-2003, 10:17 AM
Yup, that is correct.

One trick I've used to prevent gimbal lock might be useful for you. What I've usually done is to keep track of a rotation matrix for the object. Then for each new rotation applied, you PRE-multiply the new rotation to your stored rotation matrix. Then when you do the drawing, you use glMultMatrix in order to apply your rotation matrix.

Turbo_Pascal
03-04-2003, 10:51 AM
Originally posted by cosmicGirl:
^^^ thanks a bunch.
i know that the order is reverse.


in my application, the point is for a user to be able to transform a model with a mouse, so say a use has already translated in 4 units to the right and now he wants it to rotate around its y-axis.....which is why i need to remember this translation ....
so what i am planning to do is to bring it back to the origin, rotate it around the worlds y-axis, and then translate it.
am i correct? of course the translation will be pushed to be remembered, but my point is that the rotation will be done first...
anyhow i am just gonna get home and plaey aroundwith it, i think its the best way..
thanks guys http://www.opengl.org/discussion_boards/ubb/smile.gif

instead bringing back the model to 0,0,0 for do correct rotation, you just need to move temporally the world 0,0,0 to the current model position, do this:

glpushmatrix(); //save current world matrix
gltraslatef(x,y,x); //move the world to the model position. x,y,z are object position.
glrotate(xangle,1,0,0); //rotate by x
glrotate(yangle,0,1,0); //rotate by y
glrotate(zangle,0,0,1); //rotate by z

drawobject(); //redraw object with current matrix

glpopmatrix(); //restore world to his original state.

--------------

tp.

cosmicGirl
03-04-2003, 12:31 PM
thanks D, i was talking about just that...maybe i was being unclear.
pre multiplication is the answer....
but in geeneral my understanding is correct???

cosmicGirl
03-04-2003, 12:34 PM
tp: one question:
your solution seems very elegant...
but in this case how do you keep track of xangle, yangle and zangle? as you will still need to do that to get the model be drawn in the correct place

starman
03-05-2003, 03:50 AM
Pick up a copy of the red book (OpenGL Programming Guide) or find it online and read (several times if necessary) the chapter on this stuff. Practice by implementing a simple solar system with gluSphere's or something.

cosmicGirl
03-06-2003, 12:00 AM
i have the book, but i am still unclear which is why i am posting this. thanks for the tip tho

03-06-2003, 03:03 AM
a little OT but
Deisiumm said he stores a matrix them

What I've usually done is to keep track of a rotation matrix for the object. Then for each new rotation applied, you PRE-multiply the new rotation to your stored rotation matrix.


isnt that a little subject to accumulating floating point errors? so when you rotate 360 degs then undo that rotation by rotating -360 degs, your final matrix is not the same as your initial matrix?

i thought that was one reason why we pushed ,rotated then popped. Rather than just rotate and unrotate.
feel free to correct me

Miguel_dup1
03-06-2003, 04:02 AM
You keep track of your matrix transformations in variables because if you had a scene with 10000 objects, it will be impossible to derrive which one of their previous position from the current matrix. There is a limit to how many matrices you can push and pop. So accumulating matrix transformations is not an option and floating point error is not even a concern.

And I dont think he meant to say to unrotate what you rotate. I think he meant that before a new matrix transformation takes place, you push the matrix, you load the identity to clear the cumulative matrix transformations, apply the transformation, and pop the matrix to restore your previous matrix, which kind of sounds like you are undoing what you do. This allows for indepenent movement of objects where each object has its won position and orientation.



[This message has been edited by mancha (edited 03-06-2003).]

Deiussum
03-06-2003, 05:40 AM
// Possibly called on a key event
// Similar functions for rotating Y and Z
void OnRotateX(float angle, object o)
{
Matrix rot = createRotationMatrix(angle, 1.0, 0.0, 0.0);

// PRE multiply so it's that this last
// rotate is the last rotation done
o.rotMatrix = rot * o.rotMatrix;
}

void Display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

foreach(object o in objectlist)
{
glPushMatrix();
glTranslatef(o.pos.x, o.pos.y, o.pos.z);
glMultMatrixfv(o.rotMatrix);
o.Draw();
glPopMatrix();
}

}


By using a method like this you don't restrict the order of which axes you rotate around. So if you wanted you could rotate 45 degrees around the X, 25 around the Z, 10 around the X again, 15 around the Y, etc.


[This message has been edited by Deiussum (edited 03-06-2003).]

cosmicGirl
03-06-2003, 10:21 AM
thanks a bunch Del:

will this method also work if i switch between the rotation modes: ie: world and object? like i try to rotate an object around world's x-axis and then want to rotate an object around it's z-axis?

your method should work since these are after all just rotations that are kep in the matrix....is that correct?

Deiussum
03-06-2003, 10:36 AM
In that case you might want to keep 2 rotation matrices, and then do your render like so..

glPushMatrix();
glMultMatrix(o.worldRotMatrix);
glTranslatef(o.pos.x, o.pos.y, o.pos.z)
glMultMatrix(o.localRotMatrix);
o.Draw();
glPopMatrix();

Or, an alternative would be when you rotate it around the world axis, you could calculate a new x,y,z for the position.

cosmicGirl
03-06-2003, 12:41 PM
hmmm, why can't i just store all of them in one matrix ( rotation matrix).
after all of them are really just rorations that are done with glRotate() with different parameters

cosmicGirl
03-06-2003, 12:45 PM
oh one thing i have neglected to tell you is that i need to remember all of the transformations that were done to the object prior to rotation. So, if i have first rotated it around world's y-axis and then around its axis, i need to remember that worlds rotation in order to do that correctly.

Deiussum
03-07-2003, 05:15 AM
The order of operations does make a difference. Assume for instance that your model is such that it's local center is at 0,0,0. Initially when you draw it, it will be at the same location as the world origin, so rotations done on it appear to influence just the object. Now when you translate it away from the origin, your rotations will no longer appear to rotate it around it's own origin, but around the world origin.

Because the last thing applied to the matrix is effectively the first thing done, your order of operations is something like...

glRotate(rotation around world origin);
glTranslate();
glRotate(rotation around local origin);
drawObject();

About storing the location, etc. You should be doing that anyway. How else do you expect to re-draw the scene if the screen needs to be refreshed? Or for animation when you need to update the scene?

Turbo_Pascal
03-07-2003, 06:05 AM
Hello again,

I don't known how you people draw your object in the world, but what i do is that for each object that i am going to draw that can be later moved or rotated then i use internal variables to store the current world x,y,z object position and internal variable for store current xangle, yangle, zangle rotation for each object. This is easily done coding a litle class.

Then i use my x,y,z current object position and xangle, yangle and zangle in follow way:

//you said you want to rotate the world too, so then:

glpushmatrix(); //save current world state.
glrotate(world.xangle,1,0,0); //rotate by x
glrotate(world.yangle,0,1,0); //rotate by y
glrotate(world.zangle,0,0,1); //rotate by z

//now draw each object in follow way.

glpushmatrix(); //save current world matrix
gltraslatef(x,y,z); //move the world to the model position. x,y,z are object position.
glrotate(xangle,1,0,0); //rotate by x
glrotate(yangle,0,1,0); //rotate by y
glrotate(zangle,0,0,1); //rotate by z

drawobject(); //redraw object with current matrix

glpopmatrix(); //restore world to previus state. so we can continue drawing another object.

//Now do the same for next object.
//after all objects are draw then restore the matrix that we had before rotation the world.

glpopmatrix();


that's all you need to do for draw a object at different world position and be rotated correctly.

A note: me particulary I never rotate the world, i move/rotate the camera instead to the place that i want to see in my scene.


you can see few pics about my opengl world level editor at:
http://www.geocities.com/cyber_delphi/
http://www.geocities.com/cyber_delphi/tre3d/index.html


good luck litle girl.

Turbo Pascal.


[This message has been edited by Turbo_Pascal (edited 03-07-2003).]

[This message has been edited by Turbo_Pascal (edited 03-07-2003).]

cosmicGirl
03-11-2003, 12:10 PM
thanks to everyone who contributed to this post!!!
i have now figured out a way to do this, my problem was that i put all my misundertsandings together which made it a lot harder to solve http://www.opengl.org/discussion_boards/ubb/smile.gif