Blender  V2.59
math_rotation.c
Go to the documentation of this file.
00001 /*
00002  * $Id: math_rotation.c 35954 2011-04-02 03:05:49Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  
00023  * The Original Code is: some of this file.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * */
00027 
00034 #include <assert.h>
00035 #include "BLI_math.h"
00036 
00037 /******************************** Quaternions ********************************/
00038 
00039 /* used to test is a quat is not normalized */
00040 #define QUAT_EPSILON 0.0001
00041 
00042 /* convenience, avoids setting Y axis everywhere */
00043 void unit_axis_angle(float axis[3], float *angle)
00044 {
00045         axis[0]= 0.0f;
00046         axis[1]= 1.0f;
00047         axis[2]= 0.0f;
00048         *angle= 0.0f;
00049 }
00050 
00051 
00052 void unit_qt(float q[4])
00053 {
00054         q[0]= 1.0f;
00055         q[1]= q[2]= q[3]= 0.0f;
00056 }
00057 
00058 void copy_qt_qt(float *q1, const float *q2)
00059 {
00060         q1[0]= q2[0];
00061         q1[1]= q2[1];
00062         q1[2]= q2[2];
00063         q1[3]= q2[3];
00064 }
00065 
00066 int is_zero_qt(float *q)
00067 {
00068         return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0);
00069 }
00070 
00071 void mul_qt_qtqt(float *q, const float *q1, const float *q2)
00072 {
00073         float t0,t1,t2;
00074 
00075         t0=   q1[0]*q2[0]-q1[1]*q2[1]-q1[2]*q2[2]-q1[3]*q2[3];
00076         t1=   q1[0]*q2[1]+q1[1]*q2[0]+q1[2]*q2[3]-q1[3]*q2[2];
00077         t2=   q1[0]*q2[2]+q1[2]*q2[0]+q1[3]*q2[1]-q1[1]*q2[3];
00078         q[3]= q1[0]*q2[3]+q1[3]*q2[0]+q1[1]*q2[2]-q1[2]*q2[1];
00079         q[0]=t0; 
00080         q[1]=t1; 
00081         q[2]=t2;
00082 }
00083 
00084 /* Assumes a unit quaternion */
00085 void mul_qt_v3(const float *q, float *v)
00086 {
00087         float t0, t1, t2;
00088 
00089         t0=  -q[1]*v[0]-q[2]*v[1]-q[3]*v[2];
00090         t1=   q[0]*v[0]+q[2]*v[2]-q[3]*v[1];
00091         t2=   q[0]*v[1]+q[3]*v[0]-q[1]*v[2];
00092         v[2]= q[0]*v[2]+q[1]*v[1]-q[2]*v[0];
00093         v[0]=t1; 
00094         v[1]=t2;
00095 
00096         t1=   t0*-q[1]+v[0]*q[0]-v[1]*q[3]+v[2]*q[2];
00097         t2=   t0*-q[2]+v[1]*q[0]-v[2]*q[1]+v[0]*q[3];
00098         v[2]= t0*-q[3]+v[2]*q[0]-v[0]*q[2]+v[1]*q[1];
00099         v[0]=t1; 
00100         v[1]=t2;
00101 }
00102 
00103 void conjugate_qt(float *q)
00104 {
00105         q[1] = -q[1];
00106         q[2] = -q[2];
00107         q[3] = -q[3];
00108 }
00109 
00110 float dot_qtqt(const float q1[4], const float q2[4])
00111 {
00112         return q1[0]*q2[0] + q1[1]*q2[1] + q1[2]*q2[2] + q1[3]*q2[3];
00113 }
00114 
00115 void invert_qt(float *q)
00116 {
00117         float f = dot_qtqt(q, q);
00118 
00119         if (f == 0.0f)
00120                 return;
00121 
00122         conjugate_qt(q);
00123         mul_qt_fl(q, 1.0f/f);
00124 }
00125 
00126 void invert_qt_qt(float *q1, const float *q2)
00127 {
00128         copy_qt_qt(q1, q2);
00129         invert_qt(q1);
00130 }
00131 
00132 /* simple mult */
00133 void mul_qt_fl(float *q, const float f)
00134 {
00135         q[0] *= f;
00136         q[1] *= f;
00137         q[2] *= f;
00138         q[3] *= f;
00139 }
00140 
00141 void sub_qt_qtqt(float q[4], const float q1[4], const float q2[4])
00142 {
00143         float nq2[4];
00144 
00145         nq2[0]= -q2[0];
00146         nq2[1]=  q2[1];
00147         nq2[2]=  q2[2];
00148         nq2[3]=  q2[3];
00149 
00150         mul_qt_qtqt(q, q1, nq2);
00151 }
00152 
00153 /* angular mult factor */
00154 void mul_fac_qt_fl(float *q, const float fac)
00155 {
00156         float angle= fac*saacos(q[0]);  /* quat[0]= cos(0.5*angle), but now the 0.5 and 2.0 rule out */
00157         
00158         float co= (float)cos(angle);
00159         float si= (float)sin(angle);
00160         q[0]= co;
00161         normalize_v3(q+1);
00162         mul_v3_fl(q+1, si);
00163 }
00164 
00165 /* skip error check, currently only needed by mat3_to_quat_is_ok */
00166 static void quat_to_mat3_no_error(float m[][3], const float q[4])
00167 {
00168         double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
00169 
00170         q0= M_SQRT2 * (double)q[0];
00171         q1= M_SQRT2 * (double)q[1];
00172         q2= M_SQRT2 * (double)q[2];
00173         q3= M_SQRT2 * (double)q[3];
00174 
00175         qda= q0*q1;
00176         qdb= q0*q2;
00177         qdc= q0*q3;
00178         qaa= q1*q1;
00179         qab= q1*q2;
00180         qac= q1*q3;
00181         qbb= q2*q2;
00182         qbc= q2*q3;
00183         qcc= q3*q3;
00184 
00185         m[0][0]= (float)(1.0-qbb-qcc);
00186         m[0][1]= (float)(qdc+qab);
00187         m[0][2]= (float)(-qdb+qac);
00188 
00189         m[1][0]= (float)(-qdc+qab);
00190         m[1][1]= (float)(1.0-qaa-qcc);
00191         m[1][2]= (float)(qda+qbc);
00192 
00193         m[2][0]= (float)(qdb+qac);
00194         m[2][1]= (float)(-qda+qbc);
00195         m[2][2]= (float)(1.0-qaa-qbb);
00196 }
00197 
00198 
00199 void quat_to_mat3(float m[][3], const float q[4])
00200 {
00201 #ifdef DEBUG
00202         float f;
00203         if(!((f=dot_qtqt(q, q))==0.0f || (fabsf(f-1.0f) < (float)QUAT_EPSILON))) {
00204                 fprintf(stderr, "Warning! quat_to_mat3() called with non-normalized: size %.8f *** report a bug ***\n", f);
00205         }
00206 #endif
00207 
00208         quat_to_mat3_no_error(m, q);
00209 }
00210 
00211 void quat_to_mat4(float m[][4], const float q[4])
00212 {
00213         double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
00214 
00215 #ifdef DEBUG
00216         if(!((q0=dot_qtqt(q, q))==0.0f || (fabsf(q0-1.0f) < (float)QUAT_EPSILON))) {
00217                 fprintf(stderr, "Warning! quat_to_mat4() called with non-normalized: size %.8f *** report a bug ***\n", (float)q0);
00218         }
00219 #endif
00220 
00221         q0= M_SQRT2 * (double)q[0];
00222         q1= M_SQRT2 * (double)q[1];
00223         q2= M_SQRT2 * (double)q[2];
00224         q3= M_SQRT2 * (double)q[3];
00225 
00226         qda= q0*q1;
00227         qdb= q0*q2;
00228         qdc= q0*q3;
00229         qaa= q1*q1;
00230         qab= q1*q2;
00231         qac= q1*q3;
00232         qbb= q2*q2;
00233         qbc= q2*q3;
00234         qcc= q3*q3;
00235 
00236         m[0][0]= (float)(1.0-qbb-qcc);
00237         m[0][1]= (float)(qdc+qab);
00238         m[0][2]= (float)(-qdb+qac);
00239         m[0][3]= 0.0f;
00240 
00241         m[1][0]= (float)(-qdc+qab);
00242         m[1][1]= (float)(1.0-qaa-qcc);
00243         m[1][2]= (float)(qda+qbc);
00244         m[1][3]= 0.0f;
00245 
00246         m[2][0]= (float)(qdb+qac);
00247         m[2][1]= (float)(-qda+qbc);
00248         m[2][2]= (float)(1.0-qaa-qbb);
00249         m[2][3]= 0.0f;
00250         
00251         m[3][0]= m[3][1]= m[3][2]= 0.0f;
00252         m[3][3]= 1.0f;
00253 }
00254 
00255 void mat3_to_quat(float *q, float wmat[][3])
00256 {
00257         double tr, s;
00258         float mat[3][3];
00259 
00260         /* work on a copy */
00261         copy_m3_m3(mat, wmat);
00262         normalize_m3(mat);                      /* this is needed AND a NormalQuat in the end */
00263         
00264         tr= 0.25* (double)(1.0f+mat[0][0]+mat[1][1]+mat[2][2]);
00265         
00266         if(tr>(double)FLT_EPSILON) {
00267                 s= sqrt(tr);
00268                 q[0]= (float)s;
00269                 s= 1.0/(4.0*s);
00270                 q[1]= (float)((mat[1][2]-mat[2][1])*s);
00271                 q[2]= (float)((mat[2][0]-mat[0][2])*s);
00272                 q[3]= (float)((mat[0][1]-mat[1][0])*s);
00273         }
00274         else {
00275                 if(mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) {
00276                         s= 2.0*sqrtf(1.0f + mat[0][0] - mat[1][1] - mat[2][2]);
00277                         q[1]= (float)(0.25*s);
00278 
00279                         s= 1.0/s;
00280                         q[0]= (float)((mat[2][1] - mat[1][2])*s);
00281                         q[2]= (float)((mat[1][0] + mat[0][1])*s);
00282                         q[3]= (float)((mat[2][0] + mat[0][2])*s);
00283                 }
00284                 else if(mat[1][1] > mat[2][2]) {
00285                         s= 2.0*sqrtf(1.0f + mat[1][1] - mat[0][0] - mat[2][2]);
00286                         q[2]= (float)(0.25*s);
00287 
00288                         s= 1.0/s;
00289                         q[0]= (float)((mat[2][0] - mat[0][2])*s);
00290                         q[1]= (float)((mat[1][0] + mat[0][1])*s);
00291                         q[3]= (float)((mat[2][1] + mat[1][2])*s);
00292                 }
00293                 else {
00294                         s= 2.0*sqrtf(1.0 + mat[2][2] - mat[0][0] - mat[1][1]);
00295                         q[3]= (float)(0.25*s);
00296 
00297                         s= 1.0/s;
00298                         q[0]= (float)((mat[1][0] - mat[0][1])*s);
00299                         q[1]= (float)((mat[2][0] + mat[0][2])*s);
00300                         q[2]= (float)((mat[2][1] + mat[1][2])*s);
00301                 }
00302         }
00303 
00304         normalize_qt(q);
00305 }
00306 
00307 void mat4_to_quat(float *q, float m[][4])
00308 {
00309         float mat[3][3];
00310         
00311         copy_m3_m4(mat, m);
00312         mat3_to_quat(q,mat);
00313 }
00314 
00315 void mat3_to_quat_is_ok(float q[4], float wmat[3][3])
00316 {
00317         float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], angle, si, co, nor[3];
00318 
00319         /* work on a copy */
00320         copy_m3_m3(mat, wmat);
00321         normalize_m3(mat);
00322         
00323         /* rotate z-axis of matrix to z-axis */
00324 
00325         nor[0] = mat[2][1];             /* cross product with (0,0,1) */
00326         nor[1] =  -mat[2][0];
00327         nor[2] = 0.0;
00328         normalize_v3(nor);
00329         
00330         co= mat[2][2];
00331         angle= 0.5f*saacos(co);
00332         
00333         co= (float)cos(angle);
00334         si= (float)sin(angle);
00335         q1[0]= co;
00336         q1[1]= -nor[0]*si;              /* negative here, but why? */
00337         q1[2]= -nor[1]*si;
00338         q1[3]= -nor[2]*si;
00339 
00340         /* rotate back x-axis from mat, using inverse q1 */
00341         quat_to_mat3_no_error( matr,q1);
00342         invert_m3_m3(matn, matr);
00343         mul_m3_v3(matn, mat[0]);
00344         
00345         /* and align x-axes */
00346         angle= (float)(0.5*atan2(mat[0][1], mat[0][0]));
00347         
00348         co= (float)cos(angle);
00349         si= (float)sin(angle);
00350         q2[0]= co;
00351         q2[1]= 0.0f;
00352         q2[2]= 0.0f;
00353         q2[3]= si;
00354         
00355         mul_qt_qtqt(q, q1, q2);
00356 }
00357 
00358 
00359 float normalize_qt(float *q)
00360 {
00361         float len;
00362         
00363         len= (float)sqrt(dot_qtqt(q, q));
00364         if(len!=0.0f) {
00365                 mul_qt_fl(q, 1.0f/len);
00366         }
00367         else {
00368                 q[1]= 1.0f;
00369                 q[0]= q[2]= q[3]= 0.0f;                 
00370         }
00371 
00372         return len;
00373 }
00374 
00375 float normalize_qt_qt(float r[4], const float q[4])
00376 {
00377         copy_qt_qt(r, q);
00378         return normalize_qt(r);
00379 }
00380 
00381 /* note: expects vectors to be normalized */
00382 void rotation_between_vecs_to_quat(float *q, const float v1[3], const float v2[3])
00383 {
00384         float axis[3];
00385         float angle;
00386         
00387         cross_v3_v3v3(axis, v1, v2);
00388         
00389         angle = angle_normalized_v3v3(v1, v2);
00390         
00391         axis_angle_to_quat(q, axis, angle);
00392 }
00393 
00394 void rotation_between_quats_to_quat(float *q, const float q1[4], const float q2[4])
00395 {
00396         float tquat[4];
00397         double dot = 0.0f;
00398         int x;
00399 
00400         copy_qt_qt(tquat, q1);
00401         conjugate_qt(tquat);
00402         dot = 1.0f / dot_qtqt(tquat, tquat);
00403 
00404         for(x = 0; x < 4; x++)
00405                 tquat[x] *= dot;
00406 
00407         mul_qt_qtqt(q, tquat, q2);
00408 }
00409 
00410 
00411 void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
00412 {
00413         float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1;
00414         
00415         assert(axis >= 0 && axis <= 5);
00416         assert(upflag >= 0 && upflag <= 2);
00417         
00418         /* first rotate to axis */
00419         if(axis>2) {    
00420                 x2= vec[0] ; y2= vec[1] ; z2= vec[2];
00421                 axis-= 3;
00422         }
00423         else {
00424                 x2= -vec[0] ; y2= -vec[1] ; z2= -vec[2];
00425         }
00426         
00427         q[0]=1.0; 
00428         q[1]=q[2]=q[3]= 0.0;
00429 
00430         len1= (float)sqrt(x2*x2+y2*y2+z2*z2);
00431         if(len1 == 0.0f) return;
00432 
00433         /* nasty! I need a good routine for this...
00434          * problem is a rotation of an Y axis to the negative Y-axis for example.
00435          */
00436 
00437         if(axis==0) {   /* x-axis */
00438                 nor[0]= 0.0;
00439                 nor[1]= -z2;
00440                 nor[2]= y2;
00441 
00442                 if(fabs(y2)+fabs(z2)<0.0001)
00443                         nor[1]= 1.0;
00444 
00445                 co= x2;
00446         }
00447         else if(axis==1) {      /* y-axis */
00448                 nor[0]= z2;
00449                 nor[1]= 0.0;
00450                 nor[2]= -x2;
00451                 
00452                 if(fabs(x2)+fabs(z2)<0.0001)
00453                         nor[2]= 1.0;
00454                 
00455                 co= y2;
00456         }
00457         else {                  /* z-axis */
00458                 nor[0]= -y2;
00459                 nor[1]= x2;
00460                 nor[2]= 0.0;
00461 
00462                 if(fabs(x2)+fabs(y2)<0.0001)
00463                         nor[0]= 1.0;
00464 
00465                 co= z2;
00466         }
00467         co/= len1;
00468 
00469         normalize_v3(nor);
00470         
00471         angle= 0.5f*saacos(co);
00472         si= (float)sin(angle);
00473         q[0]= (float)cos(angle);
00474         q[1]= nor[0]*si;
00475         q[2]= nor[1]*si;
00476         q[3]= nor[2]*si;
00477         
00478         if(axis!=upflag) {
00479                 quat_to_mat3(mat,q);
00480 
00481                 fp= mat[2];
00482                 if(axis==0) {
00483                         if(upflag==1) angle= (float)(0.5*atan2(fp[2], fp[1]));
00484                         else angle= (float)(-0.5*atan2(fp[1], fp[2]));
00485                 }
00486                 else if(axis==1) {
00487                         if(upflag==0) angle= (float)(-0.5*atan2(fp[2], fp[0]));
00488                         else angle= (float)(0.5*atan2(fp[0], fp[2]));
00489                 }
00490                 else {
00491                         if(upflag==0) angle= (float)(0.5*atan2(-fp[1], -fp[0]));
00492                         else angle= (float)(-0.5*atan2(-fp[0], -fp[1]));
00493                 }
00494                                 
00495                 co= (float)cos(angle);
00496                 si= (float)(sin(angle)/len1);
00497                 q2[0]= co;
00498                 q2[1]= x2*si;
00499                 q2[2]= y2*si;
00500                 q2[3]= z2*si;
00501                         
00502                 mul_qt_qtqt(q,q2,q);
00503         }
00504 }
00505 
00506 #if 0
00507 /* A & M Watt, Advanced animation and rendering techniques, 1992 ACM press */
00508 void QuatInterpolW(float *result, float *quat1, float *quat2, float t)
00509 {
00510         float omega, cosom, sinom, sc1, sc2;
00511 
00512         cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ;
00513         
00514         /* rotate around shortest angle */
00515         if ((1.0f + cosom) > 0.0001f) {
00516                 
00517                 if ((1.0f - cosom) > 0.0001f) {
00518                         omega = (float)acos(cosom);
00519                         sinom = (float)sin(omega);
00520                         sc1 = (float)sin((1.0 - t) * omega) / sinom;
00521                         sc2 = (float)sin(t * omega) / sinom;
00522                 } 
00523                 else {
00524                         sc1 = 1.0f - t;
00525                         sc2 = t;
00526                 }
00527                 result[0] = sc1*quat1[0] + sc2*quat2[0];
00528                 result[1] = sc1*quat1[1] + sc2*quat2[1];
00529                 result[2] = sc1*quat1[2] + sc2*quat2[2];
00530                 result[3] = sc1*quat1[3] + sc2*quat2[3];
00531         } 
00532         else {
00533                 result[0] = quat2[3];
00534                 result[1] = -quat2[2];
00535                 result[2] = quat2[1];
00536                 result[3] = -quat2[0];
00537                 
00538                 sc1 = (float)sin((1.0 - t)*M_PI_2);
00539                 sc2 = (float)sin(t*M_PI_2);
00540                 
00541                 result[0] = sc1*quat1[0] + sc2*result[0];
00542                 result[1] = sc1*quat1[1] + sc2*result[1];
00543                 result[2] = sc1*quat1[2] + sc2*result[2];
00544                 result[3] = sc1*quat1[3] + sc2*result[3];
00545         }
00546 }
00547 #endif
00548 
00549 void interp_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], const float t)
00550 {
00551         float quat[4], omega, cosom, sinom, sc1, sc2;
00552 
00553         cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ;
00554         
00555         /* rotate around shortest angle */
00556         if (cosom < 0.0f) {
00557                 cosom = -cosom;
00558                 quat[0]= -quat1[0];
00559                 quat[1]= -quat1[1];
00560                 quat[2]= -quat1[2];
00561                 quat[3]= -quat1[3];
00562         } 
00563         else {
00564                 quat[0]= quat1[0];
00565                 quat[1]= quat1[1];
00566                 quat[2]= quat1[2];
00567                 quat[3]= quat1[3];
00568         }
00569         
00570         if ((1.0f - cosom) > 0.0001f) {
00571                 omega = (float)acos(cosom);
00572                 sinom = (float)sin(omega);
00573                 sc1 = (float)sin((1 - t) * omega) / sinom;
00574                 sc2 = (float)sin(t * omega) / sinom;
00575         } else {
00576                 sc1= 1.0f - t;
00577                 sc2= t;
00578         }
00579         
00580         result[0] = sc1 * quat[0] + sc2 * quat2[0];
00581         result[1] = sc1 * quat[1] + sc2 * quat2[1];
00582         result[2] = sc1 * quat[2] + sc2 * quat2[2];
00583         result[3] = sc1 * quat[3] + sc2 * quat2[3];
00584 }
00585 
00586 void add_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], const float t)
00587 {
00588         result[0]= quat1[0] + t*quat2[0];
00589         result[1]= quat1[1] + t*quat2[1];
00590         result[2]= quat1[2] + t*quat2[2];
00591         result[3]= quat1[3] + t*quat2[3];
00592 }
00593 
00594 void tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3])
00595 {
00596         /* imaginary x-axis, y-axis triangle is being rotated */
00597         float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3];
00598         
00599         /* move z-axis to face-normal */
00600         normal_tri_v3(vec,v1, v2, v3);
00601 
00602         n[0]= vec[1];
00603         n[1]= -vec[0];
00604         n[2]= 0.0f;
00605         normalize_v3(n);
00606         
00607         if(n[0]==0.0f && n[1]==0.0f) n[0]= 1.0f;
00608         
00609         angle= -0.5f*(float)saacos(vec[2]);
00610         co= (float)cos(angle);
00611         si= (float)sin(angle);
00612         q1[0]= co;
00613         q1[1]= n[0]*si;
00614         q1[2]= n[1]*si;
00615         q1[3]= 0.0f;
00616         
00617         /* rotate back line v1-v2 */
00618         quat_to_mat3(mat,q1);
00619         invert_m3_m3(imat, mat);
00620         sub_v3_v3v3(vec, v2, v1);
00621         mul_m3_v3(imat, vec);
00622 
00623         /* what angle has this line with x-axis? */
00624         vec[2]= 0.0f;
00625         normalize_v3(vec);
00626 
00627         angle= (float)(0.5*atan2(vec[1], vec[0]));
00628         co= (float)cos(angle);
00629         si= (float)sin(angle);
00630         q2[0]= co;
00631         q2[1]= 0.0f;
00632         q2[2]= 0.0f;
00633         q2[3]= si;
00634 
00635         mul_qt_qtqt(quat, q1, q2);
00636 }
00637 
00638 void print_qt(const char *str,  const float q[4])
00639 {
00640         printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]);
00641 }
00642 
00643 /******************************** Axis Angle *********************************/
00644 
00645 /* Axis angle to Quaternions */
00646 void axis_angle_to_quat(float q[4], const float axis[3], float angle)
00647 {
00648         float nor[3];
00649         float si;
00650 
00651         if(normalize_v3_v3(nor, axis) == 0.0f) {
00652                 unit_qt(q);
00653                 return;
00654         }
00655 
00656         angle /= 2;
00657         si = (float)sin(angle);
00658         q[0] = (float)cos(angle);
00659         q[1] = nor[0] * si;
00660         q[2] = nor[1] * si;
00661         q[3] = nor[2] * si;     
00662 }
00663 
00664 /* Quaternions to Axis Angle */
00665 void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
00666 {
00667         float ha, si;
00668 
00669 #ifdef DEBUG
00670         if(!((ha=dot_qtqt(q, q))==0.0f || (fabsf(ha-1.0f) < (float)QUAT_EPSILON))) {
00671                 fprintf(stderr, "Warning! quat_to_axis_angle() called with non-normalized: size %.8f *** report a bug ***\n", ha);
00672         }
00673 #endif
00674 
00675         /* calculate angle/2, and sin(angle/2) */
00676         ha= (float)acos(q[0]);
00677         si= (float)sin(ha);
00678         
00679         /* from half-angle to angle */
00680         *angle= ha * 2;
00681         
00682         /* prevent division by zero for axis conversion */
00683         if (fabs(si) < 0.0005)
00684                 si= 1.0f;
00685         
00686         axis[0]= q[1] / si;
00687         axis[1]= q[2] / si;
00688         axis[2]= q[3] / si;
00689 }
00690 
00691 /* Axis Angle to Euler Rotation */
00692 void axis_angle_to_eulO(float eul[3], const short order, const float axis[3], const float angle)
00693 {
00694         float q[4];
00695         
00696         /* use quaternions as intermediate representation for now... */
00697         axis_angle_to_quat(q, axis, angle);
00698         quat_to_eulO(eul, order,q);
00699 }
00700 
00701 /* Euler Rotation to Axis Angle */
00702 void eulO_to_axis_angle(float axis[3], float *angle, const float eul[3], const short order)
00703 {
00704         float q[4];
00705         
00706         /* use quaternions as intermediate representation for now... */
00707         eulO_to_quat(q,eul, order);
00708         quat_to_axis_angle(axis, angle,q);
00709 }
00710 
00711 /* axis angle to 3x3 matrix - safer version (normalisation of axis performed) */
00712 void axis_angle_to_mat3(float mat[3][3], const float axis[3], const float angle)
00713 {
00714         float nor[3], nsi[3], co, si, ico;
00715         
00716         /* normalise the axis first (to remove unwanted scaling) */
00717         if(normalize_v3_v3(nor, axis) == 0.0f) {
00718                 unit_m3(mat);
00719                 return;
00720         }
00721         
00722         /* now convert this to a 3x3 matrix */
00723         co= (float)cos(angle);          
00724         si= (float)sin(angle);
00725         
00726         ico= (1.0f - co);
00727         nsi[0]= nor[0]*si;
00728         nsi[1]= nor[1]*si;
00729         nsi[2]= nor[2]*si;
00730         
00731         mat[0][0] = ((nor[0] * nor[0]) * ico) + co;
00732         mat[0][1] = ((nor[0] * nor[1]) * ico) + nsi[2];
00733         mat[0][2] = ((nor[0] * nor[2]) * ico) - nsi[1];
00734         mat[1][0] = ((nor[0] * nor[1]) * ico) - nsi[2];
00735         mat[1][1] = ((nor[1] * nor[1]) * ico) + co;
00736         mat[1][2] = ((nor[1] * nor[2]) * ico) + nsi[0];
00737         mat[2][0] = ((nor[0] * nor[2]) * ico) + nsi[1];
00738         mat[2][1] = ((nor[1] * nor[2]) * ico) - nsi[0];
00739         mat[2][2] = ((nor[2] * nor[2]) * ico) + co;
00740 }
00741 
00742 /* axis angle to 4x4 matrix - safer version (normalisation of axis performed) */
00743 void axis_angle_to_mat4(float mat[4][4], const float axis[3], const float angle)
00744 {
00745         float tmat[3][3];
00746         
00747         axis_angle_to_mat3(tmat,axis, angle);
00748         unit_m4(mat);
00749         copy_m4_m3(mat, tmat);
00750 }
00751 
00752 /* 3x3 matrix to axis angle (see Mat4ToVecRot too) */
00753 void mat3_to_axis_angle(float axis[3], float *angle,float mat[3][3])
00754 {
00755         float q[4];
00756         
00757         /* use quaternions as intermediate representation */
00758         // TODO: it would be nicer to go straight there...
00759         mat3_to_quat(q,mat);
00760         quat_to_axis_angle(axis, angle,q);
00761 }
00762 
00763 /* 4x4 matrix to axis angle (see Mat4ToVecRot too) */
00764 void mat4_to_axis_angle(float axis[3], float *angle,float mat[4][4])
00765 {
00766         float q[4];
00767         
00768         /* use quaternions as intermediate representation */
00769         // TODO: it would be nicer to go straight there...
00770         mat4_to_quat(q,mat);
00771         quat_to_axis_angle(axis, angle,q);
00772 }
00773 
00774 /****************************** Vector/Rotation ******************************/
00775 /* TODO: the following calls should probably be depreceated sometime         */
00776 
00777 /* 3x3 matrix to axis angle */
00778 void mat3_to_vec_rot(float axis[3], float *angle,float mat[3][3])
00779 {
00780         float q[4];
00781         
00782         /* use quaternions as intermediate representation */
00783         // TODO: it would be nicer to go straight there...
00784         mat3_to_quat(q,mat);
00785         quat_to_axis_angle(axis, angle,q);
00786 }
00787 
00788 /* 4x4 matrix to axis angle */
00789 void mat4_to_vec_rot(float axis[3], float *angle,float mat[4][4])
00790 {
00791         float q[4];
00792         
00793         /* use quaternions as intermediate representation */
00794         // TODO: it would be nicer to go straight there...
00795         mat4_to_quat(q,mat);
00796         quat_to_axis_angle(axis, angle,q);
00797 }
00798 
00799 /* axis angle to 3x3 matrix */
00800 void vec_rot_to_mat3(float mat[][3], const float vec[3], const float phi)
00801 {
00802         /* rotation of phi radials around vec */
00803         float vx, vx2, vy, vy2, vz, vz2, co, si;
00804         
00805         vx= vec[0];
00806         vy= vec[1];
00807         vz= vec[2];
00808         vx2= vx*vx;
00809         vy2= vy*vy;
00810         vz2= vz*vz;
00811         co= (float)cos(phi);
00812         si= (float)sin(phi);
00813         
00814         mat[0][0]= vx2+co*(1.0f-vx2);
00815         mat[0][1]= vx*vy*(1.0f-co)+vz*si;
00816         mat[0][2]= vz*vx*(1.0f-co)-vy*si;
00817         mat[1][0]= vx*vy*(1.0f-co)-vz*si;
00818         mat[1][1]= vy2+co*(1.0f-vy2);
00819         mat[1][2]= vy*vz*(1.0f-co)+vx*si;
00820         mat[2][0]= vz*vx*(1.0f-co)+vy*si;
00821         mat[2][1]= vy*vz*(1.0f-co)-vx*si;
00822         mat[2][2]= vz2+co*(1.0f-vz2);
00823 }
00824 
00825 /* axis angle to 4x4 matrix */
00826 void vec_rot_to_mat4(float mat[][4], const float vec[3], const float phi)
00827 {
00828         float tmat[3][3];
00829         
00830         vec_rot_to_mat3(tmat,vec, phi);
00831         unit_m4(mat);
00832         copy_m4_m3(mat, tmat);
00833 }
00834 
00835 /* axis angle to quaternion */
00836 void vec_rot_to_quat(float *quat, const float vec[3], const float phi)
00837 {
00838         /* rotation of phi radials around vec */
00839         float si;
00840 
00841         quat[1]= vec[0];
00842         quat[2]= vec[1];
00843         quat[3]= vec[2];
00844         
00845         if(normalize_v3(quat+1) == 0.0f) {
00846                 unit_qt(quat);
00847         }
00848         else {
00849                 quat[0]= (float)cos((double)phi/2.0);
00850                 si= (float)sin((double)phi/2.0);
00851                 quat[1] *= si;
00852                 quat[2] *= si;
00853                 quat[3] *= si;
00854         }
00855 }
00856 
00857 /******************************** XYZ Eulers *********************************/
00858 
00859 /* XYZ order */
00860 void eul_to_mat3(float mat[][3], const float eul[3])
00861 {
00862         double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
00863         
00864         ci = cos(eul[0]); 
00865         cj = cos(eul[1]); 
00866         ch = cos(eul[2]);
00867         si = sin(eul[0]); 
00868         sj = sin(eul[1]); 
00869         sh = sin(eul[2]);
00870         cc = ci*ch; 
00871         cs = ci*sh; 
00872         sc = si*ch; 
00873         ss = si*sh;
00874 
00875         mat[0][0] = (float)(cj*ch); 
00876         mat[1][0] = (float)(sj*sc-cs); 
00877         mat[2][0] = (float)(sj*cc+ss);
00878         mat[0][1] = (float)(cj*sh); 
00879         mat[1][1] = (float)(sj*ss+cc); 
00880         mat[2][1] = (float)(sj*cs-sc);
00881         mat[0][2] = (float)-sj;  
00882         mat[1][2] = (float)(cj*si);    
00883         mat[2][2] = (float)(cj*ci);
00884 
00885 }
00886 
00887 /* XYZ order */
00888 void eul_to_mat4(float mat[][4], const float eul[3])
00889 {
00890         double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
00891         
00892         ci = cos(eul[0]); 
00893         cj = cos(eul[1]); 
00894         ch = cos(eul[2]);
00895         si = sin(eul[0]); 
00896         sj = sin(eul[1]); 
00897         sh = sin(eul[2]);
00898         cc = ci*ch; 
00899         cs = ci*sh; 
00900         sc = si*ch; 
00901         ss = si*sh;
00902 
00903         mat[0][0] = (float)(cj*ch); 
00904         mat[1][0] = (float)(sj*sc-cs); 
00905         mat[2][0] = (float)(sj*cc+ss);
00906         mat[0][1] = (float)(cj*sh); 
00907         mat[1][1] = (float)(sj*ss+cc); 
00908         mat[2][1] = (float)(sj*cs-sc);
00909         mat[0][2] = (float)-sj;  
00910         mat[1][2] = (float)(cj*si);    
00911         mat[2][2] = (float)(cj*ci);
00912 
00913 
00914         mat[3][0]= mat[3][1]= mat[3][2]= mat[0][3]= mat[1][3]= mat[2][3]= 0.0f;
00915         mat[3][3]= 1.0f;
00916 }
00917 
00918 /* returns two euler calculation methods, so we can pick the best */
00919 /* XYZ order */
00920 static void mat3_to_eul2(float tmat[][3], float eul1[3], float eul2[3])
00921 {
00922         float cy, quat[4], mat[3][3];
00923         
00924         mat3_to_quat(quat,tmat);
00925         quat_to_mat3(mat,quat);
00926         copy_m3_m3(mat, tmat);
00927         normalize_m3(mat);
00928         
00929         cy = (float)sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]);
00930         
00931         if (cy > 16.0f*FLT_EPSILON) {
00932                 
00933                 eul1[0] = (float)atan2(mat[1][2], mat[2][2]);
00934                 eul1[1] = (float)atan2(-mat[0][2], cy);
00935                 eul1[2] = (float)atan2(mat[0][1], mat[0][0]);
00936                 
00937                 eul2[0] = (float)atan2(-mat[1][2], -mat[2][2]);
00938                 eul2[1] = (float)atan2(-mat[0][2], -cy);
00939                 eul2[2] = (float)atan2(-mat[0][1], -mat[0][0]);
00940                 
00941         } else {
00942                 eul1[0] = (float)atan2(-mat[2][1], mat[1][1]);
00943                 eul1[1] = (float)atan2(-mat[0][2], cy);
00944                 eul1[2] = 0.0f;
00945                 
00946                 copy_v3_v3(eul2, eul1);
00947         }
00948 }
00949 
00950 /* XYZ order */
00951 void mat3_to_eul(float *eul,float tmat[][3])
00952 {
00953         float eul1[3], eul2[3];
00954         
00955         mat3_to_eul2(tmat, eul1, eul2);
00956                 
00957         /* return best, which is just the one with lowest values it in */
00958         if(fabs(eul1[0])+fabs(eul1[1])+fabs(eul1[2]) > fabs(eul2[0])+fabs(eul2[1])+fabs(eul2[2])) {
00959                 copy_v3_v3(eul, eul2);
00960         }
00961         else {
00962                 copy_v3_v3(eul, eul1);
00963         }
00964 }
00965 
00966 /* XYZ order */
00967 void mat4_to_eul(float *eul,float tmat[][4])
00968 {
00969         float tempMat[3][3];
00970 
00971         copy_m3_m4(tempMat, tmat);
00972         normalize_m3(tempMat);
00973         mat3_to_eul(eul,tempMat);
00974 }
00975 
00976 /* XYZ order */
00977 void quat_to_eul(float *eul, const float quat[4])
00978 {
00979         float mat[3][3];
00980 
00981         quat_to_mat3(mat,quat);
00982         mat3_to_eul(eul,mat);
00983 }
00984 
00985 /* XYZ order */
00986 void eul_to_quat(float *quat, const float eul[3])
00987 {
00988         float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
00989  
00990         ti = eul[0]*0.5f; tj = eul[1]*0.5f; th = eul[2]*0.5f;
00991         ci = (float)cos(ti);  cj = (float)cos(tj);  ch = (float)cos(th);
00992         si = (float)sin(ti);  sj = (float)sin(tj);  sh = (float)sin(th);
00993         cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
00994         
00995         quat[0] = cj*cc + sj*ss;
00996         quat[1] = cj*sc - sj*cs;
00997         quat[2] = cj*ss + sj*cc;
00998         quat[3] = cj*cs - sj*sc;
00999 }
01000 
01001 /* XYZ order */
01002 void rotate_eul(float *beul, const char axis, const float ang)
01003 {
01004         float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
01005 
01006         assert(axis >= 'X' && axis <= 'Z');
01007 
01008         eul[0]= eul[1]= eul[2]= 0.0f;
01009         if(axis=='X') eul[0]= ang;
01010         else if(axis=='Y') eul[1]= ang;
01011         else eul[2]= ang;
01012         
01013         eul_to_mat3(mat1,eul);
01014         eul_to_mat3(mat2,beul);
01015         
01016         mul_m3_m3m3(totmat, mat2, mat1);
01017         
01018         mat3_to_eul(beul,totmat);
01019         
01020 }
01021 
01022 /* exported to transform.c */
01023 /* order independent! */
01024 void compatible_eul(float eul[3], const float oldrot[3])
01025 {
01026         float dx, dy, dz;
01027         
01028         /* correct differences of about 360 degrees first */
01029         dx= eul[0] - oldrot[0];
01030         dy= eul[1] - oldrot[1];
01031         dz= eul[2] - oldrot[2];
01032         
01033         while(fabs(dx) > 5.1) {
01034                 if(dx > 0.0f) eul[0] -= 2.0f*(float)M_PI; else eul[0]+= 2.0f*(float)M_PI;
01035                 dx= eul[0] - oldrot[0];
01036         }
01037         while(fabs(dy) > 5.1) {
01038                 if(dy > 0.0f) eul[1] -= 2.0f*(float)M_PI; else eul[1]+= 2.0f*(float)M_PI;
01039                 dy= eul[1] - oldrot[1];
01040         }
01041         while(fabs(dz) > 5.1) {
01042                 if(dz > 0.0f) eul[2] -= 2.0f*(float)M_PI; else eul[2]+= 2.0f*(float)M_PI;
01043                 dz= eul[2] - oldrot[2];
01044         }
01045         
01046         /* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */      
01047         if(fabs(dx) > 3.2 && fabs(dy)<1.6 && fabs(dz)<1.6) {
01048                 if(dx > 0.0f) eul[0] -= 2.0f*(float)M_PI; else eul[0]+= 2.0f*(float)M_PI;
01049         }
01050         if(fabs(dy) > 3.2 && fabs(dz)<1.6 && fabs(dx)<1.6) {
01051                 if(dy > 0.0f) eul[1] -= 2.0f*(float)M_PI; else eul[1]+= 2.0f*(float)M_PI;
01052         }
01053         if(fabs(dz) > 3.2 && fabs(dx)<1.6 && fabs(dy)<1.6) {
01054                 if(dz > 0.0f) eul[2] -= 2.0f*(float)M_PI; else eul[2]+= 2.0f*(float)M_PI;
01055         }
01056         
01057         /* the method below was there from ancient days... but why! probably because the code sucks :)
01058                 */
01059 #if 0   
01060         /* calc again */
01061         dx= eul[0] - oldrot[0];
01062         dy= eul[1] - oldrot[1];
01063         dz= eul[2] - oldrot[2];
01064         
01065         /* special case, tested for x-z  */
01066         
01067         if((fabs(dx) > 3.1 && fabs(dz) > 1.5) || (fabs(dx) > 1.5 && fabs(dz) > 3.1)) {
01068                 if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
01069                 if(eul[1] > 0.0) eul[1]= M_PI - eul[1]; else eul[1]= -M_PI - eul[1];
01070                 if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
01071                 
01072         }
01073         else if((fabs(dx) > 3.1 && fabs(dy) > 1.5) || (fabs(dx) > 1.5 && fabs(dy) > 3.1)) {
01074                 if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
01075                 if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
01076                 if(eul[2] > 0.0) eul[2]= M_PI - eul[2]; else eul[2]= -M_PI - eul[2];
01077         }
01078         else if((fabs(dy) > 3.1 && fabs(dz) > 1.5) || (fabs(dy) > 1.5 && fabs(dz) > 3.1)) {
01079                 if(eul[0] > 0.0) eul[0]= M_PI - eul[0]; else eul[0]= -M_PI - eul[0];
01080                 if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
01081                 if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
01082         }
01083 #endif  
01084 }
01085 
01086 /* uses 2 methods to retrieve eulers, and picks the closest */
01087 /* XYZ order */
01088 void mat3_to_compatible_eul(float eul[3], const float oldrot[3], float mat[][3])
01089 {
01090         float eul1[3], eul2[3];
01091         float d1, d2;
01092         
01093         mat3_to_eul2(mat, eul1, eul2);
01094         
01095         compatible_eul(eul1, oldrot);
01096         compatible_eul(eul2, oldrot);
01097         
01098         d1= (float)fabs(eul1[0]-oldrot[0]) + (float)fabs(eul1[1]-oldrot[1]) + (float)fabs(eul1[2]-oldrot[2]);
01099         d2= (float)fabs(eul2[0]-oldrot[0]) + (float)fabs(eul2[1]-oldrot[1]) + (float)fabs(eul2[2]-oldrot[2]);
01100         
01101         /* return best, which is just the one with lowest difference */
01102         if(d1 > d2) {
01103                 copy_v3_v3(eul, eul2);
01104         }
01105         else {
01106                 copy_v3_v3(eul, eul1);
01107         }
01108         
01109 }
01110 
01111 /************************** Arbitrary Order Eulers ***************************/
01112 
01113 /* Euler Rotation Order Code:
01114  * was adapted from  
01115                   ANSI C code from the article
01116                 "Euler Angle Conversion"
01117                 by Ken Shoemake, shoemake@graphics.cis.upenn.edu
01118                 in "Graphics Gems IV", Academic Press, 1994
01119  * for use in Blender
01120  */
01121 
01122 /* Type for rotation order info - see wiki for derivation details */
01123 typedef struct RotOrderInfo {
01124         short axis[3];
01125         short parity;   /* parity of axis permutation (even=0, odd=1) - 'n' in original code */
01126 } RotOrderInfo;
01127 
01128 /* Array of info for Rotation Order calculations 
01129  * WARNING: must be kept in same order as eEulerRotationOrders
01130  */
01131 static RotOrderInfo rotOrders[]= {
01132         /* i, j, k, n */
01133         {{0, 1, 2}, 0}, // XYZ
01134         {{0, 2, 1}, 1}, // XZY
01135         {{1, 0, 2}, 1}, // YXZ
01136         {{1, 2, 0}, 0}, // YZX
01137         {{2, 0, 1}, 0}, // ZXY
01138         {{2, 1, 0}, 1}  // ZYX
01139 };
01140 
01141 /* Get relevant pointer to rotation order set from the array 
01142  * NOTE: since we start at 1 for the values, but arrays index from 0, 
01143  *               there is -1 factor involved in this process...
01144  */
01145 #define GET_ROTATIONORDER_INFO(order) (assert(order>=0 && order<=6), (order < 1) ? &rotOrders[0] : &rotOrders[(order)-1])
01146 
01147 /* Construct quaternion from Euler angles (in radians). */
01148 void eulO_to_quat(float q[4], const float e[3], const short order)
01149 {
01150         RotOrderInfo *R= GET_ROTATIONORDER_INFO(order); 
01151         short i=R->axis[0],  j=R->axis[1],      k=R->axis[2];
01152         double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
01153         double a[3];
01154         
01155         ti = e[i] * 0.5f;
01156         tj = e[j] * (R->parity ? -0.5f : 0.5f);
01157         th = e[k] * 0.5f;
01158 
01159         ci = cos(ti);  cj = cos(tj);  ch = cos(th);
01160         si = sin(ti);  sj = sin(tj);  sh = sin(th);
01161         
01162         cc = ci*ch; cs = ci*sh; 
01163         sc = si*ch; ss = si*sh;
01164         
01165         a[i] = cj*sc - sj*cs;
01166         a[j] = cj*ss + sj*cc;
01167         a[k] = cj*cs - sj*sc;
01168         
01169         q[0] = cj*cc + sj*ss;
01170         q[1] = a[0];
01171         q[2] = a[1];
01172         q[3] = a[2];
01173         
01174         if (R->parity) q[j+1] = -q[j+1];
01175 }
01176 
01177 /* Convert quaternion to Euler angles (in radians). */
01178 void quat_to_eulO(float e[3], short const order, const float q[4])
01179 {
01180         float M[3][3];
01181         
01182         quat_to_mat3(M,q);
01183         mat3_to_eulO(e, order,M);
01184 }
01185 
01186 /* Construct 3x3 matrix from Euler angles (in radians). */
01187 void eulO_to_mat3(float M[3][3], const float e[3], const short order)
01188 {
01189         RotOrderInfo *R= GET_ROTATIONORDER_INFO(order); 
01190         short i=R->axis[0],  j=R->axis[1],      k=R->axis[2];
01191         double ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
01192         
01193         if (R->parity) {
01194                 ti = -e[i];       tj = -e[j];   th = -e[k];
01195         }
01196         else {
01197                 ti = e[i];        tj = e[j];    th = e[k];
01198         }
01199         
01200         ci = cos(ti); cj = cos(tj); ch = cos(th);
01201         si = sin(ti); sj = sin(tj); sh = sin(th);
01202         
01203         cc = ci*ch; cs = ci*sh; 
01204         sc = si*ch; ss = si*sh;
01205         
01206         M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
01207         M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
01208         M[i][k] = -sj;   M[j][k] = cj*si;        M[k][k] = cj*ci;
01209 }
01210 
01211 /* returns two euler calculation methods, so we can pick the best */
01212 static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, short order)
01213 {
01214         RotOrderInfo *R= GET_ROTATIONORDER_INFO(order); 
01215         short i=R->axis[0],  j=R->axis[1],      k=R->axis[2];
01216         float m[3][3];
01217         double cy;
01218         
01219         /* process the matrix first */
01220         copy_m3_m3(m, M);
01221         normalize_m3(m);
01222         
01223         cy= sqrt(m[i][i]*m[i][i] + m[i][j]*m[i][j]);
01224         
01225         if (cy > 16.0*(double)FLT_EPSILON) {
01226                 e1[i] = atan2(m[j][k], m[k][k]);
01227                 e1[j] = atan2(-m[i][k], cy);
01228                 e1[k] = atan2(m[i][j], m[i][i]);
01229                 
01230                 e2[i] = atan2(-m[j][k], -m[k][k]);
01231                 e2[j] = atan2(-m[i][k], -cy);
01232                 e2[k] = atan2(-m[i][j], -m[i][i]);
01233         } 
01234         else {
01235                 e1[i] = atan2(-m[k][j], m[j][j]);
01236                 e1[j] = atan2(-m[i][k], cy);
01237                 e1[k] = 0;
01238                 
01239                 copy_v3_v3(e2, e1);
01240         }
01241         
01242         if (R->parity) {
01243                 e1[0] = -e1[0]; 
01244                 e1[1] = -e1[1]; 
01245                 e1[2] = -e1[2];
01246                 
01247                 e2[0] = -e2[0]; 
01248                 e2[1] = -e2[1]; 
01249                 e2[2] = -e2[2];
01250         }
01251 }
01252 
01253 /* Construct 4x4 matrix from Euler angles (in radians). */
01254 void eulO_to_mat4(float M[4][4], const float e[3], const short order)
01255 {
01256         float m[3][3];
01257         
01258         /* for now, we'll just do this the slow way (i.e. copying matrices) */
01259         normalize_m3(m);
01260         eulO_to_mat3(m,e, order);
01261         copy_m4_m3(M, m);
01262 }
01263 
01264 
01265 /* Convert 3x3 matrix to Euler angles (in radians). */
01266 void mat3_to_eulO(float eul[3], const short order,float M[3][3])
01267 {
01268         float eul1[3], eul2[3];
01269         
01270         mat3_to_eulo2(M, eul1, eul2, order);
01271                 
01272         /* return best, which is just the one with lowest values it in */
01273         if(fabs(eul1[0])+fabs(eul1[1])+fabs(eul1[2]) > fabs(eul2[0])+fabs(eul2[1])+fabs(eul2[2])) {
01274                 copy_v3_v3(eul, eul2);
01275         }
01276         else {
01277                 copy_v3_v3(eul, eul1);
01278         }
01279 }
01280 
01281 /* Convert 4x4 matrix to Euler angles (in radians). */
01282 void mat4_to_eulO(float e[3], const short order,float M[4][4])
01283 {
01284         float m[3][3];
01285         
01286         /* for now, we'll just do this the slow way (i.e. copying matrices) */
01287         copy_m3_m4(m, M);
01288         normalize_m3(m);
01289         mat3_to_eulO(e, order,m);
01290 }
01291 
01292 /* uses 2 methods to retrieve eulers, and picks the closest */
01293 void mat3_to_compatible_eulO(float eul[3], float oldrot[3], short order,float mat[3][3])
01294 {
01295         float eul1[3], eul2[3];
01296         float d1, d2;
01297         
01298         mat3_to_eulo2(mat, eul1, eul2, order);
01299         
01300         compatible_eul(eul1, oldrot);
01301         compatible_eul(eul2, oldrot);
01302         
01303         d1= (float)fabs(eul1[0]-oldrot[0]) + (float)fabs(eul1[1]-oldrot[1]) + (float)fabs(eul1[2]-oldrot[2]);
01304         d2= (float)fabs(eul2[0]-oldrot[0]) + (float)fabs(eul2[1]-oldrot[1]) + (float)fabs(eul2[2]-oldrot[2]);
01305         
01306         /* return best, which is just the one with lowest difference */
01307         if (d1 > d2)
01308                 copy_v3_v3(eul, eul2);
01309         else
01310                 copy_v3_v3(eul, eul1);
01311 }
01312 
01313 void mat4_to_compatible_eulO(float eul[3], float oldrot[3], short order,float M[4][4])
01314 {
01315         float m[3][3];
01316         
01317         /* for now, we'll just do this the slow way (i.e. copying matrices) */
01318         copy_m3_m4(m, M);
01319         normalize_m3(m);
01320         mat3_to_compatible_eulO(eul, oldrot, order, m);
01321 }
01322 /* rotate the given euler by the given angle on the specified axis */
01323 // NOTE: is this safe to do with different axis orders?
01324 void rotate_eulO(float beul[3], short order, char axis, float ang)
01325 {
01326         float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
01327 
01328         assert(axis >= 'X' && axis <= 'Z');
01329 
01330         eul[0]= eul[1]= eul[2]= 0.0f;
01331         if (axis=='X') 
01332                 eul[0]= ang;
01333         else if (axis=='Y')
01334                 eul[1]= ang;
01335         else 
01336                 eul[2]= ang;
01337         
01338         eulO_to_mat3(mat1,eul, order);
01339         eulO_to_mat3(mat2,beul, order);
01340         
01341         mul_m3_m3m3(totmat, mat2, mat1);
01342         
01343         mat3_to_eulO(beul, order,totmat);
01344 }
01345 
01346 /* the matrix is written to as 3 axis vectors */
01347 void eulO_to_gimbal_axis(float gmat[][3], const float eul[3], const short order)
01348 {
01349         RotOrderInfo *R= GET_ROTATIONORDER_INFO(order);
01350 
01351         float mat[3][3];
01352         float teul[3];
01353 
01354         /* first axis is local */
01355         eulO_to_mat3(mat,eul, order);
01356         copy_v3_v3(gmat[R->axis[0]], mat[R->axis[0]]);
01357         
01358         /* second axis is local minus first rotation */
01359         copy_v3_v3(teul, eul);
01360         teul[R->axis[0]] = 0;
01361         eulO_to_mat3(mat,teul, order);
01362         copy_v3_v3(gmat[R->axis[1]], mat[R->axis[1]]);
01363         
01364         
01365         /* Last axis is global */
01366         gmat[R->axis[2]][0] = 0;
01367         gmat[R->axis[2]][1] = 0;
01368         gmat[R->axis[2]][2] = 0;
01369         gmat[R->axis[2]][R->axis[2]] = 1;
01370 }
01371 
01372 /******************************* Dual Quaternions ****************************/
01373 
01374 /*
01375    Conversion routines between (regular quaternion, translation) and
01376    dual quaternion.
01377 
01378    Version 1.0.0, February 7th, 2007
01379 
01380    Copyright (C) 2006-2007 University of Dublin, Trinity College, All Rights 
01381    Reserved
01382 
01383    This software is provided 'as-is', without any express or implied
01384    warranty.  In no event will the author(s) be held liable for any damages
01385    arising from the use of this software.
01386 
01387    Permission is granted to anyone to use this software for any purpose,
01388    including commercial applications, and to alter it and redistribute it
01389    freely, subject to the following restrictions:
01390 
01391    1. The origin of this software must not be misrepresented; you must not
01392           claim that you wrote the original software. If you use this software
01393           in a product, an acknowledgment in the product documentation would be
01394           appreciated but is not required.
01395    2. Altered source versions must be plainly marked as such, and must not be
01396           misrepresented as being the original software.
01397    3. This notice may not be removed or altered from any source distribution.
01398 
01399    Author: Ladislav Kavan, kavanl@cs.tcd.ie
01400 
01401    Changes for Blender:
01402    - renaming, style changes and optimizations
01403    - added support for scaling
01404 */
01405 
01406 void mat4_to_dquat(DualQuat *dq,float basemat[][4], float mat[][4])
01407 {
01408         float *t, *q, dscale[3], scale[3], basequat[4];
01409         float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4];
01410         float R[4][4], S[4][4];
01411 
01412         /* split scaling and rotation, there is probably a faster way to do
01413            this, it's done like this now to correctly get negative scaling */
01414         mul_m4_m4m4(baseRS, basemat, mat);
01415         mat4_to_size(scale,baseRS);
01416 
01417         copy_v3_v3(dscale, scale);
01418         dscale[0] -= 1.0f; dscale[1] -= 1.0f; dscale[2] -= 1.0f;
01419 
01420         if((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
01421                 /* extract R and S  */
01422                 float tmp[4][4];
01423 
01424                  /* extra orthogonalize, to avoid flipping with stretched bones */
01425                 copy_m4_m4(tmp, baseRS);
01426                 orthogonalize_m4(tmp, 1);
01427                 mat4_to_quat(basequat, tmp);
01428 
01429                 quat_to_mat4(baseR, basequat);
01430                 copy_v3_v3(baseR[3], baseRS[3]);
01431 
01432                 invert_m4_m4(baseinv, basemat);
01433                 mul_m4_m4m4(R, baseinv, baseR);
01434 
01435                 invert_m4_m4(baseRinv, baseR);
01436                 mul_m4_m4m4(S, baseRS, baseRinv);
01437 
01438                 /* set scaling part */
01439                 mul_serie_m4(dq->scale, basemat, S, baseinv, NULL, NULL, NULL, NULL, NULL);
01440                 dq->scale_weight= 1.0f;
01441         }
01442         else {
01443                 /* matrix does not contain scaling */
01444                 copy_m4_m4(R, mat);
01445                 dq->scale_weight= 0.0f;
01446         }
01447 
01448         /* non-dual part */
01449         mat4_to_quat(dq->quat,R);
01450 
01451         /* dual part */
01452         t= R[3];
01453         q= dq->quat;
01454         dq->trans[0]= -0.5f*(t[0]*q[1] + t[1]*q[2] + t[2]*q[3]);
01455         dq->trans[1]=  0.5f*(t[0]*q[0] + t[1]*q[3] - t[2]*q[2]);
01456         dq->trans[2]=  0.5f*(-t[0]*q[3] + t[1]*q[0] + t[2]*q[1]);
01457         dq->trans[3]=  0.5f*(t[0]*q[2] - t[1]*q[1] + t[2]*q[0]);
01458 }
01459 
01460 void dquat_to_mat4(float mat[][4], DualQuat *dq)
01461 {
01462         float len, *t, q0[4];
01463         
01464         /* regular quaternion */
01465         copy_qt_qt(q0, dq->quat);
01466 
01467         /* normalize */
01468         len= (float)sqrt(dot_qtqt(q0, q0)); 
01469         if(len != 0.0f)
01470                 mul_qt_fl(q0, 1.0f/len);
01471         
01472         /* rotation */
01473         quat_to_mat4(mat,q0);
01474 
01475         /* translation */
01476         t= dq->trans;
01477         mat[3][0]= 2.0f*(-t[0]*q0[1] + t[1]*q0[0] - t[2]*q0[3] + t[3]*q0[2]);
01478         mat[3][1]= 2.0f*(-t[0]*q0[2] + t[1]*q0[3] + t[2]*q0[0] - t[3]*q0[1]);
01479         mat[3][2]= 2.0f*(-t[0]*q0[3] - t[1]*q0[2] + t[2]*q0[1] + t[3]*q0[0]);
01480 
01481         /* note: this does not handle scaling */
01482 }       
01483 
01484 void add_weighted_dq_dq(DualQuat *dqsum, DualQuat *dq, float weight)
01485 {
01486         int flipped= 0;
01487 
01488         /* make sure we interpolate quats in the right direction */
01489         if (dot_qtqt(dq->quat, dqsum->quat) < 0) {
01490                 flipped= 1;
01491                 weight= -weight;
01492         }
01493 
01494         /* interpolate rotation and translation */
01495         dqsum->quat[0] += weight*dq->quat[0];
01496         dqsum->quat[1] += weight*dq->quat[1];
01497         dqsum->quat[2] += weight*dq->quat[2];
01498         dqsum->quat[3] += weight*dq->quat[3];
01499 
01500         dqsum->trans[0] += weight*dq->trans[0];
01501         dqsum->trans[1] += weight*dq->trans[1];
01502         dqsum->trans[2] += weight*dq->trans[2];
01503         dqsum->trans[3] += weight*dq->trans[3];
01504 
01505         /* interpolate scale - but only if needed */
01506         if (dq->scale_weight) {
01507                 float wmat[4][4];
01508                 
01509                 if(flipped)     /* we don't want negative weights for scaling */
01510                         weight= -weight;
01511                 
01512                 copy_m4_m4(wmat, dq->scale);
01513                 mul_m4_fl(wmat, weight);
01514                 add_m4_m4m4(dqsum->scale, dqsum->scale, wmat);
01515                 dqsum->scale_weight += weight;
01516         }
01517 }
01518 
01519 void normalize_dq(DualQuat *dq, float totweight)
01520 {
01521         float scale= 1.0f/totweight;
01522 
01523         mul_qt_fl(dq->quat, scale);
01524         mul_qt_fl(dq->trans, scale);
01525         
01526         if(dq->scale_weight) {
01527                 float addweight= totweight - dq->scale_weight;
01528                 
01529                 if(addweight) {
01530                         dq->scale[0][0] += addweight;
01531                         dq->scale[1][1] += addweight;
01532                         dq->scale[2][2] += addweight;
01533                         dq->scale[3][3] += addweight;
01534                 }
01535 
01536                 mul_m4_fl(dq->scale, scale);
01537                 dq->scale_weight= 1.0f;
01538         }
01539 }
01540 
01541 void mul_v3m3_dq(float *co, float mat[][3],DualQuat *dq)
01542 {       
01543         float M[3][3], t[3], scalemat[3][3], len2;
01544         float w= dq->quat[0], x= dq->quat[1], y= dq->quat[2], z= dq->quat[3];
01545         float t0= dq->trans[0], t1= dq->trans[1], t2= dq->trans[2], t3= dq->trans[3];
01546         
01547         /* rotation matrix */
01548         M[0][0]= w*w + x*x - y*y - z*z;
01549         M[1][0]= 2*(x*y - w*z);
01550         M[2][0]= 2*(x*z + w*y);
01551 
01552         M[0][1]= 2*(x*y + w*z);
01553         M[1][1]= w*w + y*y - x*x - z*z;
01554         M[2][1]= 2*(y*z - w*x); 
01555 
01556         M[0][2]= 2*(x*z - w*y);
01557         M[1][2]= 2*(y*z + w*x);
01558         M[2][2]= w*w + z*z - x*x - y*y;
01559         
01560         len2= dot_qtqt(dq->quat, dq->quat);
01561         if(len2 > 0.0f)
01562                 len2= 1.0f/len2;
01563         
01564         /* translation */
01565         t[0]= 2*(-t0*x + w*t1 - t2*z + y*t3);
01566         t[1]= 2*(-t0*y + t1*z - x*t3 + w*t2);
01567         t[2]= 2*(-t0*z + x*t2 + w*t3 - t1*y);
01568 
01569         /* apply scaling */
01570         if(dq->scale_weight)
01571                 mul_m4_v3(dq->scale, co);
01572         
01573         /* apply rotation and translation */
01574         mul_m3_v3(M, co);
01575         co[0]= (co[0] + t[0])*len2;
01576         co[1]= (co[1] + t[1])*len2;
01577         co[2]= (co[2] + t[2])*len2;
01578 
01579         /* compute crazyspace correction mat */
01580         if(mat) {
01581                 if(dq->scale_weight) {
01582                         copy_m3_m4(scalemat, dq->scale);
01583                         mul_m3_m3m3(mat, M, scalemat);
01584                 }
01585                 else
01586                         copy_m3_m3(mat, M);
01587                 mul_m3_fl(mat, len2);
01588         }
01589 }
01590 
01591 void copy_dq_dq(DualQuat *dq1, DualQuat *dq2)
01592 {
01593         memcpy(dq1, dq2, sizeof(DualQuat));
01594 }
01595 
01596 /* axis matches eTrackToAxis_Modes */
01597 void quat_apply_track(float quat[4], short axis, short upflag)
01598 {       
01599         /* rotations are hard coded to match vec_to_quat */
01600         const float quat_track[][4]= {{0.70710676908493, 0.0, -0.70710676908493, 0.0},  /* pos-y90 */ 
01601                                       {0.5, 0.5, 0.5, 0.5},  /* Quaternion((1,0,0), radians(90)) * Quaternion((0,1,0), radians(90)) */ 
01602                                       {0.70710676908493, 0.0, 0.0, 0.70710676908493},  /* pos-z90 */ 
01603                                       {0.70710676908493, 0.0, 0.70710676908493, 0.0}, /* neg-y90 */ 
01604                                       {0.5, -0.5, -0.5, 0.5}, /* Quaternion((1,0,0), radians(-90)) * Quaternion((0,1,0), radians(-90)) */ 
01605                                       {-3.0908619663705394e-08, 0.70710676908493, 0.70710676908493, 3.0908619663705394e-08}}; /* no rotation */
01606 
01607         assert(axis >= 0 && axis <= 5);
01608         assert(upflag >= 0 && upflag <= 2);
01609         
01610         mul_qt_qtqt(quat, quat, quat_track[axis]);
01611 
01612         if(axis>2)
01613                 axis= axis-3;
01614 
01615         /* there are 2 possible up-axis for each axis used, the 'quat_track' applies so the first
01616          * up axis is used X->Y, Y->X, Z->X, if this first up axis isn used then rotate 90d
01617          * the strange bit shift below just find the low axis {X:Y, Y:X, Z:X} */
01618         if(upflag != (2-axis)>>1) {
01619                 float q[4]= {0.70710676908493, 0.0, 0.0, 0.0}; /* assign 90d rotation axis */
01620                 q[axis+1] = ((axis==1)) ? 0.70710676908493 : -0.70710676908493; /* flip non Y axis */
01621                 mul_qt_qtqt(quat, quat, q);
01622         }
01623 }
01624 
01625 
01626 void vec_apply_track(float vec[3], short axis)
01627 {
01628         float tvec[3];
01629 
01630         assert(axis >= 0 && axis <= 5);
01631         
01632         copy_v3_v3(tvec, vec);
01633 
01634         switch(axis) {
01635         case 0: /* pos-x */
01636                 /* vec[0]=  0.0; */
01637                 vec[1]=  tvec[2];
01638                 vec[2]=  -tvec[1];
01639                 break;
01640         case 1: /* pos-y */
01641                 /* vec[0]= tvec[0]; */
01642                 /* vec[1]=  0.0; */
01643                 /* vec[2]= tvec[2]; */ 
01644                 break;
01645         case 2: /* pos-z */
01646                 /* vec[0]= tvec[0]; */
01647                 /* vec[1]= tvec[1]; */
01648                 // vec[2]=  0.0; */
01649                 break;
01650         case 3: /* neg-x */
01651                 /* vec[0]=  0.0; */
01652                 vec[1]=  tvec[2];
01653                 vec[2]= -tvec[1];
01654                 break;
01655         case 4: /* neg-y */
01656                 vec[0]= -tvec[2];
01657                 /* vec[1]=  0.0; */
01658                 vec[2]= tvec[0];
01659                 break;
01660         case 5: /* neg-z */
01661                 vec[0]= -tvec[0];
01662                 vec[1]= -tvec[1];
01663                 /* vec[2]=  0.0; */
01664                 break;
01665         }
01666 }
01667 
01668 /* lens/angle conversion (radians) */
01669 float lens_to_angle(float lens)
01670 {
01671         return 2.0f * atanf(16.0f/lens);
01672 }
01673 
01674 float angle_to_lens(float angle)
01675 {
01676         return 16.0f / tanf(angle * 0.5f);
01677 }
01678 
01679 /* 'mod_inline(-3,4)= 1', 'fmod(-3,4)= -3' */
01680 static float mod_inline(float a, float b)
01681 {
01682         return a - (b * floorf(a / b));
01683 }
01684 
01685 float angle_wrap_rad(float angle)
01686 {
01687         return mod_inline(angle + (float)M_PI, (float)M_PI*2.0f) - (float)M_PI;
01688 }
01689 
01690 float angle_wrap_deg(float angle)
01691 {
01692         return mod_inline(angle + 180.0f, 360.0f) - 180.0f;
01693 }