Jump to content
  • Advertisement
Sign in to follow this  
gaimplay

Rotation matrix ortho-normalization

This topic is 5103 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

I'm trying to figure out how to orthonormalize a rotation matrix so that the basis vectors would be unit length and perpendicular. This is to combat floating point precision errors that accumulate in the matrix. The way I figured it, all you need to do is take a unit vector, transform it by your current rotation matrix, then inspect the resulting vector and build a some kind of a scaling matrix that makes the resulting vector unit length, then concatenate this matrix with your current one to fix it. If I'm way off course, it would be great if someone could post some pseudo code or actual code to demonstate the correct algorithm. I'm currently using DX9 but can't find a built-in function to do this kind of thing. Any help appreciated.

Share this post


Link to post
Share on other sites
Advertisement
google gramm schmidth ortogonalization (spelling is probably boxxored, so that could be a problem with google...)

basicly it comes down to picking one vector as base direction, then substract all from the second vector that isnt orthonormal to the first, and substract from the third the parts that are not normal to the first aswell as the second, then normalize everything, and there you go.

Share this post


Link to post
Share on other sites
Consider storing dynamic referentials (where you accumulate transfos) as Quaternions, AxisAngle or EulerAngles if possible. Renormalizing matrices will necessarilly be more unstable. Then use conversions when required to pass something to DX9 for instance.

Share this post


Link to post
Share on other sites
Quote:
Original post by gaimplay
I'm trying to figure out how to orthonormalize a rotation matrix so that the basis vectors would be unit length and perpendicular. This is to combat floating point precision errors that accumulate in the matrix.

The way I figured it, all you need to do is take a unit vector, transform it by your current rotation matrix, then inspect the resulting vector and build a some kind of a scaling matrix that makes the resulting vector unit length, then concatenate this matrix with your current one to fix it.

If I'm way off course, it would be great if someone could post some pseudo code or actual code to demonstate the correct algorithm.

I'm currently using DX9 but can't find a built-in function to do this kind of thing.

Any help appreciated.


As others have said, use quaternions. Anyway, it can be done as

Column1=Normalized(CrossProduct(Column2,Column3));
Column2=Normalized(CrossProduct(Column3,Column1));
// and ther you don't really need to Column3=Normalized(CrossProduct(Column1,Column2));
Column3=Normalized(Column3);

Where ColumnN contains nth column of 3x3 rotation matrix as vector. If you use 4x4 matrix, it's submatrix in top-left corner.
You can do the same with rows if you want.
Note that one column/row may be selected to be distorted the least.

Also, don't do it when matrix is unchanged, or your things might start slowly turn.

Share this post


Link to post
Share on other sites
Quote:
Original post by Charles B
Consider storing dynamic referentials (where you accumulate transfos) as Quaternions, AxisAngle or EulerAngles if possible. Renormalizing matrices will necessarilly be more unstable. Then use conversions when required to pass something to DX9 for instance.

/agree.

quaternions are a much better way to store orientations than matrices. the only thing matrices are best for is transforming coordinates actually, so they should only be generated just before transforming your stuff ideally.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Gramm-Schmidt Orthogonalization Too complicated, the two cross product much faster and practical

Column1=Normalized(CrossProduct(Column2,Column3));
Column2=Normalized(CrossProduct(Column3,Column1));

Not need to renormalize Column3 as it is already part of the matrix.

Elco quote:
"quaternions are a much better way to store orientations than matrices. the only thing matrices are best for is transforming coordinates actually, so they should only be generated just before transforming your stuff ideally."

You should disclaim this by saying is you opnion not a fact.
Quatenions are good for key frame interpolation and physics but they are in fact a terrible way to store transformation matrices. Just think of a scene graph with tenth of children in which the application have to transform and rotate vectors several time. Rotation of a vector by a quaternion while it is possible it is about 8 time more expensive than rotation by the matrix equivalent. If you do not belief me then you look and two mayor graphics apis OpneGL and direct3d they use matrices to form matrix stack, not quaternion.


Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Gramm-Schmidt Orthogonalization Too complicated, the two cross product much faster and practical

Column1=Normalized(CrossProduct(Column2,Column3));
Column2=Normalized(CrossProduct(Column3,Column1));

Not need to renormalize Column3 as it is already part of the matrix.

Elco quote:
"quaternions are a much better way to store orientations than matrices. the only thing matrices are best for is transforming coordinates actually, so they should only be generated just before transforming your stuff ideally."

You should disclaim this by saying is you opnion not a fact.
Quatenions are good for key frame interpolation and physics but they are in fact a terrible way to store transformation matrices. Just think of a scene graph with tenth of children in which the application have to transform and rotate vectors several time. Rotation of a vector by a quaternion while it is possible it is about 8 time more expensive than rotation by the matrix equivalent. If you do not belief me then you look and two mayor graphics apis OpneGL and direct3d they use matrices to form matrix stack, not quaternion.

1: it's needed to normalize 3rd column, like i said. Otherwise it will not be unit-length.

1: matrices VS quaternions:
You're mixing apples with oranges.
Matrices is good to store arbitrary transforms, including rotation. It's their power and weakness. If you apply many transforms, matrices becomes non-orthonormal. Quaternions is good for storing variable rotations, because them can store only rotation and scale, and therefore CAN'T store unwanted transform (and one normalization it's everything you need).
Before doing transformation, quaternions is usually converted to matrices. In my math lib, there's even no function for rotating vector using quaternion.
Also,quaternion*quaternion multiplication is fast. It's faster to obtain inverse rotation with quaternion.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Gramm-Schmidt Orthogonalization Too complicated, the two cross product much faster and practical

Column1=Normalized(CrossProduct(Column2,Column3));
Column2=Normalized(CrossProduct(Column3,Column1));

Not need to renormalize Column3 as it is already part of the matrix.

Elco quote:
"quaternions are a much better way to store orientations than matrices. the only thing matrices are best for is transforming coordinates actually, so they should only be generated just before transforming your stuff ideally."

You should disclaim this by saying is you opnion not a fact.
Quatenions are good for key frame interpolation and physics but they are in fact a terrible way to store transformation matrices. Just think of a scene graph with tenth of children in which the application have to transform and rotate vectors several time. Rotation of a vector by a quaternion while it is possible it is about 8 time more expensive than rotation by the matrix equivalent. If you do not belief me then you look and two mayor graphics apis OpneGL and direct3d they use matrices to form matrix stack, not quaternion.

actually transforming a vector with a quad is only about twice as slow. but you wont be doing that anyway. generating a matrix from a quad is rather easy. so thats why im saying: store rotations as quaternions, for each primitive group, calc the transform matrix after traversing bone hierachies and such, and use this to transform everything. since quat*quat is faster than matrix*matrix this is probably faster aswell even while taking into account the quattomatrix.

the reason apis and videocards dont work that way is because they have to provide more flexibility than just rotation. however, things like scaling can be added in a quaternion based engine just aswell, and in the end youre still using less memory than with a matrix.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
As I understood the matrix was loosing orthogonality. But yes you are correct normalizing the third row will make it more robust.

In your second point I think you are one mixing the oranges and the apples not me.
Quaternions are not transformation matrices and they are not rotation matrices.

The same lost of orthogonality that happens to matrices when you multiplying then together also happen to quaternions. You said yourself when you mention “and one normalization it's everything you need”

You also mention the product of two quaternion is easy and fast, however that meaning less operation for most graphics application.

Say you have rotation Matrices A, B, C;
And a quaternion function M = f(q) where q is a quaternion and M in a rotation matrix

if equality 1) A = B * C is true
and 2) qa = qb * qc is also true

this lead to 3) A = f(qb) * f(qc) which is true

if you calculate the matrix M = f(qa) you will see that it is different than matrix A

so you get f(qa) != A
f(qb * qc) != f(qb) * f(qc)

The rotation matrix mapped by the product of two quaternion is different that the product of the matrices mapped by the quaternions. So hinting that the product of two quaternions is fast as a replacement of matrix multiplication is just wrong and misleading.

Finally who say that scaling can not be apply to matrices?

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
The same lost of orthogonality that happens to matrices when you multiplying then together also happen to quaternions. You said yourself when you mention “and one normalization it's everything you need”

?
a quat is always ortho, if not unit length. the problem of loss of orthogonality comes from rotationmatrices being overdefined. a quaternion hence cant suffer from this by definition.

and one normalization is quite a lot faster than renomalizing and reothogonizing a matrix.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!