/*!*************************************************************************** @Function Name PVRTMatrixRotationZX @Output mOut Rotation matrix @Input fAngle Angle of the rotation @Description Create an Z rotation matrix mOut. *****************************************************************************/ void PVRTMatrixRotationZX( PVRTMATRIXx &mOut, const int fAngle) { int fCosine, fSine; /* Precompute cos and sin */ #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10) fCosine = PVRTXCOS(-fAngle); fSine = PVRTXSIN(-fAngle); #else fCosine = PVRTXCOS(fAngle); fSine = PVRTXSIN(fAngle); #endif /* Create the trigonometric matrix corresponding to Z Rotation */ mOut.f[ 0]=fCosine; mOut.f[ 4]=fSine; mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f); mOut.f[ 1]=-fSine; mOut.f[ 5]=fCosine; mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f); mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=PVRTF2X(0.0f); mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f); }
/*!*************************************************************************** @Function PVRTMatrixQuaternionSlerpX @Output qOut Result of the interpolation @Input qA First quaternion to interpolate from @Input qB Second quaternion to interpolate from @Input t Coefficient of interpolation @Description Perform a Spherical Linear intERPolation between quaternion A and quaternion B at time t. t must be between 0.0f and 1.0f Requires input quaternions to be normalized *****************************************************************************/ void PVRTMatrixQuaternionSlerpX( PVRTQUATERNIONx &qOut, const PVRTQUATERNIONx &qA, const PVRTQUATERNIONx &qB, const int t) { int fCosine, fAngle, A, B; /* Parameter checking */ if (t<PVRTF2X(0.0f) || t>PVRTF2X(1.0f)) { _RPT0(_CRT_WARN, "PVRTMatrixQuaternionSlerp : Bad parameters\n"); qOut.x = PVRTF2X(0.0f); qOut.y = PVRTF2X(0.0f); qOut.z = PVRTF2X(0.0f); qOut.w = PVRTF2X(1.0f); return; } /* Find sine of Angle between Quaternion A and B (dot product between quaternion A and B) */ fCosine = PVRTXMUL(qA.w, qB.w) + PVRTXMUL(qA.x, qB.x) + PVRTXMUL(qA.y, qB.y) + PVRTXMUL(qA.z, qB.z); if(fCosine < PVRTF2X(0.0f)) { PVRTQUATERNIONx qi; /* <http://www.magic-software.com/Documentation/Quaternions.pdf> "It is important to note that the quaternions q and -q represent the same rotation... while either quaternion will do, the interpolation methods require choosing one over the other. "Although q1 and -q1 represent the same rotation, the values of Slerp(t; q0, q1) and Slerp(t; q0,-q1) are not the same. It is customary to choose the sign... on q1 so that... the angle between q0 and q1 is acute. This choice avoids extra spinning caused by the interpolated rotations." */ qi.x = -qB.x; qi.y = -qB.y; qi.z = -qB.z; qi.w = -qB.w; PVRTMatrixQuaternionSlerpX(qOut, qA, qi, t); return; } fCosine = PVRT_MIN(fCosine, PVRTF2X(1.0f)); fAngle = PVRTXACOS(fCosine); /* Avoid a division by zero */ if (fAngle==PVRTF2X(0.0f)) { qOut = qA; return; } /* Precompute some values */ A = PVRTXDIV(PVRTXSIN(PVRTXMUL((PVRTF2X(1.0f)-t), fAngle)), PVRTXSIN(fAngle)); B = PVRTXDIV(PVRTXSIN(PVRTXMUL(t, fAngle)), PVRTXSIN(fAngle)); /* Compute resulting quaternion */ qOut.x = PVRTXMUL(A, qA.x) + PVRTXMUL(B, qB.x); qOut.y = PVRTXMUL(A, qA.y) + PVRTXMUL(B, qB.y); qOut.z = PVRTXMUL(A, qA.z) + PVRTXMUL(B, qB.z); qOut.w = PVRTXMUL(A, qA.w) + PVRTXMUL(B, qB.w); /* Normalise result */ PVRTMatrixQuaternionNormalizeX(qOut); }