How to rotate about global axes?

Started by
7 comments, last by NPS 14 years, 5 months ago
Hi, everybody. I'm new here. Anyway, I've got a 3D object and want to rotate it. See, I'm writing a 3D Tetris and I want to be able to rotate it about global axes. glRotate() function rotates objects about their local axes. Actually it rotates coordinate system and then you're able to draw in that rotated system. The thing is in 3D Tetris when user presses for example 'Q' button he wants to rotate the brick about the X axis CCW. Then he presses for example 'W' button to rotate it about the Y axis. But the object rotates about its rotated Y axis which is not what the user wants. It's not what I want either. How to rotate about global axes (about axes which remain the same for the whole time)?
Advertisement

X - glRotatef(45.0, 1, 0, 0);
Y - glRotatef(45.0, 0, 1, 0);
Z - glRotatef(45.0, 0, 0, 1);

What's wrong with that?
You've got some object. You rotate it about Y axis CCW 90 degrees. You can say (form your point of view) it rotates from left to right. Then you rotate it about X axis CCW 90 degrees. If you rotated it about global X axis, it should rotate from up to down. But when you use glRotate(), it rotates about its local Y axis, so it rotates like clock's hand (all the time you observe form the same point).

I hope that cleared things up a little.
Quote:glRotate() function rotates objects about their local axes.
No it doesn't. All glRotate() does is build a rotation matrix and apply it to the top of the matrix stack; what effect this has (or appears to have) depends on the transforms (if any) that preceed or follow the rotation.

In any case, it sounds like what you're after is incremental rotations (in increments of 90 degrees, in this case). To do this, you'll need to track the object's orientation yourself rather than relying on glRotate().

There's more than one way to do this, but if I were implementing a game where all rotations were in increments of 90 degrees (such as the 3-d Tetris-like game you're describing), I'd probably create a table of all 24 (?) unique axis-aligned orientations, along with virtual links between entries in the table corresponding to input events (e.g. if you're at orientation 12, pressing 'Q' takes you to orientation 21). Taking this approach would ensure that the results would be deterministic and that there would be no accumulated numerical error.
That sounds like an idea. It has its advantages. Although, when implemented it would look like a big monster with a lot of switches and cases. Should work but I'm not sure if it could be called "A good style of programming" and if it's a good way to do it.

Anyway, it's an option and thank you for that.
Quote:Although, when implemented it would look like a big monster with a lot of switches and cases.
Only if that's how you choose to implement it ;)

The way I'd probably do it is to create a 2-d array (hard-coded, read from a file, or generated procedurally) that defined what input events took you from orientation to orientation. Let's say for the sake of argument that there are 24 orientations (I think that's right) and 4 control keys for rotating. The array would then have 24 rows (one for each orientation) and 4 columns (one for each control key). The entry at i, j would tell you what orientation to switch to when you press control key i while at orientation j. Make sense?

The hard part, such as it may be, is creating the array, but even that shouldn't take you too long, even if you just hard-code it. The actual code to change orientations would probably end up looking something like this:
int get_new_orientation(int current_orientation, int control_key) {    return orientation_map[control_key][current_orientation];}
Which, as you'll notice, is not a huge switch statement :)
I figured it out. To rotate about local axes call glRotate in order you want to rotate. To rotate about global axes call glRotate backwards - last rotation goes first, first goes last.

Example:

You want to rotate object about local axes:
1) about X axis
2) about Y axis
3) about Z axis
Write:
1) glRotate(angle, 1.0, 0.0, 0.0);
2) glRotate(angle, 0.0, 1.0, 0.0);
3) glRotate(angle, 0.0, 0.0, 1.0);

You want to rotate object about global axes:
1) about X axis
2) about Y axis
3) about Z axis
Write:
1) glRotate(angle, 0.0, 0.0, 1.0);
2) glRotate(angle, 0.0, 1.0, 0.0);
3) glRotate(angle, 1.0, 0.0, 0.0);

jyk, I don't get your idea on creating the array (I'm just saying as I've solved the problem).
Quote:jyk, I don't get your idea on creating the array (I'm just saying as I've solved the problem).
Well, if you've fixed the problem, I guess you don't need the array :)

I have to admit though that I'm not sure how you're going to be able to apply successive incremental rotations using only glRotate(). Have you actually tested it using multiple rotations with alternating axes? (E.g. x, x, y, x, y, x, etc.)

Maybe I just have the wrong idea about what you're trying to do (if so, the solution I proposed probably isn't relevant anyway).
The nice thing is I've implemented some kind of rotations queue. It was before I found out about the described problem. But when I got my solution I just changed changed the code so that it performed rotations from the last one to the first. So I didn't even have to change much. And it works nicely.

But still, can you describe your idea? I'm just curious. How do you want to create your array?

This topic is closed to new replies.

Advertisement