PDA

View Full Version : Rotation Issues

EJDSlayer
04-17-2009, 07:11 AM
Hey, I am fairly new to OpenGL and I am currently in the process of programming a game. I am trying to make a cube that can rotate/translate (to give the affect that it is rolling) around the X/Z plane.

I am currently using :

glRotated(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotated(angle1, 0.0, 1.0, 0.0); //rotate on the y axis
glRotated(angle2, 0.0, 0.0, 1.0); //rotate on the z axis

to perform the rotation, but as the object has local co-ordinates the axis position/direction is constantly changing with each rotation. Can anyone tell me how I can keep a fixed axis by which the object rotates around, rather then the axis rotating and the object following it.

I have tried creating 4 rotate functions per axis, so each one rotates by 90, then when the final one finishes, they are all reset back to 0. It was a very long shot but it didnt work obviously!

From what I can gather glMultMatrix seems to be the way forward, but I cannot get my head around the coding at all.

If it helps (anyone feels kind/bored enough to do the algorithm for me :) ) I have 3 rotation matrices as can be seen above, and my algorithm for rotation is :

if (Left == true)
{
//if (angle == 0){
angle2 = angle2 + 18;
xDisp = xDisp - 1;
Sleep(50);

whereby the boolean is set to false via an if statement when the angle reaches 90 / 180/ 270 respectively, and the left key is an idlefunction, so that the object will rotate by itself through those angles. I also have an if conditional for when it reaches 360 that resets the angle back to 0.

Any help will be very appreciated as I have been working on this for many hours, and all i want is a cube that can be user controlled and rolls around a screen. At the moment I feel ti would be easier to get blood from a stone.

[EDIT] I forgot to add that I have also tried transforming the cube back to the origin, then rotating, but obviously as the axis are changing directions, this does not work either.

Kind Regards,

EJDSlayer

EJDSlayer
04-17-2009, 08:40 AM
[UPDATE]

Still digging my hole, I just tried to create a rotation matrix but have no idea how to implement it properly, or even if it is a possible solution, but this is it:

float RotationMatrix[16];

void Rotate(){

RotationMatrix[0] = ((1 - cos)*(angle*angle)) + cos;
RotationMatrix[1] = ((1-cos) * angle * angle1) - (sin * angle2);
RotationMatrix[2] = ((1-cos) * angle * angle2) + (sin * angle1);
RotationMatrix[3] = 0;
RotationMatrix[4] = ((1-cos) * angle * angle1) + (sin * angle2);
RotationMatrix[5] = ((1 - cos)*(angle1*angle1)) + cos;
RotationMatrix[6] = ((1 - cos)*(angle1*angle2)) - (sin * angle);
RotationMatrix[7] = 0;
RotationMatrix[8] = ((1-cos) * angle * angle2) - (sin * angle1);;
RotationMatrix[9] = ((1 - cos)*(angle1*angle2)) + (sin * angle);
RotationMatrix[10] = ((1 - cos)*(angle2*angle2)) + cos;
RotationMatrix[11] = 0;
RotationMatrix[12] = 0;
RotationMatrix[13] = 0;
RotationMatrix[14] = 0;
RotationMatrix[15] = 1;

RotationAnswer[0] = RotationMatrix[0] + RotationMatrix[4] + RotationMatrix[8] + RotationMatrix[12];
RotationAnswer[1] = RotationMatrix[1] + RotationMatrix[5] + RotationMatrix[9] + RotationMatrix[13];
RotationAnswer[2] = RotationMatrix[2] + RotationMatrix[6] + RotationMatrix[10] + RotationMatrix[14];
RotationAnswer[3] = RotationMatrix[3] + RotationMatrix[7] + RotationMatrix[11] + RotationMatrix[15];
}

Is this a valid way to do it, if so how would i implement it? I would also prefere an easier solution then this if there is one.

Thanks :)

ZbuffeR
04-17-2009, 09:10 AM
No need to fill in the matrices by hand.
just using glTranslate/glRotate/glPushMatrix/glPopMatrix should be enough.
http://glprogramming.com/red/chapter03.html#name8

Rosario Leonardi
04-17-2009, 09:47 AM
Cool!! The rotating cube game. Remember to add some bosses like a rotating cone or something else. :D

Using multiple glRotate can lead to some problem (http://en.wikipedia.org/wiki/Gimbal_lock) one solution can be quaternion, but if you are not a maths expert they can give you an huge headache. :p
For simple rotation (max two axis) zBuffer solution works fine, but for more general solution you can build the matrix by hand
just remember that matrix columns are the axis of your object an you can easily compute any orientation.

This is a DirectX matrix, in openGL the matrix is transposed. :)
http://img211.imageshack.us/img211/3361/matrixtransformationir7.png

MaxH
04-17-2009, 11:50 AM
I might be able to help if I understood your question. From your explanation I can't tell what is happening, nor what you really want to happen. Can you post a small, GLUT, program that demonstrates your problem?

EJDSlayer
04-18-2009, 04:18 PM
Hey, thanks for replying! I will have a look at quaternions, but from the brief glimpse I had of them, it looks rather confusing! In regards to the Z Buffer, what would that entail, I am a complete rookie when it comes to OpenGL. ALso how would building the matrix by hand work, would it be like the code in my second post? Also how would i implement it?

MaxH sorry if I wasnt clear, I have an object, a cube, its made up of vertices defined by me, not the predefined cube function.

It is then called by a function which has a translation formula to move the object back to the world origin, then a rotation formula which rotates the cube in the direction of the cursor key pressed. The rotation is the issue I have, because when you rotate the object once, the axis then change, because for some reason in OpenGL the axis seem to rotate and the object follows the axis, rather then the object rotating around the axis like a normal program! Therefore when i press another cursor key the function no longer makes the object move the right way as the objects axis have been changed. So how would i overcome this problem? Is there anyway to make the object rotate about its axis, rather then the axis rotating too?

I have found a very tedious way to overcome this, and have implemented it to some degree, and it involves one of the worlds longest nested if statements. Which takes every possible combination of axis positions, and then works out which axis is facing which way, and rotates it along the corrisponding axis. This is a very long process, which requires 64 if statements for every key! So i'm not too keen on implementing it fully.

If the above description doesnt help, I will post up my current code to see if anyone can make heads or tails of it. At the moment it is a bit of a mess, as four of us are working on various aspects.

Thanks for the replies.

ZbuffeR
04-19-2009, 02:02 AM
If yes, then what did you not understand ?

EJDSlayer
04-19-2009, 04:58 AM
Hey, sorry didnt notice the sly link there :)

I will have a look at that and have a go at implementing it tommorrow :)

Will give you an update of how it goes then :)

MaxH
04-19-2009, 12:40 PM
Hey, thanks for replying! I will have a look at quaternions, ... Quaternions are not necessary.

MaxH sorry if I wasnt clear, I know you tried to be clearer this time, but your language is still too vague for me to be able to help you. There are Object Space rotations, Screen Space rotations, and Euler Sequence rotations. Sounds like you have coded up an Euler Sequence and decided you don't like it. When you rotate objects using a sequence of glRotate calls you get Euler rotations. They only 'feel' or 'look' right if done in a certain order. I'm guessing that you want either Screen or Object Space rotations, but I can't tell from your language.

... because for some reason in OpenGL Not just OpenGL - all graphics libraries behave the same way because the underlying math of rotations is matrix multiplication.

then the object rotating around the axis like a normal program! There is no such thing as a 'normal' program. There is only what you want.

If the above description doesnt help, I will post up my current code ... That would be best. But let me point you to some code I posted recently which shows a way to set up Object Space rotations. It's GLUT based. If this doesn't do what you want, then you probably want Screen Space rotations.

Object Space Rotations (http://pastebin.com/m343f77bd)

EJDSlayer
04-20-2009, 04:52 AM
Hey,

I looked at that bit of code before, that is currently what I am using and is basically what I do not want. As i said before I am a complete beginner to OpenGL, so have absolutely no idea of types of rotations, or their names. As seen in your code, when you rotate around the y axis for example, the orientation of both the x and z changes, therefore what originally would of made a z rotation rotate right, could end up rotating left. What i would like is an object where the axis are fixed, so pressing for example the right key will always rotate right. Is this a screen rotation? If so how would i implement it?

thanks

EJDSlayer
04-20-2009, 04:58 AM
Okay I decided to post up all my code which deals with rotation, maybe this will better help you understand where I am going wrong...

The Main Rotate / Translation Function

void cube(void)
{

glPushMatrix();
//For Rotation and Translation
glTranslatef((2.5+xDisp),(2.5),(2.5+zDisp));

glRotated(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotated(angle1, 0.0, 1.0, 0.0); //rotate on the y axis
glRotated(angle2, 0.0, 0.0, 1.0); //rotate on the z axis

// Rotate();

glTranslatef(-(2.5),-(2.5),-(2.5));

drawcube();

glPopMatrix();
}

The Functions That Change The Angle / Axis Of Rotation

void cubeSpinUp (void)
{
if (Up == true)
{
angle = angle - 18;
zDisp = zDisp - 1;
Sleep(50);
if (angle == 90 || angle == 180 || angle == 270 || angle == -90 || angle == -180 || angle == -270){
Up = false;
}
else if (angle == 360 || angle == -360 || angle == 0) {
angle = 0;
Up = false;
}
}
}

void cubeSpinDown (void)
{
if (Down == true)
{
angle = angle + 18;
zDisp = zDisp + 1;
Sleep(50);
if (angle == 90 || angle == 180 || angle == 270 || angle == -90 || angle == -180 || angle == -270){
Down = false;
}
else if (angle == 360 || angle == -360 || angle == 0) {
angle = 0;
Down = false;
}
}
}

void cubeSpinRight (void)
{
if (Right == true)
{
//if (angle == 0){
angle2 = angle2 - 18;
xDisp = xDisp + 1;
Sleep(50);

if (angle2 == 90 || angle2 == 180 || angle2 == 270 || angle2 == -90 || angle2 == -180 || angle2 == -270){
Right = false;
}
else if (angle2 == 360 || angle2 == -360 || angle2 == 0) {
angle2 = 0;
Right = false;
}
}

void cubeSpinLeft (void)

{
if (Left == true)
{
//if (angle == 0){
angle2 = angle2 + 18;
xDisp = xDisp - 1;
Sleep(50);

if (angle2 == 90 || angle2 == 180 || angle2 == 270 || angle2 == -90 || angle2 == -180 || angle2 == -270){
Left = false;
}
else if (angle2 == 360 || angle2 == -360 || angle2 == 0) {
angle2 = 0;
Left = false;
}
}

The Keys That Are Used To Control The Movement.

case 'W':
case 'w': MapUp = true;
Up = true;
glutIdleFunc(cubeSpinUp);
glutPostRedisplay();
break;

case 'S':
case 's': MapDown = true;
Down = true;
glutIdleFunc(cubeSpinDown);
glutPostRedisplay();
break ;

case 'A':
case 'a': //Beep(425,90);
//Beep(450,50);
MapLeft = true;
Left = true;
glutIdleFunc(cubeSpinLeft);
//count = 0;
break ;

case 'D':
case 'd': //Beep(425,90);
//Beep(450,50);
MapRight = true;
Right = true;
glutIdleFunc(cubeSpinRight);
break ;

EJDSlayer
04-20-2009, 05:17 AM
Can anyone perhaps send me a link to a code that implements a matrix, preferably a rotation one? Just so i can see how to implement mine and see if i can do it that way? unless you think this is totally unneccesary

martinsm
04-20-2009, 07:15 AM
http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three

EJDSlayer
04-20-2009, 09:54 AM
Hey,

the wikipedia doesnt really help me, I understand how to do matrix multiplication, but cannot figure out how to program it. For example how would i update the x and z variables in the matrices, then relay the answer to move the cube?

MaxH
04-20-2009, 11:06 AM
EJD - I'm guessing that the type of rotations you want to do are what I call 'Screen Space' rotations. This is where objects in the scene always rotate around axes fixed to the screen (i.e. x to the right, y is up, and Z is out of the screen). I've extended the code I posted previously to do both object and screen space rotations and posted it as a new thread in this forum. Good luck. Let me know how it goes.

EJDSlayer
04-21-2009, 06:08 AM
Yeah that seems to be what I want :) Thanks for all your help. Just out of curiosity, where your floor rotates with it, I presume that can be fixed with a push and pop somewhere along the line, so it applies purely to the cube and not everything?

MaxH
04-21-2009, 09:45 AM
Yeah that seems to be what I want :) Thanks for all your help. Just out of curiosity, where your floor rotates with it, I presume that can be fixed with a push and pop somewhere along the line, so it applies purely to the cube and not everything? The names 'Screen Space' and 'Object Space' rotations should make some sense now that you've run that demo. It is not necessary to use push and pop to make the floor not rotate with the cube. Simply move the 'Draw_Floor' call from line 245 to line 247 (i.e. before the MultMatrix call).

EJDSlayer
04-21-2009, 10:13 AM
Okay thanks for all your help! :) Just a few more things to straighten out with this program and I may actually have a game up and running! Another quick question, say the screen was to rotate (e.g. you could move the camera), would that then mean the screen space rotations would happen in a different direction?

MaxH
04-21-2009, 05:30 PM
Okay thanks for all your help! :) Just a few more things to straighten out with this program and I may actually have a game up and running! Another quick question, say the screen was to rotate (e.g. you could move the camera), would that then mean the screen space rotations would happen in a different direction? This depends on how you code it up and what you really want to happen. You COULD code it up so that the X-Y-Z axes appear to rotate when the camera moved, and have your objects rotate around the changed X-Y-Z axes. I wouldn't call that 'Screen Space' rotations anymore. Or you could code it up so that wherever your camera is, the objects rotate around the screen axes (x->right, y->up, z->out). It comes down to what you want and what order you put the multmatrix and Lookat commands in.