|
Blender
V2.59
|
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 }