Sign in to follow this  
tealrabbit

Quaternions has a 90 deg dead angle

Recommended Posts

tealrabbit    122
Hi I am using quaternions for both animations and my camera and I am encountering the same problem in both cases. It seems like the quaternions have a dead angle of 90 degrees. Passing that angle will either make the quaternion roll around rotating the other direction, or break it. By break it I mean that any rotation matrix made from the quaternion ends up havid bad right, up, and at vectors causing the entire frustum to collapse in the camera case. In the animations some joints sometime flip around an entire lap and get twisted. Here are the funcitons I use. Sorry if its a lot of code I'm kind of new to quaternions so go easy on me please // SLERP void SiCQuaternion::Slerp(const SiVector4T *pQuaternion1, const SiVector4T *pQuaternion2, float fDelta) { SiVector4T v4Quat2 = *pQuaternion2; float fDot = pQuaternion1->Dot(*pQuaternion2); if( fDot < 0.0f ) { fDot =-fDot; v4Quat2.fX = -v4Quat2.fX; v4Quat2.fY = -v4Quat2.fY; v4Quat2.fZ = -v4Quat2.fZ; v4Quat2.fW = -v4Quat2.fW; } if (fDot <= 1.f && fDot > 0.999f) { Lerp(pQuaternion1, &v4Quat2, fDelta); return; } float fTheta = acosf(fDot); float fT = 1.f / sinf(fTheta); m_v4Quaternion.Add(*pQuaternion1 * sinf( (1.f - fDelta) * fTheta), v4Quat2 * sinf(fDelta * fTheta)); m_v4Quaternion = m_v4Quaternion * fT; } // BUILD ROTATION MATRIX float fWX, fWY, fWZ, fXX, fYY, fZZ, fYZ, fXY, fXZ, fX2, fY2, fZ2; // Clean the matrix memset(pOutMatrix, 0, sizeof(SiMatrix4T)); pOutMatrix->_44 = 1.0f; fX2 = m_v4Quaternion.fX + m_v4Quaternion.fX; fY2 = m_v4Quaternion.fY + m_v4Quaternion.fY; fZ2 = m_v4Quaternion.fZ + m_v4Quaternion.fZ; fXX = m_v4Quaternion.fX * fX2; fYY = m_v4Quaternion.fY * fY2; fZZ = m_v4Quaternion.fZ * fZ2; fXY = m_v4Quaternion.fX * fY2; fXZ = m_v4Quaternion.fX * fZ2; fYZ = m_v4Quaternion.fY * fZ2; fWX = m_v4Quaternion.fW * fX2; fWY = m_v4Quaternion.fW * fY2; fWZ = m_v4Quaternion.fW * fZ2; pOutMatrix->_11 = 1.f - (fYY + fZZ); pOutMatrix->_12 = fXY - fWZ; pOutMatrix->_13 = fXZ + fWY; pOutMatrix->_21 = fXY + fWZ; pOutMatrix->_22 = 1.f - (fXX + fZZ); pOutMatrix->_23 = fYZ - fWX; pOutMatrix->_31 = fXZ - fWY; pOutMatrix->_32 = fYZ + fWX; pOutMatrix->_33 = 1.f - (fXX + fYY); } // And finally build from matrix. This can not be the problem in the animation case since I export quaternions from maya { float fTemp = pMatrix->_11 + pMatrix->_22 + pMatrix->_33 + pMatrix->_44; float fFour; int i,j,k; if (fTemp >= 1.f) { fFour = 2.f * sqrt(fTemp); m_v4Quaternion.fW = fFour * 0.25f; m_v4Quaternion.fX = (pMatrix->_32 - pMatrix->_23) / fFour; m_v4Quaternion.fY = (pMatrix->_13 - pMatrix->_31) / fFour; m_v4Quaternion.fZ = (pMatrix->_21 - pMatrix->_12) / fFour; } else { if (pMatrix->_11 > pMatrix->_22) { i = 0; } else { i = 1; } if (pMatrix->_33 > pMatrix->fMatrix[i * 4 + 4]) { i = 2; } j = (i+1)%3; k = (j+1)%3; fFour = 2.f * sqrt(pMatrix->fMatrix[i * 4 + i] - pMatrix->fMatrix[i * 4 + i] - pMatrix->fMatrix[k * 4 + k] + 1.f); m_v4Quaternion.fVec[i] = fFour * 0.25f; m_v4Quaternion.fVec[j] = (pMatrix->fMatrix[j* 4 + i] + pMatrix->fMatrix[i* 4 + j]) / fFour; m_v4Quaternion.fVec[k] = (pMatrix->fMatrix[k* 4 + i] + pMatrix->fMatrix[i* 4 + k]) / fFour; m_v4Quaternion.fW = (pMatrix->fMatrix[j * 4 + k] - pMatrix->fMatrix[k * 4 + j]) / fFour; } Thanks

Share this post


Link to post
Share on other sites
Dave Eberly    1173
Quote:
Original post by tealrabbit
// And finally build from matrix. This can not be the problem in the animation case since I export quaternions from maya

and
Quote:

fFour = 2.f * sqrt(pMatrix->fMatrix[i * 4 + i] - pMatrix->fMatrix[i * 4 + i] - pMatrix->fMatrix[k * 4 + k] + 1.f);


Is this correct?

Share this post


Link to post
Share on other sites
jyk    2094
In addition to the line Dave pointed out, I think you may also have a problem in this line:

if (pMatrix->_33 > pMatrix->fMatrix[i * 4 + 4])

Also it seems that your slerp function could fail if the two input quaternions are very close to equal. To avoid this I would change this line:

if (fDot <= 1.f && fDot > 0.999f)

To:

if (fDot > 0.999f)

Share this post


Link to post
Share on other sites
tealrabbit    122
Thanks a lot for the quick answers. You where both right. Those two fixes took care of the quaternions breaking and making bad matrices. The only problem now is that the quaternions still seems to switch direction when they hit a certain angle and get "inverted".

This is in the Lerp or Slerp I am pretty sure.

Thanks for the help. I'm sure I'll figure this out.

Share this post


Link to post
Share on other sites
swiftcoder    18437
Quote:
Original post by tealrabbit
The only problem now is that the quaternions still seems to switch direction when they hit a certain angle and get "inverted".
This is in the Lerp or Slerp I am pretty sure.


This is fairly common with Lerp and Slerp algorithms, it happens whenever the quaternions are are at such a rotation that any axis will do for the rotation. My fix was to use the first quaternions up vector as the axis for the rotation, if any axis is acceptable.

Sorry if that isn't very clear,

SwiftCoder

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
regarding the "switching directions" on your interpolation.
i'm imagining that you have these keyframes:

time 0: 0 degrees
time 30: 90 degrees
time 60: 0 degrees.

at time 31, there is nothing in the slerp math that can tell which direction you want to go in -- it can't tell whether 91 or 89 degrees is the right answer for frame 31..

maya, internally, uses function curves for this, so maya knows more information than your quaternion...

the solution is to have your artist put in keyframes at, say, time 45..
or to put them in programmaticall as you are pulling the animation out of maya.

that's what we do where i work.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this