PDA

View Full Version : Matrix to Quaternion



santyhamer
05-07-2001, 02:16 PM
How can I convert a rotation Matrix into a quaternion? This is my code:

void CQuaternion :: ConvertFromMatrix ( const CMatrix& m )
{
//NOTE: The matrix MUST BE homogeneus-orthonormalized
//Local variables
FLOATTYPE l_flFloat = m.GetElement(0,0)+m.GetElement(1,1)+m.GetElement(2 ,2);
unsigned int l_i, l_j, l_k, l_uiNxt[3]= {1,2,0};

if ( l_flFloat > static_cast<FLOATTYPE>(0.0) )
{
l_flFloat = static_cast<FLOATTYPE>(sqrt(l_flFloat+1.0));
m_flV[0] = (m.GetElement(2,1)-m.GetElement(1,2)) / (static_cast<FLOATTYPE>(2) * l_flFloat);
m_flV[1] = (m.GetElement(0,2)-m.GetElement(2,0)) / (static_cast<FLOATTYPE>(2) * l_flFloat);
m_flV[2] = (m.GetElement(1,0)-m.GetElement(0,1)) / (static_cast<FLOATTYPE>(2) * l_flFloat);
m_flS = static_cast<FLOATTYPE>(0.5) * l_flFloat;
}
else
{
( m.GetElement(1,1) > m.GetElement(0,0) ) ? l_i = 1 : l_i = 0;
if ( m.GetElement(2,2) > l_i ) l_i = 2;
l_j = l_uiNxt[l_i];
l_k = l_uiNxt[l_j];

l_flFloat = static_cast<FLOATTYPE>( sqrt ( m.GetElement(l_i,l_i) - m.GetElement(l_j,l_j) - m.GetElement(l_k,l_k) + static_cast<FLOATTYPE>(1) ) );

operator[](l_i) = l_flFloat * static_cast<FLOATTYPE>(0.5);

l_flFloat = static_cast<FLOATTYPE>(4) * operator[](l_i);

m_flS = ( m.GetElement(l_k,l_j) - m.GetElement(l_j,l_k) ) / l_flFloat;
operator[](l_j) = ( m.GetElement(l_j,l_i) + m.GetElement(l_i,l_j) ) / l_flFloat;
operator[](l_k) = ( m.GetElement(l_k,l_i) + m.GetElement(l_i,l_k) ) / l_flFloat;
}

but doesn't work correctly for matrix trace <= 0.0f. Anybody could tell me why?

santyhamer
05-07-2001, 02:19 PM
This is the header:

//UNIT quaternion class
class CQuaternion
{
protected:
IGE_FLOATTYPE m_flV[3], m_flS;

public:
//Operators
CQuaternion& operator = ( const CQuaternion& q ) { m_flV[0] = q.m_flV[0];
m_flV[1] = q.m_flV[1];
m_flV[2] = q.m_flV[2];
m_flS = q.m_flS;
return *this; }

IGE_FLOATTYPE& operator [] (unsigned int i) const { return const_cast<IGE_FLOATTYPE&>((i<3)?m_flV[i]:m_flS); }

//Normalization methods
CQuaternion& Normalize ();

//Conversion methods
void ConvertFromMatrix ( const CMatrix& );
void ConvertToMatrix ( CMatrix& );

//Constuctor & initializers
void SetDefaults() { m_flV[0] = m_flV[1] = m_flV[2] = static_cast<IGE_FLOATTYPE>(0);
m_flS = static_cast<IGE_FLOATTYPE>(0); }

CQuaternion () { SetDefaults(); }
CQuaternion ( const CQuaternion& q ) { *this=q; }
CQuaternion ( const CMatrix& m ) { ConvertFromMatrix ( m ); }

};

Funk_dat
05-08-2001, 12:59 PM
I don't have a lot of experience with Matrix-Quaternion conversion but I'll try to help.

Correct me if I'm wrong, but I dont think the matrix trace can be zero. You need to find the quaternion component with the greatest absolute value and then use that to find the other components, wether it's w(the scalar part of the quaternion) or x, or y or z (the 3d vector part of the quaternion).

There should be two cases in the conversion. One where the Trace is greater than or equal to 1(use w and solve for the others) and the other case where the Trace is less than 1(find the largest value between x,y and z then use that).

You might know all that already, but it should work out that the trace is never zero if you're at this point.

hope this helps

Funk.

bsenftner
05-08-2001, 07:32 PM
Look in the "Interpolating Rotation keyframes" topic. I posted my entire (verified working) quat logic earlier today...

-Blake

santyhamer
05-09-2001, 05:26 AM
First, thanks to all. But... is possible that quaternions, sometimes, doesn't represent EXACTLY a rotation matrix. Could commit any high non-despreciable error? Suffers an strange Gimbal Lock?

pleopard
05-09-2001, 05:30 AM
Originally posted by bsenftner:
Look in the "Interpolating Rotation keyframes" topic. I posted my entire (verified working) quat logic earlier today...
-Blake
Since the search engine is SOOOOOOO SLOOOOOWWW!!! ...
http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/002895.html