Problems with rotations

Started by
20 comments, last by ma_hty 15 years, 11 months ago
The picture lets me assume you want to rotate around local axes, while your code lets me assume you want to rotate around global axes. Perhaps your problem is to distinuish these 2 cases?

For this you must be aware that a transformation happens ever in its global co-ordinate frame. From your picture it seems me that you want to rotate around local axes. If so, you cannot simply use global axes! Instead, you have to figure out how the desired local axis is currently oriented in global space, and use that as argument to the glRotate function.

E.g. the y axis of your co-ordinate cross is
y = [ 0 1 0 ]T
in global space before any transformation. After a rotation by 90° around (global) x axis
y' := Rgx(90°) * y = [ 0 0 1 ]T
the result will point along the global z axis! See the difference: The global y axis is, of course, still [ 0 1 0 ]T w.r.t. the global space, but the local y axis is now [ 0 0 1 ]T w.r.t. the global space.

Now, rotating by glRotatef(90,0,1,0) around the (global) y axis will result in
yg" := Rgy(90°) * y' = [ 1 0 0 ]T
in a vector pointing along global x axis, while rotating around the "local" y axis using glRotate(90,0,0,1) results in
yl" := Rly(90°) * y' = [ 0 0 1 ]T
(doesn't change anything, because y axis rotated around y axis ;) ). Perhaps I've used a wrong sign anywhere, but the principle should became clear.


Using Euler angles means nothing else to use a specific order of a sequence of 3 glRotate invocations, each one with a defined axis. Several Euler triples exist; in principle your XYZ rotation is one of them. Using a quaternion means nothing more than to use a single glRotate, but with a "arbitrary" axis, i.e. where [ x y z ]T will typically differ all from 0. Although you can compute the belonging matrices by yourself, IMHO it doesn't effectively change anything significant here. So go with glRotate, but clarify which axes you want to rotate around.

[Edited by - haegarr on May 8, 2008 9:26:03 AM]
Advertisement
haegarr, thanks for your explanation. I understand all you say, but there's something that I don't understand. I explain you:

The program always run this sentences continously:

glRotatef(rotx,1,0,0);
glRotatef(roty,0,1,0);
glRotatef(rotz,0,0,1);

so, as you say, when rotx=90, roty=0 and rotz=0, I have the local y axis pointing out of the screen [0 0 1], along the positive global z axis. Is it ok? (I think so)

Then I change the value of roty=90 (rotx=90,roty=90,rotz=0), so when I compute the three sentences glRotatef, I have to obtain the local y axis looking at the direction of positive x axis [1 0 0]. Is it ok? (I think so)

But I don't get this. If you show my picture you can see that I get a rotation around the global z axis (out the screen) so the local y axis doesn't move, and get the local y axis [0 0 1].

What's happend, or what is what i don't understand?

Pds: I understand that glRotatef always rotate around global axis, as you say.

Thanks for your time.
I think you still don't consider all aspects. Let's see ...
Still using column vectors and right handed co-ordinate systems:

Quote:Original post by zorro68
so, as you say, when rotx=90, roty=0 and rotz=0, I have the local y axis pointing out of the screen [0 0 1], along the positive global z axis. Is it ok? (I think so)

Yes, its okay, because the mathematical equivalent is
v' := Rx(90°) * Ry(0°) * Rz(0°) * [ 0 1 0 ]T
== Rx(90°) * I * I * [ 0 1 0 ]T
== Rx(90°) * [ 0 1 0 ]T
== [ 0 0 1 ]T

Quote:Original post by zorro68
Then I change the value of roty=90 (rotx=90,roty=90,rotz=0), so when I compute the three sentences glRotatef, I have to obtain the local y axis looking at the direction of positive x axis [1 0 0]. Is it ok? (I think so)

Nope. Because the mathematical equivalent is
v' := Rx(90°) * Ry(90°) * Rz(0°) * [ 0 1 0 ]T
== Rx(90°) * Ry(90°) * I * [ 0 1 0 ]T
== Rx(90°) * Ry(90°) * [ 0 1 0 ]T
== Rx(90°) * [ 0 1 0 ]T
== [ 0 0 1 ]T

Keep in mind that (as already written in one of the previous answers) mathematically
A * B * C == ( A * B ) * C == A * ( B * C )
is all the same.

I suggest you: Don't think in code with stuff like this! Think in mathematical terms, and then translate that to code.

[Edited by - haegarr on May 8, 2008 11:14:14 AM]
I see what you say (I see better with maths).

So if I think in math terms, the solution of my problem is to multiply the three matrix before apply to the scene. (ok?)

But how can I do this with glRotatef function only?

PD: I have to do this in my paintGL() functions that is always running.

Thanks very much.
Quote:Original post by zorro68
So if I think in math terms, the solution of my problem is to multiply the three matrix before apply to the scene. (ok?)

Err, not primarily; I'm not sure whether I understood you correctly here, so my following explanation may be superfluous, but what should I do ;) Make yourself clear what happens step-by-step. Assume you use the pseudecode sequence
glLoadIdentity();
glRotate(A);
glRotate(B);
glBegin(...);
glVertex3(v);

Now, glLoadIdentity() prepares OpenGL's matrix stack:
M := I

The 1st rotation glRotate(A) then causes
M := I * A
being on the stack.

The 2nd rotation glRotate(B) then causes
M := I * A * B
being on the stack.

Applying that to the vertex glVertex3(v) then means
v' := M * v = I * A * B * v

Now, the sequence of invocations has computed this actually as
( ( I * A ) * B ) * v
but, as already said several times, it is mathematically absolutely the same as
I * ( A * ( B * v ) )
or any other (syntactically correct) arrangement of parantheses!

In other words, using glRotate has definitely build up the matrix as a whole internally before the first vertex is transformed by it, but it plays no role for the result (only for the performance). You could use quaternions, multiply them together, convert the result to a matrix, and use glMultMatrix; whatever ... it'll change nothing.

Unfortunately, I still have no real clue what you are desired to reach. So I tell you again what's going wrong, but am not able to hint in the correct direction. I'm pretty sure that the results you want to reach are possible using glRotate (it must be since glRotate does nothing more than converting into a rotation matrix and multiply that). Could you perhaps illustrate in detail what should happen? And why are you forced to use that specific sequence of rotations?
I have no clue what he the OP is trying to do, but I have tried the rotations you asked for and found the cube will end up back at the starting point after you move the axes in the order you wanted.

To check this yourself grab a dice, mark all 6 sides as front, back, left, right, bottom, top. Now keep the front facing you to start with, rotate X,Z,Y mind you you need to rotate in a CW direction when you do this. You will be back at the front facing you after all three have moved. Is this what you want?
If you are trying to implement a rotation user interface, do not use Euler angle.

Using Euler angle is a bad idea.

By the way, this is going to help...
http://www.gamedev.net/community/forums/topic.asp?topic_id=463800
u can use eular angles no problems, what u shouldnt do though is perform several glRotatef(..) commands in a row as this will often end in gimbal lock
see the matrix faq

read this
http://www.j3d.org/matrix_faq/matrfaq_latest.html

Q33. How do I combine rotation matrices?
Q34. What is Gimbal Lock?
Quote:Original post by zedz
u can use eular angles no problems, what u shouldnt do though is perform several glRotatef(..) commands in a row as this will often end in gimbal lock

How are you using Euler angles w/o performing several glRotates in row (or, as an equivalent, compose the matrix by yourself)? Euler angles means ever a composition of consecutive rotations.
Quote:Original post by haegarr
In other words, using glRotate has definitely build up the matrix as a whole internally before the first vertex is transformed by it, but it plays no role for the result (only for the performance). You could use quaternions, multiply them together, convert the result to a matrix, and use glMultMatrix; whatever ... it'll change nothing.


Yes you are right.

Quote:Original post by MARS_999
To check this yourself grab a dice, mark all 6 sides as front, back, left, right, bottom, top. Now keep the front facing you to start with, rotate X,Z,Y mind you you need to rotate in a CW direction when you do this. You will be back at the front facing you after all three have moved. Is this what you want?


I'm going to explain you what I need?

Quote:Original post by ma_hty
If you are trying to implement a rotation user interface, do not use Euler angle.
Using Euler angle is a bad idea.


I have read this. By the way, thanks for the gimbal lock discussion.

Quote:Original post by zedz
read this
http://www.j3d.org/matrix_faq/matrfaq_latest.html


It's a very good summarized in maths.


I thought the rotation problem was a closed theme (in maths and in opengl), but I can see that there's a lots of doubts.

I'm going to explain what I am doing and what is my problem. I'm programming a molecular viewer with opengl. I have seen other molecular viewer and when you click with the mouse into the scene and move the mouse you rotate all the scene (in my case, the molecule). But I have seen that all of them has a problem, if you rotate the scene with the mouse you can see the rotation of the scene and it seems that is all ok. But you are rotating the scene sometimes around global axis and sometime around local axes. This is the same effect that I am having when I use, three times, glRotatef function. Due to the matrix order multiplication, it seems that you are rotating the scene sometime around its local axes and sometime around its global axes. (Show what I'm trying to say in the picture)

Free Image Hosting at www.ImageShack.us

What I am trying to program is that when I click and move the mouse (left click + left-right move around x axis, left click + top-down move around y axis, right click + left-right move around z axes, and right click + top-down zoom the scene) or move the slices the scene seems to rotate ALWAYS around the global axes, or seems to rotate ALWAYS around the local axes. But not a mix of them.

I hope you understand me. If not, show me and I'll try again.

Pd: My main problem is that I cannot explain in English like I would like.

Thanks to all of you.

This topic is closed to new replies.

Advertisement