## matrix normalization??

once again a matrix problem

i am multiplying lots of rotation matrices, and after a

while my rotations dont look as i think they should!

i once read somewhere, matrices should be normalized every

once in a while when multiplying them with each other ...

is that true? and could that be the reason for my problems?

and, if i have to do that, does anyone have a link

on HOW to normalize a 4x4 matrix??

sebastian

However I dont believe...

Quote:Originally posted by Mark Levinis completely accurate. If you need to have a matrix which will accumulate errors you *can* orthonormalize it. Its slow - but again as you posted - you dont need to do it every frame because it takes some time for a matrix to become undone.

"Normalizing the matrix" means clearing it to the identity matrix and setting it explicitly to the rotation you want, instead of multiplying a rotation matrix with very small numbers a hundred thousand times.

I use the math library called FreeMagic - which you can get at <http://www.magic-software.com> and it has this method for dealing with 3x3 matricies (and you really only need to apply this to the 'rotational' 3x3 section of OpenGL's 4x4 matrix)

[SOURCECODE]void Matrix3::Orthonormalize ()

{

// Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is

// M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],

//

// q0 = m0/|m0|

// q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|

// q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|

//

// where |V| indicates length of vector V and A*B indicates dot

// product of vectors A and B.

// compute q0

Real fInvLength = Math::InvSqrt(m_aafEntry[0][0]*m_aafEntry[0][0]

+ m_aafEntry[1][0]*m_aafEntry[1][0] +

m_aafEntry[2][0]*m_aafEntry[2][0]);

m_aafEntry[0][0] *= fInvLength;

m_aafEntry[1][0] *= fInvLength;

m_aafEntry[2][0] *= fInvLength;

// compute q1

Real fDot0 =

m_aafEntry[0][0]*m_aafEntry[0][1] +

m_aafEntry[1][0]*m_aafEntry[1][1] +

m_aafEntry[2][0]*m_aafEntry[2][1];

m_aafEntry[0][1] -= fDot0*m_aafEntry[0][0];

m_aafEntry[1][1] -= fDot0*m_aafEntry[1][0];

m_aafEntry[2][1] -= fDot0*m_aafEntry[2][0];

fInvLength = Math::InvSqrt(m_aafEntry[0][1]*m_aafEntry[0][1] +

m_aafEntry[1][1]*m_aafEntry[1][1] +

m_aafEntry[2][1]*m_aafEntry[2][1]);

m_aafEntry[0][1] *= fInvLength;

m_aafEntry[1][1] *= fInvLength;

m_aafEntry[2][1] *= fInvLength;

// compute q2

Real fDot1 =

m_aafEntry[0][1]*m_aafEntry[0][2] +

m_aafEntry[1][1]*m_aafEntry[1][2] +

m_aafEntry[2][1]*m_aafEntry[2][2];

fDot0 =

m_aafEntry[0][0]*m_aafEntry[0][2] +

m_aafEntry[1][0]*m_aafEntry[1][2] +

m_aafEntry[2][0]*m_aafEntry[2][2];

m_aafEntry[0][2] -= fDot0*m_aafEntry[0][0] + fDot1*m_aafEntry[0][1];

m_aafEntry[1][2] -= fDot0*m_aafEntry[1][0] + fDot1*m_aafEntry[1][1];

m_aafEntry[2][2] -= fDot0*m_aafEntry[2][0] + fDot1*m_aafEntry[2][1];

fInvLength = Math::InvSqrt(m_aafEntry[0][2]*m_aafEntry[0][2] +

m_aafEntry[1][2]*m_aafEntry[1][2] +

m_aafEntry[2][2]*m_aafEntry[2][2]);

m_aafEntry[0][2] *= fInvLength;

m_aafEntry[1][2] *= fInvLength;

m_aafEntry[2][2] *= fInvLength;

}

[/SOURCECODE]

hth,

Codemattic