quaternions?

Started by
2 comments, last by quasar3d 18 years, 9 months ago
I am trying to use quaternions for my animations, but I can't really get them working correctly. I made a plugin for maya, which gets the quaternion from the items transformation matrix. Most of the time this seems to work fine, but especially if I try to blend between multiply animations, it sometimes gives very weird results. I think the problem has something to do with the fact that you can represent each rotation by 2 diffent quaternions. I did a little test with a cube which rotates only around it's x axis. This is a part of the quaternion keyframes I got, and there is indead a flip of signs: <key t = "5" value = ".7330, -.6801, 0, 0"/> <key t = "6" value = ".6234, -.7818, 0, 0"/> <key t = "7" value = "-.4999, .8660, 0, 0"/> <key t = "8" value = "-.3653, .9308, 0, 0"/> Is there a way to get the quaternions in a way that those sign flips won't occur? This is my matrix to quaternion code

Quaternion Matrix4::ToQuaternion() const
{
	float trace = m[0][0] + m[1][1] + m[2][2];
	
	if(trace > 0)
	{
		float root = sqrtf(trace + 1);

		Quaternion ret;
		ret.w = root * .5f;
		root = .5f / root;
		ret.x = (m[2][1] - m[1][2]) * root;
		ret.y = (m[0][2] - m[2][0]) * root;
		ret.z = (m[1][0] - m[0][1]) * root;
		ret.Normalize();
		return ret;
	}
	else
	{
		const int next[] = {1,2,0};
		int i = 0;
		if(m[1][1] > m[0][0])
			i = 1;
		if(m[2][2] > m)
			i = 2;
		int j = next;
		int k = next[j];

		float root = sqrtf(m - m[j][j] - m[k][k] + 1);

		Quaternion ret;
		ret.vec = root * .5f;
		root = .5f / root;
		ret.w = (m[k][j] - m[j][k]) * root;
		ret.vec[j] = (m[j] + m[j]) * root;
		ret.vec[k] = (m[k] + m[k]) * root;
		ret.Normalize();
		return ret;
	}
}


Advertisement
Quote:Is there a way to get the quaternions in a way that those sign flips won't occur?


Negating the quaternion when necessary to keep the w coordinate always positive should work OK.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
Quote:Is there a way to get the quaternions in a way that those sign flips won't occur?


Negating the quaternion when necessary to keep the w coordinate always positive should work OK.


Actually, no (from experience trying this with real data sets). What you need to do is make sure the angle between consecutive quaternions is acute. If q0 and q1 are those quaternions, if Dot(q0,q1) >= 0 then interpolate q0 and q1. If Dot(q0,q1) < 0 then interpolate q0 and -q1. In my own applications, I preprocess quaternion sequences so that the dot product is always nonnegative, thus avoiding the dot-product test at run time.
Quote:Original post by Dave Eberly
Quote:Original post by Fruny
Quote:Is there a way to get the quaternions in a way that those sign flips won't occur?


Negating the quaternion when necessary to keep the w coordinate always positive should work OK.


Actually, no (from experience trying this with real data sets). What you need to do is make sure the angle between consecutive quaternions is acute. If q0 and q1 are those quaternions, if Dot(q0,q1) >= 0 then interpolate q0 and q1. If Dot(q0,q1) < 0 then interpolate q0 and -q1. In my own applications, I preprocess quaternion sequences so that the dot product is always nonnegative, thus avoiding the dot-product test at run time.


Thanks alot man, this works perfectly.

This topic is closed to new replies.

Advertisement