Advertisement

Matrix to quaternion

Started by October 30, 2001 07:16 AM
2 comments, last by Rudan 23 years, 3 months ago
I''ve been trying to learn how to use quaternions for a while now, and I got a question: When creating a quaternion from a matrix, most of the examples I''ve seen are pretty long. However, I''ve seen this(or similiar) in a few places:
public final void set(Matrix4f m1)
{
w = Math.sqrt(1.0 + m1.m00 + m1.m11 + m1.m22) / 2.0;
double w4 = (4.0 * w);
x = (m1.m12 - m1.m21) / w4 ;
y = (m1.m20 - m1.m02) / w4 ;
z = (m1.m01 - m1.m10) / w4 ;
} 
I wonder if this works too? Probably not, why would not more people use it that''s the case? Thanks...
-----------------------------Reporter: Are they slow-moving, chief?Sheriff: Yeah, they're dead. They're all messed up.-Night of the living dead
This will work for some (but not all) matrices...

A safer version might be:

const float d = (1.0f + m1.m00 + m1.m11 + m1.m22);if (d > 0.0f){    w = 0.5f * sqrtf(d);    const float temp = 0.25f / w;    x = (m1.m12 - m1.m21) * temp;    y = (m1.m20 - m1.m02) * temp;    z = (m1.m01 - m1.m10) * temp;}else{    // fall back to long code...} 


As a general rule, you should always check that values you pass to square-root functions are >= 0, plus you don''t want a divide by zero.
Advertisement
Damn, I was hoping to get away with the short one.
I guess I''ll have to learn the hard way to do it.
Thanks
-----------------------------Reporter: Are they slow-moving, chief?Sheriff: Yeah, they're dead. They're all messed up.-Night of the living dead
I don''t know if this works (I haven''t seriously tested it, in other words) but this is what I wrote a while back for my engine. The lower case ''s'' is what I use where most people use ''w''. ''v'' is a local vector. Val.v is a 16 element 1D array of floats.
void rQuat::operator = (const rMatrix4x4 &Val) {	float T, S;	T = Val.v[0] + Val.v[5] + Val.v[10] + 1.0f;	if(T > 0.0f) {		S = 0.5f / (float) rInternalSqrt(T);		s = 0.25f / S;		v.v[0] = S * (Val.v[9] - Val.v[6]);		v.v[1] = S * (Val.v[2] - Val.v[8]);		v.v[2] = S * (Val.v[4] - Val.v[1]);	} else {		if(Val.v[0] > Val.v[5]) {			if(Val.v[0] > Val.v[10]) { // Column 1				S = 0.5f / (float)rInternalSqrt(1.0f + Val.v[0] - Val.v[5] - Val.v[10]);				s = S * (Val.v[6] + Val.v[9]);				v.v[0] = S * 0.5f;				v.v[1] = S * (Val.v[1] + Val.v[4]);				v.v[2] = S * (Val.v[2] + Val.v[8]);			} else goto HandleCol3;		} else {			if(Val.v[5] > Val.v[10]) { // Column 2				S = 0.5f / (float)rInternalSqrt(1.0f + Val.v[5] - Val.v[0] - Val.v[10]);				s = S * (Val.v[2] + Val.v[8]);				v.v[0] = S * (Val.v[1] + Val.v[4]);				v.v[1] = S * 0.5f;				v.v[2] = S * (Val.v[2] + Val.v[8]);			} else goto HandleCol3;		}		return;		HandleCol3:		{ // Column 3			S = 0.5f / (float)rInternalSqrt(1.0f + Val.v[10] - Val.v[0] - Val.v[5]);			s = S * (Val.v[1] + Val.v[4]);			v.v[0] = S * (Val.v[2] + Val.v[8]);			v.v[1] = S * (Val.v[6] + Val.v[9]);			v.v[2] = S * 0.5f;		}	}}


[Resist Windows XP''s Invasive Production Activation Technology!]

This topic is closed to new replies.

Advertisement