Archived

This topic is now archived and is closed to further replies.

Orientation using matrices

This topic is 6150 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Can someone please give TRUE and FALSE answers to the following statements, then maybe provide some advice (see my problem further down): (1) Euler angles are susceptible to Gimbal Lock. Matrices & Quaternions are not. (2) Rotating around all three axes at once (yaw, pitch & roll) using matrices can lead to loss of a direction of freedom. (3) Diana Gruber's rotation matrices (see her GDNet article on Quaternions - Programming/3D-Theory) eliminate this DOF problem when using matrices for orientation. I have a problem with my camera/object orientations (objects rotated with both yaw and pitch are not orientated correctly), and I would like to know how if I can eliminate this from my current orientation system (I currently rotate up, down & forward unit vectors for both the camera and objects). Is there an easy way of adjusting this system so that my vectors/axes are in the same format as they are in Diana's matrices, so that I can try representing orientatations her way? Paulcoz. Edited by - paulcoz on January 29, 2001 11:51:54 PM

Share this post


Link to post
Share on other sites
Just a quick point to help you out:

heh, "its in the matrix"

For any given view matrix (but before any perspective is applied), the orientation is contained, value for value, precomputed in the matrix.

take your regular 3x3 matrix, call it "m":
the first(x) column is the "left" vector
the 2nd(y) is the "up" vector
and the 3rd(z) column is the "at" or "direction" vector.

Left.x = m[0][0]; Up.x = m[0][1]; Dir.x = m[0][2];
Left.y = m[1][0]; Up.y = m[1][1]; Dir.y = m[1][2];
Left.z = m[2][0]; Up.z = m[2][1]; Dir.z = m[2][2];

although i'm not sure if they need normalized or not, but i'd imagine so (i just always do...)

what i do every frame to is generate my view matrix ( from a quaternion ), then extract the orientation from it, and use that for the camera, like moving directions and stuff.

hope that helps you out.

plus, if you know how to transform a quaternion into a matrix, you can skip the matrix construction and go right from quaternion to vectors.


Edited by - Succinct on February 1, 2001 7:31:31 PM

Share this post


Link to post
Share on other sites
Succinct,

At the moment I have a 3x3 matrix like you say - with the left vector row one, the up vector row two and the forward vector row three.

Each time I need to orientate an object I set the 3x3 to an identity matrix, then apply a pitch rotation to the identity, then applying a yaw rotation to the combined (identity & pitch) rotation, then applying a roll rotation to the combined (pitch & yaw) rotation.

I get the objects coordinates in the transformed coordinate system by multiplying a point with the resulting matrix - it works o.k., until I try to do two rotations at once (eg. pitch & yaw).

The problem I have understanding Diana's tutorial is that she refers to an axis-angle representation and I'm not real familiar with that (I understand the idea, but have not tried to get it working).

I'm finding these combined rotations really frustrating - I know I have to eliminate Gimbal lock (which I think is what I am experiencing), but noone can explain quaternions in simple enough terms for me to understand - and I do not use anything in my program until I understand it fully.

Paulcoz.

Edited by - paulcoz on February 1, 2001 8:24:41 PM

Share this post


Link to post
Share on other sites
paulcoz
Your getting Gimbal Lock because your rebuilding your matrix for each frame. Don''t set it to identity each frame, just add some rotations on top of what already exists in the matrix and you will not suffer from it any more.
Just rotate the old matrix by whatever increment you want and forget about the roll/yaw/pitch variables. You''ll find that you don''t really need them at all (Store the matrix with your camera/object instead). You will have to normalize the matrix from time to time as floating point errors creep in, but that is not to much of a problem. Just pick one matrix per frame and normalize it.
Another nice side effect of this is, if you have a lot of objects on screen that don''t often move(trees/tables/buildings...), you don''t have to recalculate matrices for them every frame.

Share this post


Link to post
Share on other sites
Hi Boke,

"Just rotate the old matrix by whatever increment you want and forget about the roll/yaw/pitch variables"

So instead of doing this:

Take the values captured from the mouse and add them to yaw and pitch values for the camera, then use these to construct a new rotation matrix each frame.

I should do this?

Take the values captured from the mouse and construct a new rotation matrix from these incremental values, then multiply the old rotation matrix by the new matrix.

Do you have any idea how many incremental rotations you can do before the matrix must be normalised (no. of frames)?

Thankyou,
Paulcoz.

Edited by - paulcoz on February 6, 2001 2:32:26 AM

Share this post


Link to post
Share on other sites
you can just forget about needing to orthonormalize the matrix if you skip it all toghether and just use quaternions.

what you can do is keep a single quaternion that will represent the current orientation, then have it "accumulate" the changes.
this is what i do: (well, something like it off the top of my head)
  static Quaternion CurrentOrientation = ZeroQuaternion;

// dx, dy, and dz are the euler changes in orientation

Quaternion Delta = ConvertEulerToQuaterion( dx,dy,dz );

CurrentOrientation = CurrentOrientation*Delta;
// or

CurrentOrientation = Delta*CurrentOrientation;


try both the pre-multiply and post-multiply to see which you like better.

then you can go directly from quaternion to rotation matrix or to axis angle. if you need any of the above conversion code, either look for Jeff Lander and his Quaternion stuff, try www.magic-software.com, e-mail me and i''ll send ya my code, or just ask me to post it here

hope it''s what ur looking for


Thank you for your bandwidth.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~Succinct Demos Online~


"<DiLLiGaS> I''m suprised nobody takes M$ to court for rape... The OS keeps going down on you w/o your permission."

Share this post


Link to post
Share on other sites
"Take the values captured from the mouse and add them to yaw and pitch values for the camera, then use these to construct a new rotation matrix each frame."
I don''t store Roll/yaw/pitch values with my camera(or any other object). I store a rotation matrix with it instead. The advatage is you don''t need to rebuild it''s matrix for each frame. By storing angles and rebuilding each frame you get Gimbal Lock.

"Take the values captured from the mouse and construct a new rotation matrix from these incremental values, then multiply the old rotation matrix by the new matrix."
Not quite, just take the new mouse value-old mouse value and rotate the camera''s existing matrix by the result. You dont need to rebuild a new matrix at all.

"Do you have any idea how many incremental rotations you can do before the matrix must be normalised (no. of frames)?"
I''m not sure about the number of rotations, I have let my program run for >30 min without normalizing and haven''t noticed any problems.

This is all I do to move my camera, I''m using some of my own matrix routines but you should get the idea. I left out the Pitch and Roll. I do not suffer from Gimbal lock using this method.

if (GetAsyncKeyState(VK_RIGHT)<0)MyScene->Camera.Matrix.Yaw(1);
if (GetAsyncKeyState(VK_LEFT)<0)MyScene->Camera.Matrix.Yaw(-1);
if (GetAsyncKeyState(VK_UP)<0)MyScene->Camera.Matrix.Translate(0.0,0.0,.2);
if (GetAsyncKeyState(VK_DOWN)<0)MyScene->Camera.Matrix.Translate(0.0,0.0,-.2);

Before rendering I do this->
D3DMATRIX temp;
D3DXMatrixInverse(&temp,null,&Camera.Matrix);
ID3dDevice->SetTransform( D3DTS_VIEW , &temp );

You could use Succinct''s method, But I prefer not to use quaternions.


Share this post


Link to post
Share on other sites
"You could use Succinct's method, But I prefer not to use quaternions."

I'm still undecided. I have seen good reasons given for using both, but I do find rotation matrices very intuitive personally, and I understand them completely.

I don't think I can include Quaternions just on the grounds that I don't understand how they work - even though some people say it is not necessary to know that, it is important to me. When I run into problems with code I like to be able to confirm the code is error-free because I can understand the logic behind everything I am doing.

I'll certainly be implementing this matrix method before I try and use Quaternions - I'll just be happy to get rid of Gimbal Lock for the moment.

Thanks for your help Boke, I appreciate it.

Paulcoz.

Edited by - paulcoz on February 7, 2001 2:02:37 AM

Share this post


Link to post
Share on other sites
The way I handle camera rotations is that my app class has 4 vectors, one each for the positive x,y, and z axes relative to the camera''s orientation and one for the camera''s position. Then when I want to rotate the camera, I simply rotate the first 3 vectors by an axis-rotation matrix. So if I want to pitch up or down, I rotate the vectors for the positive y and z direction around the positive x vector by the given value, and so forth for the other two directions. This is probably much more easily accomplished using quaternions, but then I can simply construct my view matrix from those 4 vectors, like this:

{px.x, px.y, px.z, 0}
{py.x, py.y, py.z, 0}
{pz.x, pz.y, pz.z, 0}
{pos.x,pos.y,pos.z,1}

At least, I think I''ve got that above part right, I just did that off the top of my head.

This works great. Then all I have to do is something like camera.RotateRelative(mouse.ymove, mouse.xmove), and I''ve got a good intuitive camera movement interface.

Probably there are faster and better ways to do this, but when it''s only happening a few times in a frame anyway, who cares?



~BenDilts( void );

Share this post


Link to post
Share on other sites