a to convert a matrix to a quaternion

Hi everyone

I am new to the forum and just learning and in top of that I am not a native english speaker so please bear with me.

I am working with some animation and want to make a mesh move and rotate according to a bezier path I have manage to make it move but the way I came with to make it rotate is to make a lookat matrix look from the current to the next position in the bezier curve, I’m not very good at math so, I don’t know how to make a lookat quaternion so I use lookat matrix and convert it to a quaternion. All my rotation need to be in quaternion because all the interpolation is already done that way my scene graph, I tested my lookat matrix and is fine but the conversion to quaternion is wrong the function I am using is the one I have been seen around the web every where

void CQuaternion::FromMatrix(CMatrix& m)
{
float trace = 1 + m.m11 + m.m22 + m.m33;
float s = 0;

		if (trace > 0.0000001) 
		{
			s = (float)sqrt(trace) * 2;
			x = (m.m23 - m.m32) / s;
			y = (m.m31 - m.m13) / s;
			z = (m.m12 - m.m21) / s;
			w = 0.25f * s;
		} 
		else 
		{
			if (m.m11 > m.m22 && m.m11 > m.m33) 
			{
				// Column 0: 
				s = (float)sqrt(1.0 + m.m11 - m.m22 - m.m33) * 2;
				x = 0.25f * s;
				y = (m.m12 + m.m21) / s;
				z = (m.m31 + m.m13) / s;
				w = (m.m23 - m.m32) / s;
			} 
			else if (m.m22 > m.m33) 
			{
				// Column 1: 
				s = (float)sqrt(1.0 + m.m22 - m.m11 - m.m33) * 2;
				x = (m.m12 + m.m21) / s;
				y = 0.25f * s;
				z = (m.m23 + m.m32) / s;
				w = (m.m31 - m.m13) / s;
			} 
			else 
			{
				// Column 2:
				s = (float)sqrt(1.0 + m.m33 - m.m11 - m.m22) * 2;
				x = (m.m31 + m.m13) / s;
				y = (m.m23 + m.m32) / s;
				z = 0.25f * s;
				w = (m.m12 - m.m21) / s;
			}
		}
}

and this is my lookat matrix method just to be more clear

void CMatrix::LookAt(CVector3 Pos, CVector3 Target, CVector3 y)
{
CVector3 x, z;

	z = Target - Pos;
	z.Normalize();

	if(!z.x && z.y == 1.0f && !z.z)
	{
		Rotate(-1.5707963267948966f, 0.0f, 0.0f);
	//	Translate( Pos.x,  Pos.y,  Pos.z);
		return;
	}else
	if(!z.x && z.y == -1.0f && !z.z)
	{
		Identity();
		Rotate(1.5707963267948f, 0.0f, 0.0f);
	//	Translate( Pos.x,  Pos.y,  Pos.z);
		return;
	}

	x.CrossProduct(z, y);
	//x.Normalize();

	y.CrossProduct(x, z);
	y.Normalize();

	m11 =  x.x;
	m12 =  x.y;
	m13 =  x.z;

	m21 =  y.x;
	m22 =  y.y;
	m23 =  y.z;

	m31 =  z.x;
	m32 =  z.y;
	m33 =  z.z;

	/*don't need position
                        m14 = m24 = m34 = 0;
	m41 = Pos[0];
	m42 = Pos[1];
	m43 = Pos[2];*/
	m44 = 1.0f;
}

please help, and thank you

You Matrix - Quaternion is quite different to mine. Are you sure the matrix is from OpenGL and not DirectX. You may need to find the original maths; mine is based on Allan and Mark Watt’s “Advanced Animation and Rendering Techniques”.

Looking at your MatrixToQuat code, looks nearly equivalent to what I’m using (regrouping terms, of course). Two differences. One is my if/elif conditions for the nested if (i.e. those in the trace <= 0 case) are >= instead of > (a minor point). And second is that for greater numerical stability, it’s better for the first if if you check for (trace-1) > 0, not trace > 0. This corresponds to a w^2 > 1/4 case as opposed to the w^2 > 0. Additionally, this gets rid of the need for that 0.0000001 you’re using to test against.

Note that the above routine presumes "row-major operator-on-the-right " math order (e.g. y=xM), which generates the same results as OpenGL’s “column-major operator-on-the-left” math order (y=Mx).

Haven’t sifted your LookAt code. Cut it out of the picture and do some MatrixToQuat followed by QuatToMatrix – make sure you get the same thing back out. That’s a pretty good test.

it was basically what you mansion darkphoton I just realize my FromMatrix was row major while the lookat matrix was column major the funny thing was that I thought about it and decided to swap the column before using my FromMatrix method and the result were wrong too until I realize that by negating the z vector of my lookat matrix plus swapping from row to column major on the FromMatrix works fine.