123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
- /*===============================================================
- * Project: Mongoose Tool Kit
- * Author : Terry 'Mongoose' Hendrix
- * Website: http://www.westga.edu/~stu7440/
- * Email : stu7440@westga.edu
- * Object :
- * Comment: 3d math util functions.
- *
- * FIXME: OpenGL matrices are col major OOPS!
- * some are using col some aren't
- *
- *-- History -----------------------------------------------
- *
- * 2001.11.23:
- * Mongoose - Move to OpenGL compatible matrices
- *
- * 2000-03-25:
- * Mongoose - Recreated from GooseEgg prototyping
- *
- * 1999-06-14:
- * Mongoose - Created
- ==============================================================*/
-
- #include <math.h>
- #include <stdio.h>
-
- #include "mtk3d.h"
-
-
- /*
- double mtk3d_norm3d(double u[3])
- {
- return(sqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]));
- }
-
- double mtk3d_norm2d(double u[2])
- {
- return(sqrt(u[0]*u[0]+u[1]*u[1]));
- }
- */
-
- vec_t mtkRandNum(vec_t from, vec_t to)
- {
- return from + (to*rand()/(RAND_MAX+1.0));
- }
-
-
- // Heh, this is scary... try to avoid many indexing computations
- void mtkVectorMatrixMult4dv(double v[4], matrix_t m, double result[4])
- {
- #ifdef OBSOLETE
- int i, j;
-
- for (i = 0; i < 4; i++)
- {
- result[i] = 0;
-
- for (j = 0; j < 4; j++)
- {
- result[i] += m[i][j] * v[j];
- }
- }
- #else
- /////////////////////////////////////////////
- // 0,0 - 0; 0,1 - 1; 0,2 - 2; 0,3 - 3
- // 1,0 - 4; 1,1 - 5; 1,2 - 6; 1,3 - 7
- // 2,0 - 8; 2,1 - 9; 2,2 - 10; 2,3 - 11
- // 3,0 - 12; 3,1 - 13; 3,2 - 14; 3,3 - 15
- /////////////////////////////////////////////
-
-
- // Col major?
- //result[0] = m[ 0] * v[0] + m[ 4] * v[1] + m[ 8] * v[2] + m[12] * v[3];
- //result[1] = m[ 1] * v[0] + m[ 5] * v[1] + m[ 9] * v[2] + m[13] * v[3];
- //result[2] = m[ 2] * v[0] + m[ 6] * v[1] + m[10] * v[2] + m[14] * v[3];
-
- result[0] = m[ 0] * v[0] + m[ 1] * v[1] + m[ 2] * v[2] + m[ 3] * v[3];
- result[1] = m[ 4] * v[0] + m[ 5] * v[1] + m[ 6] * v[2] + m[ 7] * v[3];
- result[2] = m[ 8] * v[0] + m[ 9] * v[1] + m[10] * v[2] + m[11] * v[3];
- result[3] = m[12] * v[0] + m[13] * v[1] + m[14] * v[2] + m[15] * v[3];
- #endif
- }
-
-
- void mtkMatrixPrint(matrix_t matrix)
- {
- #ifdef OBSOLETE
- printf("matrix = {\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
- matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
- matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
- matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
- matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
- #else
- printf("matrix = {\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n}\n",
- matrix[ 0], matrix[ 1], matrix[ 2], matrix[ 3],
- matrix[ 4], matrix[ 5], matrix[ 6], matrix[ 7],
- matrix[ 8], matrix[ 9], matrix[10], matrix[11],
- matrix[12], matrix[13], matrix[14], matrix[15]);
- #endif
- }
-
-
- vec_t mtkDist2d(vec_t x, vec_t y, vec_t x2, vec_t y2)
- {
- return (sqrt( ((x2 - x)*(x2 - x)) + ((y2 - y)*(y2 - y)) ));
- }
-
-
- vec_t mtkDist3d(vec_t x, vec_t y, vec_t z,
- vec_t x2, vec_t y2, vec_t z2)
- {
- return (sqrt( ((x2 - x)*(x2 - x))+((y2 - y)*(y2 - y))+((z2 - z)*(z2 - z))));
- }
-
- vec_t mtkDegToRad(vec_t degrees)
- {
- return ((degrees / 180.0) * MTK_PI); // degrees * (180.0 / MTK_PI);
- }
-
- vec_t mtkRadToDeg(vec_t rad)
- {
- return ((rad / MTK_PI) * 180.0); // rad * (MTK_PI / 180.0);
- }
-
-
- void mtkVectorMatrixMult(vec3_t v, matrix_t m, vec3_t result)
- {
- result[0] = m[ 0] * v[0] + m[ 1] * v[1] + m[ 2] * v[2] + m[ 3] * v[3];
- result[1] = m[ 4] * v[0] + m[ 5] * v[1] + m[ 6] * v[2] + m[ 7] * v[3];
- result[2] = m[ 8] * v[0] + m[ 9] * v[1] + m[10] * v[2] + m[11] * v[3];
- }
-
-
- // Vector from two points
- void mtkVectorSubtract(vec3_t a, vec3_t b, vec3_t result)
- {
- result[0] = a[0] - b[0];
- result[1] = a[1] - b[1];
- result[2] = a[2] - b[2];
- }
-
-
- void mtkVectorAdd(vec3_t a, vec3_t b, vec3_t result)
- {
- result[0] = a[0] + b[0];
- result[1] = a[1] + b[1];
- result[2] = a[2] + b[2];
- }
-
-
- // Magnitude
- vec_t mtkVectorNorm(vec3_t v)
- {
- return (vec_t)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
- }
-
-
- void mtkVectorNormalize(vec3_t v, vec3_t result)
- {
- vec_t mag = mtkVectorNorm(v);
-
-
- result[0] = v[0] / mag;
- result[1] = v[1] / mag;
- result[2] = v[2] / mag;
- }
-
-
- void mtkVectorCrossProduct(vec3_t a, vec3_t b, vec3_t normal)
- {
- normal[0] = a[1]*b[2] - a[2]*b[1];
- normal[0] = a[2]*b[0] - a[0]*b[2];
- normal[0] = a[0]*b[1] - a[1]*b[0];
- }
-
-
- vec_t mtkVectorDotProduct(vec3_t a, vec3_t b)
- {
- return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
- }
-
-
- // Heh, this is scary... try to avoid many indexing computations
- void mtkMatrixMult(matrix_t m1, matrix_t m2, matrix_t mp)
- {
- #ifdef MTK3D_MULT_DIM_MATRIX
- int i,j;
-
-
- for (i = 0; i < 4; i++)
- {
- for (j = 0 ; j < 4; j++)
- {
- mp[i][j] = m1[i][0] * m2[0][j] +
- m1[i][1] * m2[1][j] +
- m1[i][2] * m2[2][j] +
- m1[i][3] * m2[3][j];
- }
- }
- #else
- /////////////////////////////////////////////
- // 0,0 - 0; 0,1 - 1; 0,2 - 2; 0,3 - 3
- // 1,0 - 4; 1,1 - 5; 1,2 - 6; 1,3 - 7
- // 2,0 - 8; 2,1 - 9; 2,2 - 10; 2,3 - 11
- // 3,0 - 12; 3,1 - 13; 3,2 - 14; 3,3 - 15
- /////////////////////////////////////////////
-
- mp[ 0] = m1[0] * m2[0] + m1[1] * m2[4] + m1[2] * m2[ 8] + m1[3] * m2[12];
- mp[ 1] = m1[0] * m2[1] + m1[1] * m2[5] + m1[2] * m2[ 9] + m1[3] * m2[13];
- mp[ 2] = m1[0] * m2[2] + m1[1] * m2[6] + m1[2] * m2[10] + m1[3] * m2[14];
- mp[ 3] = m1[0] * m2[3] + m1[1] * m2[7] + m1[2] * m2[11] + m1[3] * m2[15];
-
- mp[ 4] = m1[4] * m2[0] + m1[5] * m2[4] + m1[6] * m2[ 8] + m1[7] * m2[12];
- mp[ 5] = m1[4] * m2[1] + m1[5] * m2[5] + m1[6] * m2[ 9] + m1[7] * m2[13];
- mp[ 6] = m1[4] * m2[2] + m1[5] * m2[6] + m1[6] * m2[10] + m1[7] * m2[14];
- mp[ 7] = m1[4] * m2[3] + m1[5] * m2[7] + m1[6] * m2[11] + m1[7] * m2[15];
-
- mp[ 8] = m1[8] * m2[0] + m1[9] * m2[4] + m1[10] * m2[ 8] + m1[11] * m2[12];
- mp[ 9] = m1[8] * m2[1] + m1[9] * m2[5] + m1[10] * m2[ 9] + m1[11] * m2[13];
- mp[10] = m1[8] * m2[2] + m1[9] * m2[6] + m1[10] * m2[10] + m1[11] * m2[14];
- mp[11] = m1[8] * m2[3] + m1[9] * m2[7] + m1[10] * m2[11] + m1[11] * m2[15];
-
- mp[12] = m1[12] * m2[0] + m1[13] * m2[4] + m1[14] * m2[ 8] + m1[15] * m2[12];
- mp[13] = m1[12] * m2[1] + m1[13] * m2[5] + m1[14] * m2[ 9] + m1[15] * m2[13];
- mp[14] = m1[12] * m2[2] + m1[13] * m2[6] + m1[14] * m2[10] + m1[15] * m2[14];
- mp[15] = m1[12] * m2[3] + m1[13] * m2[7] + m1[14] * m2[11] + m1[15] * m2[15];
- #endif
- }
-
-
- void mtkMatrixConvert3x3ToMtk(float *m3x3, matrix_t dest)
- {
- if (!m3x3)
- {
- mtkMatrixIdentity(dest);
- return;
- }
-
- dest[0] = m3x3[0]; dest[1] = m3x3[1]; dest[2 ] = m3x3[2];
- dest[4] = m3x3[3]; dest[5] = m3x3[4]; dest[6 ] = m3x3[5];
- dest[8] = m3x3[6]; dest[9] = m3x3[7]; dest[10] = m3x3[8];
-
- // yeah, wolf
- dest[11] = dest[12] = dest[13] = dest[14] = 0.0f;
- dest[15] = 1.0f;
- }
-
-
- void mtkMatrixCopy(matrix_t source, matrix_t dest)
- {
- #ifdef OBSOLETE
- int i,j;
-
-
- for(i = 0; i < 4; i++)
- {
- for(j = 0 ; j < 4; j++)
- {
- dest[i][j] = source[i][j];
- }
- }
- #else
- dest[ 0] = source[ 0];
- dest[ 1] = source[ 1];
- dest[ 2] = source[ 2];
- dest[ 3] = source[ 3];
-
- dest[ 4] = source[ 4];
- dest[ 5] = source[ 5];
- dest[ 6] = source[ 6];
- dest[ 7] = source[ 7];
-
- dest[ 8] = source[8];
- dest[ 9] = source[9];
- dest[10] = source[10];
- dest[11] = source[11];
-
- dest[12] = source[12];
- dest[13] = source[13];
- dest[14] = source[14];
- dest[15] = source[15];
- #endif
- }
-
-
- void mtkMatrixTransform(matrix_t t, vec3_t p)
- {
- vec_t m1[4];
-
-
- m1[0] = p[0];
- m1[1] = p[1];
- m1[2] = p[2];
- m1[3] = 1;
-
- #ifdef OBSOLETE
- p[0] = t[0][0]*m1[0] + t[1][0]*m1[1] + t[2][0]*m1[2] + t[3][0]*m1[3];
- p[1] = t[0][1]*m1[0] + t[1][1]*m1[1] + t[2][1]*m1[2] + t[3][1]*m1[3];
- p[2] = t[0][2]*m1[0] + t[1][2]*m1[1] + t[2][2]*m1[2] + t[3][2]*m1[3];
- #else
- p[0] = t[0] * m1[0] + t[4] * m1[1] + t[ 8] * m1[2] + t[12] * m1[3];
- p[1] = t[1] * m1[0] + t[5] * m1[1] + t[ 9] * m1[2] + t[13] * m1[3];
- p[2] = t[2] * m1[0] + t[6] * m1[1] + t[10] * m1[2] + t[14] * m1[3];
- #endif
- }
-
-
- void mtkMatrixIdentity(matrix_t matrix)
- {
- #ifdef OBSOLETE
- matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0; matrix[0][3] = 0;
- matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0; matrix[1][3] = 0;
- matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1; matrix[2][3] = 0;
- matrix[3][0] = 0; matrix[3][1] = 0; matrix[3][2] = 0; matrix[3][3] = 1;
- #else
- matrix[ 0] = 1; matrix[ 1] = 0; matrix[ 2] = 0; matrix[ 3] = 0;
- matrix[ 4] = 0; matrix[ 5] = 1; matrix[ 6] = 0; matrix[ 7] = 0;
- matrix[ 8] = 0; matrix[ 9] = 0; matrix[10] = 1; matrix[11] = 0;
- matrix[12] = 0; matrix[13] = 0; matrix[14] = 0; matrix[15] = 1;
- #endif
- }
-
-
- // FIXME: Might want to make scale matrix, etc consts
- void mtkMatrixScale(matrix_t matrix, vec_t sx, vec_t sy, vec_t sz)
- {
- matrix_t tmp, smatrix;
-
-
- #ifdef OBSOLETE
- smatrix[0][0] = sx;smatrix[0][1] = 0; smatrix[0][2] = 0; smatrix[0][3] = 0;
- smatrix[1][0] = 0; smatrix[1][1] = sy;smatrix[1][2] = 0; smatrix[1][3] = 0;
- smatrix[2][0] = 0; smatrix[2][1] = 0; smatrix[2][2] = sz;smatrix[2][3] = 0;
- smatrix[3][0] = 0; smatrix[3][1] = 0; smatrix[3][2] = 0; smatrix[3][3] = 1;
- #else
- smatrix[ 0] = sx;smatrix[ 1] = 0; smatrix[ 2] = 0; smatrix[ 3] = 0;
- smatrix[ 4] = 0; smatrix[ 5] = sy;smatrix[ 6] = 0; smatrix[ 7] = 0;
- smatrix[ 8] = 0; smatrix[ 9] = 0; smatrix[10] = sz;smatrix[11] = 0;
- smatrix[12] = 0; smatrix[13] = 0; smatrix[14] = 0; smatrix[15] = 1;
- #endif
-
- mtkMatrixMult(matrix, smatrix, tmp);
- mtkMatrixCopy(tmp, matrix);
- }
-
- void mtkMatrixRotate(matrix_t matrix, vec_t ax, vec_t ay, vec_t az)
- {
- matrix_t xmat, ymat, zmat, tmp, tmp2;
-
-
- #ifdef OBSOLETE
- xmat[0][0]=1; xmat[0][1]=0; xmat[0][2]=0; xmat[0][3]=0;
- xmat[1][0]=0; xmat[1][1]=cos(ax); xmat[1][2]=sin(ax); xmat[1][3]=0;
- xmat[2][0]=0; xmat[2][1]=-sin(ax); xmat[2][2]=cos(ax); xmat[2][3]=0;
- xmat[3][0]=0; xmat[3][1]=0; xmat[3][2]=0; xmat[3][3]=1;
-
- ymat[0][0]=cos(ay); ymat[0][1]=0; ymat[0][2]=-sin(ay); ymat[0][3]=0;
- ymat[1][0]=0; ymat[1][1]=1; ymat[1][2]=0; ymat[1][3]=0;
- ymat[2][0]=sin(ay); ymat[2][1]=0; ymat[2][2]=cos(ay); ymat[2][3]=0;
- ymat[3][0]=0; ymat[3][1]=0; ymat[3][2]=0; ymat[3][3]=1;
-
- zmat[0][0]=cos(az); zmat[0][1]=sin(az); zmat[0][2]=0; zmat[0][3]=0;
- zmat[1][0]=-sin(az); zmat[1][1]=cos(az); zmat[1][2]=0; zmat[1][3]=0;
- zmat[2][0]=0; zmat[2][1]=0; zmat[2][2]=1; zmat[2][3]=0;
- zmat[3][0]=0; zmat[3][1]=0; zmat[3][2]=0; zmat[3][3]=1;
- #else
- xmat[ 0]=1; xmat[ 1]=0; xmat[ 2]=0; xmat[ 3]=0;
- xmat[ 4]=0; xmat[ 5]=cos(ax); xmat[ 6]=sin(ax); xmat[ 7]=0;
- xmat[ 8]=0; xmat[ 9]=-sin(ax); xmat[10]=cos(ax); xmat[11]=0;
- xmat[12]=0; xmat[13]=0; xmat[14]=0; xmat[15]=1;
-
- ymat[ 0]=cos(ay); ymat[ 1]=0; ymat[ 2]=-sin(ay); ymat[ 3]=0;
- ymat[ 4]=0; ymat[ 5]=1; ymat[ 6]=0; ymat[ 7]=0;
- ymat[ 8]=sin(ay); ymat[ 9]=0; ymat[10]=cos(ay); ymat[11]=0;
- ymat[12]=0; ymat[13]=0; ymat[14]=0; ymat[15]=1;
-
- zmat[ 0]=cos(az); zmat[ 1]=sin(az); zmat[ 2]=0; zmat[ 3]=0;
- zmat[ 4]=-sin(az); zmat[ 5]=cos(az); zmat[ 6]=0; zmat[ 7]=0;
- zmat[ 8]=0; zmat[ 9]=0; zmat[10]=1; zmat[11]=0;
- zmat[12]=0; zmat[13]=0; zmat[14]=0; zmat[15]=1;
- #endif
-
- mtkMatrixMult(matrix, ymat, tmp);
- mtkMatrixMult(tmp, xmat, tmp2);
- mtkMatrixMult(tmp2, zmat, matrix);
- }
-
- void mtkMatrixTranslate(matrix_t matrix, vec_t tx, vec_t ty, vec_t tz)
- {
- matrix_t tmat, tmp;
-
- #ifdef OBSOLETE
- tmat[0][0]=1; tmat[0][1]=0; tmat[0][2]=0; tmat[0][3]=0;
- tmat[1][0]=0; tmat[1][1]=1; tmat[1][2]=0; tmat[1][3]=0;
- tmat[2][0]=0; tmat[2][1]=0; tmat[2][2]=1; tmat[2][3]=0;
- tmat[3][0]=tx; tmat[3][1]=ty; tmat[3][2]=tz; tmat[3][3]=1;
- #else
- tmat[ 0]=1; tmat[ 1]=0; tmat[ 2]=0; tmat[ 3]=0;
- tmat[ 4]=0; tmat[ 5]=1; tmat[ 6]=0; tmat[ 7]=0;
- tmat[ 8]=0; tmat[ 9]=0; tmat[10]=1; tmat[11]=0;
- tmat[12]=tx; tmat[13]=ty; tmat[14]=tz; tmat[15]=1;
- #endif
-
- mtkMatrixMult(matrix, tmat, tmp);
- mtkMatrixCopy(tmp, matrix);
- }
-
- ////////////////////////////////
-
- void mtkQuaternionCopy(quaternion_t source, quaternion_t dest)
- {
- dest.x = source.x;
- dest.y = source.y;
- dest.z = source.z;
- dest.w = source.w;
- }
-
-
- void mtkQuaternionSlerp(quaternion_t qI, quaternion_t qA, quaternion_t qB,
- float time)
- {
- /*******************************************************************
- * Spherical Linear Interpolation algorthim
- *-----------------------------------------------------------------
- *
- * Interpolate between A and B rotations ( Find qI )
- *
- * qI = (((qB . qA)^ -1)^ Time) qA
- *
- * http://www.magic-software.com/Documentation/quat.pdf
- *
- * Thanks to digiben for algorithms and basis of the notes in
- * this func
- *
- *******************************************************************/
-
- float result, scaleA, scaleB, theta, sinTheta;
-
-
- // Don't bother if it's the same rotation, it's the same as the result
- if (&qA == &qB ||
- qA.x == qB.x && qA.y == qB.y && qA.z == qB.z && qA.w == qB.w)
- {
- mtkQuaternionCopy(qA, qI);
- return;
- }
-
- // A . B
- result = (qA.x * qB.x) + (qA.y * qB.y) + (qA.z * qB.z) + (qA.w * qB.w);
-
- // If the dot product is less than 0, the angle is greater than 90 degrees
- if (result < 0.0f)
- {
- // Negate quaternion B and the result of the dot product
- qB.x = -qB.x;
- qB.y = -qB.y;
- qB.z = -qB.z;
- qB.w = -qB.w;
-
- result = -result;
- }
-
- // Set the first and second scale for the interpolation
- scaleA = 1 - time;
- scaleB = time;
-
- // Next, we want to actually calculate the spherical interpolation. Since this
- // calculation is quite computationally expensive, we want to only perform it
- // if the angle between the 2 quaternions is large enough to warrant it. If the
- // angle is fairly small, we can actually just do a simpler linear interpolation
- // of the 2 quaternions, and skip all the complex math. We create a "delta" value
- // of 0.1 to say that if the cosine of the angle (result of the dot product) between
- // the 2 quaternions is smaller than 0.1, then we do NOT want to perform the full on
- // interpolation using. This is because you won't really notice the difference.
-
- // 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
- theta = (float)acos(result);
- sinTheta = (float)sin(theta);
-
- // Calculate the scale for qA and qB, according to
- // the angle and it's sine value
- scaleA = (float)sin((1 - time) * theta) / sinTheta;
- scaleB = (float)sin((time * theta)) / sinTheta;
- }
-
- // Calculate the x, y, z and w values for the quaternion by using a special
- // form of linear interpolation for quaternions.
- qI.x = (scaleA * qA.x) + (scaleB * qB.x);
- qI.y = (scaleA * qA.y) + (scaleB * qB.y);
- qI.z = (scaleA * qA.z) + (scaleB * qB.z);
- qI.w = (scaleA * qA.w) + (scaleB * qB.w);
- }
-
-
- void mtkQuaternionFrom3x3Matrix(float *m3x3, quaternion_t q)
- {
- matrix_t matrix;
-
-
- mtkMatrixConvert3x3ToMtk(m3x3, matrix);
- mtkQuaternionFromMatrix(matrix, q);
- }
-
-
- void mtkQuaternionFromMatrix(matrix_t matrix, quaternion_t q)
- {
- float diagonal, scale;
-
-
- diagonal = matrix[0] + matrix[5] + matrix[10] + 1;
- scale = 0.0f;
-
- mtkQuaternionIdentity(q);
-
- // diagonal is greater than 'zero'
- if (diagonal > 0.00000001)
- {
- scale = float(sqrt(diagonal) * 2);
-
- q.x = (matrix[9] - matrix[6]) / scale;
- q.y = (matrix[2] - matrix[8]) / scale;
- q.z = (matrix[4] - matrix[1]) / scale;
- q.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 it
- scale = (float)sqrt(1.0f + matrix[0] - matrix[5] - matrix[10]) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion
- q.x = 0.25f * scale;
- q.y = (matrix[4] + matrix[1]) / scale;
- q.z = (matrix[2] + matrix[8]) / scale;
- q.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 it
- scale = (float)sqrt(1.0f + matrix[5] - matrix[0] - matrix[10]) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion
- q.x = (matrix[4] + matrix[1]) / scale;
- q.y = 0.25f * scale;
- q.z = (matrix[9] + matrix[6]) / scale;
- q.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 it
- scale = (float)sqrt(1.0f + matrix[10] - matrix[0] - matrix[5]) * 2.0f;
-
- // Calculate the x, y, x and w of the quaternion
- q.x = (matrix[2] + matrix[8]) / scale;
- q.y = (matrix[9] + matrix[6]) / scale;
- q.z = 0.25f * scale;
- q.w = (matrix[4] - matrix[1]) / scale;
- }
- }
- }
-
-
- void mtkQuaternionToMatrix(quaternion_t q, matrix_t m)
- {
- #ifdef OBSOLETE
- float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
-
-
- x2 = q.x + q.x; y2 = q.y + q.y; z2 = q.z + q.z;
- xx = q.x * x2; xy = q.x * y2; xz = q.x * z2;
- yy = q.y * y2; yz = q.y * z2; zz = q.z * z2;
- wx = q.w * x2; wy = q.w * y2; wz = q.w * z2;
-
- m[ 0] = 1.0 - (yy + zz);
- m[ 1] = xy - wz;
- m[ 2] = xz + wy;
- m[ 3] = 0.0;
-
- m[ 4] = xy + wz;
- m[ 5] = 1.0 - (xx + zz);
- m[ 6] = yz - wx;
- m[ 7] = 0.0;
-
- m[ 8] = xz - wy;
- m[ 9] = yz + wx;
- m[10] = 1.0 - (xx + yy);
- m[11] = 0.0;
-
- m[12] = 0;
- m[13] = 0;
- m[14] = 0;
- m[15] = 1;
- #else
- m[ 0] = 1.0f - 2.0f * (q.y*q.y + q.z*q.z);
- m[ 1] = 2.0f * (q.x*q.y - q.w*q.z);
- m[ 2] = 2.0f * (q.x*q.z + q.w*q.y);
- m[ 3] = 0.0f;
-
- m[ 4] = 2.0f * (q.x*q.y + q.w*q.z);
- m[ 5] = 1.0f - 2.0f * (q.x*q.x + q.z*q.z);
- m[ 6] = 2.0f * (q.y*q.z - q.w*q.x);
- m[ 7] = 0.0f;
-
- m[ 8] = 2.0f * (q.x*q.z - q.w*q.y);
- m[ 9] = 2.0f * (q.y*q.z + q.w*q.x);
- m[10] = 1.0 - 2.0f * (q.x*q.x + q.y*q.y);
- m[11] = 0.0f;
-
- m[12] = 0.0f;
- m[13] = 0.0f;
- m[14] = 0.0f;
- m[15] = 1.0f;
- #endif
- }
-
-
- void mtkQuaternionIdentity(quaternion_t q)
- {
- q.w = 1.0;
- q.x = 0.0;
- q.y = 0.0;
- q.z = 0.0;
- }
-
-
- void mtkQuaternionSet(quaternion_t q, float angle, float x, float y, float z)
- {
- float temp, dist;
-
- // Normalize
- temp = x*x + y*y + z*z;
-
- dist = (float)(1.0 / sqrt(temp));
-
- x *= dist;
- y *= dist;
- z *= dist;
-
- q.x = x;
- q.y = y;
- q.z = z;
-
- q.w = (float)cos(angle / 2.0f);
- }
-
-
- void mtkQuaternionMult(quaternion_t a, quaternion_t b, quaternion_t result)
- {
- result.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y;
- result.y = a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z;
- result.z = a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x;
- result.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z;
-
- // Quaternion needs to be a unit quaternion
- mtkQuaternionNormalize(result);
- }
-
-
- void mtkQuaternionNormalize(quaternion_t q)
- {
- float dist, square;
-
-
- square = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
-
- if (square > 0.00000001)
- {
- dist = (float)(1.0 / sqrt(square));
- }
- else
- {
- dist = 1;
- }
-
- q.x *= dist;
- q.y *= dist;
- q.z *= dist;
- q.w *= dist;
- }
|