rotate around own axis

Member
Posts: 94
Joined: 2008.08
Post: #16
I definitely have to stop using Euler angles as ive spotted more problems; specifically with moving in the direction your pointing. Eg, if you rotate 180 around y and then rotate 180 around x, so essentially your pointing the same way you started; but it will mess up the move ability as it still acts as though you are facing the opposite direction.

On a side note, I think there is a typo in the Matrices tutorial:

struct Matrix {
float m[16];
}
typedef struct Matrix Matrix;

should be:
struct Matrix {
float m[16];
};
typedef struct Matrix Matrix;

it took me a while to spot it. Mainly cos Im still new to C Smile
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #17
Ooh, good catch. Thanks! Will fix...
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #18
ok, I think Ive got the rotation code figured out. Fairly simple when it came to it Smile
Im still maintaining my eular angles but here's what im doing:

quat = quaternion_from_euler(viewAngle.x/RAD_TO_DEG, viewAngle.y/RAD_TO_DEG, viewAngle.z/RAD_TO_DEG);

Quaternion_toAxisAngle(quat, &newV, &myangle);
Matrix matrix;
matrix = Quaternion_toMatrix(quat);
glMultMatrixf(matrix.m);

But like I said earlier, Im still having problems moving forward in the direction you are pointing. Im currently doing:

viewSpeed.x =cos((viewAngle.y+270)/RAD_TO_DEG);
viewSpeed.y =cos((viewAngle.x+90)/RAD_TO_DEG);
viewSpeed.z =((cos((viewAngle.y+180)/RAD_TO_DEG)/2) + (cos((viewAngle.x+90)/RAD_TO_DEG))/2);

viewPosition.x+=viewSpeed.x;
viewPosition.y+=viewSpeed.y;
viewPosition.z+=viewSpeed.z;

But, as i mentioned earlier this really messes up and rotating x around 180 and then y around 180, as it moves me further away instead of closer to. Is there a better a way of doing this?

Thanks again!
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #19
wonza Wrote:Im still maintaining my eular angles

...

But, as i mentioned earlier this really messes up and rotating x around 180 and then y around 180, as it moves me further away instead of closer to. Is there a better a way of doing this?

As I said before, Euler angles really don't work at all. Don't use them. Use a quaternion to store the cumulative state of each rotation. If you're keeping Euler angles around and recalculating your rotation every time based on them, you will keep running into the sort of problems you're seeing here.

The quaternion solution is reasonably simple; just start with the identity, apply rotations to it when you want to rotate, and allow those rotations to accumulate over the lifetime of your object (as in, don't restart with the identity quaternion every frame). So, when you want to turn left, simply do this:

Code:
Vector axis = {0.0f, 1.0f, 0.0f};
Quaternion_rotate(&orientation, axis, some_positive_value_in_radians);

Rotations will be on the quaternion's local axes; if you want to rotate on a world axis, multiply your axis vector by the inverse of the quaternion before rotating, like so:

Code:
Vector axis = {0.0f, 1.0f, 0.0f};
axis = Quaternion_multiplyVector(Quaternion_inverted(orientation), axis);
Quaternion_rotate(&orientation, axis, some_positive_value_in_radians);

Also, as AnotherJake mentioned, you may need to normalize your quaternion occasionally, but you probably won't have to worry about that unless you see your object getting mysteriously larger or smaller after having been rotated a lot. (For the record, I've never seen it happen in practice, but it certainly could if your quaternion has a long lifetime is rotated a lot.)

To move forward relative to a quaternion orientation, you can simply do this:

Code:
// IDENTITY_DIRECTION is the forward vector in the identity orientation
Vector direction = IDENTITY_DIRECTION;

direction = Quaternion_multiplyVector(orientation, direction);

position.x += SPEED * direction.x;
position.y += SPEED * direction.y;
position.z += SPEED * direction.z;
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #20
ThemsAllTook Wrote:(For the record, I've never seen it happen in practice, but it certainly could if your quaternion has a long lifetime is rotated a lot.)

[Slightly Off-Topic -- doesn't directly help the OP ATM] I've seen it happen with relatively large quaternion deltas. It only *appeared* to happen when the quaternion was possibly near some mathematical singularity (i.e. near one of its own internal axes), so even at that, it didn't happen very often. I don't know how the math worked out like that, but it looked almost like a weird little gimbal lock of some kind at certain points during the rotation, with the object speeding up and rotating around that point temporarily -- hard to describe. Normalizing after every few of those "large" deltas fixed it. I've since decided to just normalize every update for simplicity (three quat delta adds (x, y, z)). Doesn't seem to affect performance much. Seems like the rendering code still winds up at the top of the list in Shark, and quaternion code often showing up a distant second. I suppose if it did start to affect performance, one could use something like that fast InvSqrt, but even then, it seems like hardware nowadays handles sqrtf pretty quick (and floating point calcs in general).
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #21
thats exactly what i was looking for, thanks! Smile

I seem to have a problem with the direction movement though. Im doing this:
Vector direction = {0.0f, 0.0f, -1.0f};
direction = Quaternion_multiplyVector(orientation, direction);

This works for the most part, but for particular angles and positions it will suddenly start moving me away from the object instead of close to- similar to the old method. Do I need to be altering the direction vector based on its current direct?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #22
No, that should work... Any specific examples you can give of it misbehaving? (Which angle, etc.)
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #23
here is some of my debug:

positions: vx: 3.705867, vy: -26.964016, vz: -5.705433
angles: vax: 25.000000, vay: 220.000000,

so I moved forward, up and to the right of the center, then turned towards the centre and tried to go forwards, but it sent me back instead. very strange.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #24
Looks OK. The only suspicious thing I see is that you say you moved up, but your y coordinate is negative. Unless you meant to say down, there may be a math error somewhere in your code.

It looks like there was an error in the code I posted earlier for my quaternion-based gluLookAt substitute. I don't know if you're actually using that, but if you are, you'll want to invert the quaternion before multiplying the current matrix by it. So, invert if the thing that's rotating is the camera; don't invert if the thing that's rotating is the object being viewed from another perspective.

If that doesn't help, could you post the multiply-by-orientation-and-move-forward code you're using, as well as your drawing transformation code?
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #25
I decided to use the multiply-by-orientation-and-move-forward code you helped me with:

//rotate on button pressed (there are 3 others of these for look up,down,left,right)
Vector axis = {0.0f, -1.0f, 0.0f};
axis = Quaternion_multiplyVector(Quaternion_inverted(orientation), axis);
Quaternion_rotate(&orientation, axis, inc);


//thrust applied/ move forward
Vector direction = {0.0f, 0.0f, -1.0f};
direction = Quaternion_multiplyVector(orientation, direction);

viewSpeed.x+=direction.x;
viewSpeed.y+=direction.y;
viewSpeed.z+=direction.z;


//update view
viewPosition.x+=viewSpeed.x;
viewPosition.y+=viewSpeed.y;
viewPosition.z+=viewSpeed.z;
glTranslatef(-viewPosition.x, -viewPosition.y, -viewPosition.z);


//rotate on quat
Matrix matrix;
matrix = Quaternion_toMatrix(orientation);
glMultMatrixf(matrix.m);


hope this helps, thanks!
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #26
This might just be the way you're doing the view transformation. See if it helps to do things in this order and invert the orientation:

Code:
matrix = Quaternion_toMatrix(Quaternion_inverted(orientation));
glMultMatrixf(matrix.m);

glTranslatef(-viewPosition.x, -viewPosition.y, -viewPosition.z);
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #27
I just tried- unfortunately it didnt seem to work. It didnt move towards the objects at, and then when i rotated they dissappeared. I also tried keeping that order but removing the inverted part.. and i tried keeping the original order but leaving in the inverted function; but neither worked.
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #28
I think I may have it!

I just inverted the quat then multiplied it before passing it into the direction vector:
Vector direction = {0.0f, 0.0f, -1.0f};
direction = Quaternion_multiplyVector(Quaternion_inverted(orientation), direction);

Its made me realise I am going to have to add buttons for rotating around z though Smile

Again, thanks for all your help!! Smile
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #29
Cool, glad to hear it's working for you!
Quote this message in a reply
Member
Posts: 94
Joined: 2008.08
Post: #30
As its very related I thought Id post here. I've now got my camera properly working, and ships too; as they move around randomly in the direct they are point, and ive also got some at random to point towards the camera and move towards it. Now again, Im having problems but with getting missiles working.

When i press another button Ive got a missile to become active and ive moved it to the position of the camera and then firing away from the camera. My problem is that I've setting the missiles orientation to that of the camera, which I think should make it move in the direction you are looking, but it just does not want to seem to work. Here is some of the relevant code:

Code:
glPushMatrix();
    glTranslatef(AllMissiles[m].Position.x, AllMissiles[m].Position.y, AllMissiles[m].Position.z);    
    moveMissile(&AllMissiles[m]);        
    Matrix matrix;
    matrix = Quaternion_toMatrix((AllMissiles[m].missileOrientation));
    glMultMatrixf(matrix.m);
    showMissile();
glPopMatrix();


//create new missile
AllMissiles[m].active = TRUE;
AllMissiles[m].Position = viewPosition;
AllMissiles[m].missileOrientation = orientation;

Thanks for any help!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Seperating Axis Theorem Code mikey 5 4,246 Oct 9, 2010 03:25 PM
Last Post: Oddity007
  Separating Axis Collision Detection Joseph Duchesne 4 3,884 Dec 22, 2005 10:18 AM
Last Post: Leisure Suit Lurie
  Separation axis collision detection SOUR-Monkey 5 5,683 Mar 24, 2005 01:23 AM
Last Post: DoG