#include #include "quaternions.h" //============================================================================ void Quat_Identity( quat_t q ) { q[0] = 0; q[1] = 0; q[2] = 0; q[3] = 1; } void Quat_Copy( const quat_t q1, quat_t q2 ) { q2[0] = q1[0]; q2[1] = q1[1]; q2[2] = q1[2]; q2[3] = q1[3]; } void Quat_Conjugate( const quat_t q1, quat_t q2 ) { q2[0] = -q1[0]; q2[1] = -q1[1]; q2[2] = -q1[2]; q2[3] = q1[3]; } float Quat_Normalize( quat_t q ) { float length; length = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; if( length != 0 ) { float ilength = 1.0f / (float)sqrt( length ); q[0] *= ilength; q[1] *= ilength; q[2] *= ilength; q[3] *= ilength; } return length; } float Quat_Inverse( const quat_t q1, quat_t q2 ) { Quat_Conjugate( q1, q2 ); return Quat_Normalize( q2 ); } void Matrix_Quat( float m[3][3], quat_t q ) { float tr, s; tr = m[0][0] + m[1][1] + m[2][2]; if( tr > 0.00001 ) { s = (float)sqrt( tr + 1.0f ); q[3] = (float)(s * 0.5); s = (float)(0.5 / s); q[0] = (m[2][1] - m[1][2]) * s; q[1] = (m[0][2] - m[2][0]) * s; q[2] = (m[1][0] - m[0][1]) * s; } else { int i, j, k; i = 0; if (m[1][1] > m[0][0]) i = 1; if (m[2][2] > m[i][i]) i = 2; j = (i + 1) % 3; k = (i + 2) % 3; s = (float)sqrt( m[i][i] - (m[j][j] + m[k][k]) + 1.0 ); q[i] = (float)(s * 0.5); if( s != 0.0 ) s = (float)(0.5 / s); q[j] = (m[j][i] + m[i][j]) * s; q[k] = (m[k][i] + m[i][k]) * s; q[3] = (m[k][j] - m[j][k]) * s; } Quat_Normalize( q ); } void Quat_Multiply( const quat_t q1, const quat_t q2, quat_t out ) { out[0] = q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1]; out[1] = q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2]; out[2] = q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0]; out[3] = q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]; } void Quat_Lerp( const quat_t q1, const quat_t q2, float t, quat_t out ) { quat_t p1; float omega, cosom, sinom, scale0, scale1; cosom = q1[0] * q2[0] + q1[1] * q2[1] + q1[2] * q2[2] + q1[3] * q2[3]; if( cosom < 0.0 ) { cosom = -cosom; p1[0] = -q1[0]; p1[1] = -q1[1]; p1[2] = -q1[2]; p1[3] = -q1[3]; } else { p1[0] = q1[0]; p1[1] = q1[1]; p1[2] = q1[2]; p1[3] = q1[3]; } if( cosom < 1.0f - 0.001f ) { omega = (float)acos( cosom ); sinom = 1.0f / (float)sin( omega ); scale0 = (float)sin( (1.0 - t) * omega ) * sinom; scale1 = (float)sin( t * omega ) * sinom; } else { scale0 = 1.0f - t; scale1 = t; } out[0] = scale0 * p1[0] + scale1 * q2[0]; out[1] = scale0 * p1[1] + scale1 * q2[1]; out[2] = scale0 * p1[2] + scale1 * q2[2]; out[3] = scale0 * p1[3] + scale1 * q2[3]; } void Quat_Matrix( const quat_t q, float m[3][3] ) { float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; x2 = q[0] + q[0]; y2 = q[1] + q[1]; z2 = q[2] + q[2]; xx = q[0] * x2; xy = q[0] * y2; xz = q[0] * z2; yy = q[1] * y2; yz = q[1] * z2; zz = q[2] * z2; wx = q[3] * x2; wy = q[3] * y2; wz = q[3] * z2; m[0][0] = 1.0f - yy - zz; m[0][1] = xy - wz; m[0][2] = xz + wy; m[1][0] = xy + wz; m[1][1] = 1.0f - xx - zz; m[1][2] = yz - wx; m[2][0] = xz - wy; m[2][1] = yz + wx; m[2][2] = 1.0f - xx - yy; } void Quat_TransformVector( const quat_t q, const float v[3], float out[3] ) { float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2; x2 = q[0] + q[0]; y2 = q[1] + q[1]; z2 = q[2] + q[2]; xx = q[0] * x2; xy = q[0] * y2; xz = q[0] * z2; yy = q[1] * y2; yz = q[1] * z2; zz = q[2] * z2; wx = q[3] * x2; wy = q[3] * y2; wz = q[3] * z2; out[0] = (1.0f - yy - zz) * v[0] + (xy - wz) * v[1] + (xz + wy) * v[2]; out[1] = (xy + wz) * v[0] + (1.0f - xx - zz) * v[1] + (yz - wx) * v[2]; out[2] = (xz - wy) * v[0] + (yz + wx) * v[1] + (1.0f - xx - yy) * v[2]; } void Quat_ConcatTransforms( const quat_t q1, const float v1[3], const quat_t q2, const float v2[3], quat_t q, float v[3] ) { Quat_Multiply( q1, q2, q ); Quat_TransformVector( q1, v2, v ); v[0] += v1[0]; v[1] += v1[1]; v[2] += v1[2]; }