home *** CD-ROM | disk | FTP | other *** search
- #include "quaternionmath.h"
-
- #include <math.h>
- #include <stdio.h>
-
- #include "vectormath.h"
-
-
- float* quaternionToMatrix(quaternion_t q, float* matrix){
- // if(!matrix)
- // return;
-
- matrix[ 0] = 1.0f - 2.0f * ( q[1] * q[1] + q[2] * q[2] );
- matrix[ 1] = 2.0f * ( q[0] * q[1] - q[3] * q[2] );
- matrix[ 2] = 2.0f * ( q[0] * q[2] + q[3] * q[1] );
- matrix[ 3] = 0.0f;
-
- matrix[ 4] = 2.0f * ( q[0] * q[1] + q[3] * q[2] );
- matrix[ 5] = 1.0f - 2.0f * ( q[0] * q[0] + q[2] * q[2] );
- matrix[ 6] = 2.0f * ( q[1] * q[2] - q[3] * q[0] );
- matrix[ 7] = 0.0f;
-
- matrix[ 8] = 2.0f * ( q[0] * q[2] - q[3] * q[1] );
- matrix[ 9] = 2.0f * ( q[1] * q[2] + q[3] * q[0] );
- matrix[10] = 1.0f - 2.0f * ( q[0] * q[0] + q[1] * q[1] );
- matrix[11] = 0.0f;
-
- matrix[12] = 0;
- matrix[13] = 0;
- matrix[14] = 0;
- matrix[15] = 1.0f;
-
- return matrix;
- }
-
-
-
- float* quaternionFromMatrix(float* matrix, quaternion_t q){
- /*
- float diagSum=matrix[0]+matrix[5]+matrix[10]+1.0f;
- if(diagSum<0.0){
- // printf("BOING!!\n");
- return q; // THINKABOUTME: oder auf null setzten, um Fehler anzuzeigen?
- }
-
- q[3]=(float)(2.0 * sqrt(diagSum));
- float s1 = (matrix[0]+1 - 2*q[3]*q[3])/2;
- s1 = s1 < 0.0 ? -s1 : s1;
- float s2 = (matrix[5]+1 - 2*q[3]*q[3])/2;
- s2 = s2 < 0.0 ? -s2 : s2;
- float s3 = (matrix[10]+1 - 2*q[3]*q[3])/2;
- s3 = s3 < 0.0 ? -s3 : s3;
- q[0]=(float)sqrt(s1);
- q[1]=(float)sqrt(s2);
- q[2]=(float)sqrt(s3);
-
- // printf("sqrt(%f)\n", (matrix[0]+1 - 2*q[3]*q[3])/2);
- // printf("sqrt(%f)\n", (matrix[5]+1 - 2*q[3]*q[3])/2);
- // printf("sqrt(%f)\n", (matrix[10]+1 - 2*q[3]*q[3])/2);
-
- return q;
- // printf("x: %f; y: %f; z: %f; w: %f; length: %f\n", x,y,z,w,x*x+y*y+z*z+w*w);
- */
-
- float x,y,z,w;
-
- float diagonal = matrix[0] + matrix[5] + matrix[10] + 1;
- float scale = 0.0f;
-
- // If the diagonal is greater than zero
- if(diagonal > 0.00000001)
- {
- // Calculate the scale of the diagonal
- scale = float(sqrt(diagonal ) * 2);
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = ( matrix[9] - matrix[6] ) / scale;
- y = ( matrix[2] - matrix[8] ) / scale;
- z = ( matrix[4] - matrix[1] ) / scale;
- w = 0.25f * scale;
- }
- else
- {
- // If the first element of the diagonal is the greatest value
- if ( matrix[0] > matrix[5] && matrix[0] > matrix[10] )
- {
- // Find the scale according to the first element, and double that value
- scale = (float)sqrt( 1.0f + matrix[0] - matrix[5] - matrix[10] ) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = 0.25f * scale;
- y = (matrix[4] + matrix[1] ) / scale;
- z = (matrix[2] + matrix[8] ) / scale;
- w = (matrix[9] - matrix[6] ) / scale;
- }
- // Else if the second element of the diagonal is the greatest value
- else if ( matrix[5] > matrix[10] )
- {
- // Find the scale according to the second element, and double that value
- scale = (float)sqrt( 1.0f + matrix[5] - matrix[0] - matrix[10] ) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = (matrix[4] + matrix[1] ) / scale;
- y = 0.25f * scale;
- z = (matrix[9] + matrix[6] ) / scale;
- w = (matrix[2] - matrix[8] ) / scale;
- }
- // Else the third element of the diagonal is the greatest value
- else
- {
- // Find the scale according to the third element, and double that value
- scale = (float)sqrt( 1.0f + matrix[10] - matrix[0] - matrix[5] ) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion through the respective equation
- x = (matrix[2] + matrix[8] ) / scale;
- y = (matrix[9] + matrix[6] ) / scale;
- z = 0.25f * scale;
- w = (matrix[4] - matrix[1] ) / scale;
- }
- }
-
- q[0] = x;
- q[1] = y;
- q[2] = z;
- q[3] = w;
-
- return q;
- }
-
-
-
- float* quaternionSlerp(quaternion_t q1, quaternion_t q2, float t, quaternion_t r){
- quaternion_t tmp;
-
-
- // Here we do a check to make sure the 2 quaternions aren't the same, return q1 if they are
- if( fabs(q1[0]-q2[0]) < 0.00001
- && fabs(q1[1]-q2[1]) < 0.00001
- && fabs(q1[2]-q2[2]) < 0.00001
- && fabs(q1[3]-q2[3]) < 0.00001
- ){
- vectorCopy4d(q1, r);
- return q1;
- }
-
- // Following the (b.a) part of the equation, we do a dot product between q1 and q2.
- // We can do a dot product because the same math applied for a 3D vector as a 4D vector.
- float result = vectorDotP4d(q1, q2);
-
- // If the dot product is less than 0, the angle is greater than 90 degrees
- if(result < 0.0f){
- // Negate the second quaternion and the result of the dot product
- vectorScale4d(-1.0f, q2, tmp);
- result = -result;
- }else{
- vectorCopy4d(q2, tmp);
- }
-
- // Set the first and second scale for the interpolation (linear!)
- float scale1 = 1 - t;
- float scale2 = t;
-
- // Check if the angle between the 2 quaternions was big enough to warrant such calculations
- if(1 - result > 0.1f){
- // Get the angle between the 2 quaternions, and then store the sin() of that angle
- float theta = (float)acos(result);
- float sinTheta = (float)sin(theta);
-
- // Calculate the scale for q1 and q2, according to the angle and it's sine value
- scale1 = (float)sin( ( 1 - t ) * theta) / sinTheta;
- scale2 = (float)sin( ( t * theta) ) / sinTheta;
-
- // printf("theta: %f, sin_theta: %f, scale1: %f, scale2: %f\n", theta, sinTheta, scale1, scale2);
- }
-
- vectorLinCombi4d(scale1, q1, scale2, tmp, r);
- // printf("q1: [%f %f %f %f]\n", q1[0], q1[1], q1[2], q1[3]);
- // printf("q2: [%f %f %f %f]\n", q2[0], q2[1], q2[2], q2[3]);
- // printf("r : [%f %f %f %f]\n", r[0], r[1], r[2], r[3]);
- // Return the interpolated quaternion
- return r;
- }
-
-
- void slerpMatrix(float* m1, float* m2, float t, float* r){
- quaternion_t q1,q2,qi;
-
- quaternionFromMatrix(m1, q1);
- quaternionFromMatrix(m2, q2);
- quaternionSlerp(q1, q2, t, qi);
-
- quaternionToMatrix(qi, r);
-
- vectorLinCombi3d((1-t), &m1[12], t, &m2[12], &r[12]); // FIXME: animationen sehen scheisse aus, aber Kollision klappt!!
- // vectorCopy3d(&m1[12], &r[12]);
- }
-