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