00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef matrix_rotation_h
00014 #define matrix_rotation_h
00015
00016 #include <cml/mathlib/matrix_misc.h>
00017 #include <cml/mathlib/vector_ortho.h>
00018
00019
00020
00021 namespace cml {
00022
00024
00026
00028 template < typename E, class A, class B, class L > void
00029 matrix_rotation_world_axis( matrix<E,A,B,L>& m, size_t axis, E angle)
00030 {
00031 typedef matrix<E,A,B,L> matrix_type;
00032 typedef typename matrix_type::value_type value_type;
00033
00034
00035 detail::CheckMatLinear3D(m);
00036 detail::CheckIndex3(axis);
00037
00038 size_t i, j, k;
00039 cyclic_permutation(axis, i, j, k);
00040
00041 value_type s = value_type(std::sin(angle));
00042 value_type c = value_type(std::cos(angle));
00043
00044 identity_transform(m);
00045
00046 m.set_basis_element(j,j, c);
00047 m.set_basis_element(j,k, s);
00048 m.set_basis_element(k,j,-s);
00049 m.set_basis_element(k,k, c);
00050 }
00051
00053 template < typename E, class A, class B, class L > void
00054 matrix_rotation_world_x(matrix<E,A,B,L>& m, E angle) {
00055 matrix_rotation_world_axis(m,0,angle);
00056 }
00057
00059 template < typename E, class A, class B, class L > void
00060 matrix_rotation_world_y(matrix<E,A,B,L>& m, E angle) {
00061 matrix_rotation_world_axis(m,1,angle);
00062 }
00063
00065 template < typename E, class A, class B, class L > void
00066 matrix_rotation_world_z(matrix<E,A,B,L>& m, E angle) {
00067 matrix_rotation_world_axis(m,2,angle);
00068 }
00069
00071
00073
00075 template < typename E, class A, class B, class L, class VecT > void
00076 matrix_rotation_axis_angle(matrix<E,A,B,L>& m, const VecT& axis, E angle)
00077 {
00078 typedef matrix<E,A,B,L> matrix_type;
00079 typedef typename matrix_type::value_type value_type;
00080
00081
00082 detail::CheckMatLinear3D(m);
00083 detail::CheckVec3(axis);
00084
00085 identity_transform(m);
00086
00087 value_type s = std::sin(angle);
00088 value_type c = std::cos(angle);
00089 value_type omc = value_type(1) - c;
00090
00091 value_type xomc = axis[0] * omc;
00092 value_type yomc = axis[1] * omc;
00093 value_type zomc = axis[2] * omc;
00094
00095 value_type xxomc = axis[0] * xomc;
00096 value_type yyomc = axis[1] * yomc;
00097 value_type zzomc = axis[2] * zomc;
00098 value_type xyomc = axis[0] * yomc;
00099 value_type yzomc = axis[1] * zomc;
00100 value_type zxomc = axis[2] * xomc;
00101
00102 value_type xs = axis[0] * s;
00103 value_type ys = axis[1] * s;
00104 value_type zs = axis[2] * s;
00105
00106 m.set_basis_element(0,0, xxomc + c );
00107 m.set_basis_element(0,1, xyomc + zs);
00108 m.set_basis_element(0,2, zxomc - ys);
00109 m.set_basis_element(1,0, xyomc - zs);
00110 m.set_basis_element(1,1, yyomc + c );
00111 m.set_basis_element(1,2, yzomc + xs);
00112 m.set_basis_element(2,0, zxomc + ys);
00113 m.set_basis_element(2,1, yzomc - xs);
00114 m.set_basis_element(2,2, zzomc + c );
00115 }
00116
00118
00120
00122 template < typename E, class A, class B, class L, class QuatT > void
00123 matrix_rotation_quaternion(matrix<E,A,B,L>& m, const QuatT& q)
00124 {
00125 typedef matrix<E,A,B,L> matrix_type;
00126 typedef QuatT quaternion_type;
00127 typedef typename quaternion_type::order_type order_type;
00128 typedef typename matrix_type::value_type value_type;
00129
00130 enum {
00131 W = order_type::W,
00132 X = order_type::X,
00133 Y = order_type::Y,
00134 Z = order_type::Z
00135 };
00136
00137
00138 detail::CheckMatLinear3D(m);
00139 detail::CheckQuat(q);
00140
00141 identity_transform(m);
00142
00143 value_type x2 = q[X] + q[X];
00144 value_type y2 = q[Y] + q[Y];
00145 value_type z2 = q[Z] + q[Z];
00146
00147 value_type xx2 = q[X] * x2;
00148 value_type yy2 = q[Y] * y2;
00149 value_type zz2 = q[Z] * z2;
00150 value_type xy2 = q[X] * y2;
00151 value_type yz2 = q[Y] * z2;
00152 value_type zx2 = q[Z] * x2;
00153 value_type xw2 = q[W] * x2;
00154 value_type yw2 = q[W] * y2;
00155 value_type zw2 = q[W] * z2;
00156
00157 m.set_basis_element(0,0, value_type(1) - yy2 - zz2);
00158 m.set_basis_element(0,1, xy2 + zw2);
00159 m.set_basis_element(0,2, zx2 - yw2);
00160 m.set_basis_element(1,0, xy2 - zw2);
00161 m.set_basis_element(1,1, value_type(1) - zz2 - xx2);
00162 m.set_basis_element(1,2, yz2 + xw2);
00163 m.set_basis_element(2,0, zx2 + yw2);
00164 m.set_basis_element(2,1, yz2 - xw2);
00165 m.set_basis_element(2,2, value_type(1) - xx2 - yy2);
00166 }
00167
00169
00171
00194 template < typename E, class A, class B, class L > void
00195 matrix_rotation_euler(matrix<E,A,B,L>& m, E angle_0, E angle_1, E angle_2,
00196 EulerOrder order)
00197 {
00198 typedef matrix<E,A,B,L> matrix_type;
00199 typedef typename matrix_type::value_type value_type;
00200
00201
00202 detail::CheckMatLinear3D(m);
00203
00204 identity_transform(m);
00205
00206 size_t i, j, k;
00207 bool odd, repeat;
00208 detail::unpack_euler_order(order, i, j, k, odd, repeat);
00209
00210 if (odd) {
00211 angle_0 = -angle_0;
00212 angle_1 = -angle_1;
00213 angle_2 = -angle_2;
00214 }
00215
00216 value_type s0 = std::sin(angle_0);
00217 value_type c0 = std::cos(angle_0);
00218 value_type s1 = std::sin(angle_1);
00219 value_type c1 = std::cos(angle_1);
00220 value_type s2 = std::sin(angle_2);
00221 value_type c2 = std::cos(angle_2);
00222
00223 value_type s0s2 = s0 * s2;
00224 value_type s0c2 = s0 * c2;
00225 value_type c0s2 = c0 * s2;
00226 value_type c0c2 = c0 * c2;
00227
00228 if (repeat) {
00229 m.set_basis_element(i,i, c1 );
00230 m.set_basis_element(i,j, s1 * s2 );
00231 m.set_basis_element(i,k,-s1 * c2 );
00232 m.set_basis_element(j,i, s0 * s1 );
00233 m.set_basis_element(j,j,-c1 * s0s2 + c0c2);
00234 m.set_basis_element(j,k, c1 * s0c2 + c0s2);
00235 m.set_basis_element(k,i, c0 * s1 );
00236 m.set_basis_element(k,j,-c1 * c0s2 - s0c2);
00237 m.set_basis_element(k,k, c1 * c0c2 - s0s2);
00238 } else {
00239 m.set_basis_element(i,i, c1 * c2 );
00240 m.set_basis_element(i,j, c1 * s2 );
00241 m.set_basis_element(i,k,-s1 );
00242 m.set_basis_element(j,i, s1 * s0c2 - c0s2);
00243 m.set_basis_element(j,j, s1 * s0s2 + c0c2);
00244 m.set_basis_element(j,k, s0 * c1 );
00245 m.set_basis_element(k,i, s1 * c0c2 + s0s2);
00246 m.set_basis_element(k,j, s1 * c0s2 - s0c2);
00247 m.set_basis_element(k,k, c0 * c1 );
00248 }
00249 }
00250
00273 template < typename E, class A, class B, class L > void
00274 matrix_rotation_euler_derivatives(
00275 matrix<E,A,B,L>& m, int axis, E angle_0, E angle_1, E angle_2,
00276 EulerOrder order)
00277 {
00278 typedef matrix<E,A,B,L> matrix_type;
00279 typedef typename matrix_type::value_type value_type;
00280
00281
00282 detail::CheckMatLinear3D(m);
00283
00284 identity_transform(m);
00285
00286 size_t i, j, k;
00287 bool odd, repeat;
00288 detail::unpack_euler_order(order, i, j, k, odd, repeat);
00289 if(repeat) throw std::invalid_argument(
00290 "matrix_rotation_euler_derivatives does not support repeated axes");
00291
00292 if (odd) {
00293 angle_0 = -angle_0;
00294 angle_1 = -angle_1;
00295 angle_2 = -angle_2;
00296 }
00297
00298 value_type s0 = std::sin(angle_0);
00299 value_type c0 = std::cos(angle_0);
00300 value_type s1 = std::sin(angle_1);
00301 value_type c1 = std::cos(angle_1);
00302 value_type s2 = std::sin(angle_2);
00303 value_type c2 = std::cos(angle_2);
00304
00305 value_type s0s2 = s0 * s2;
00306 value_type s0c2 = s0 * c2;
00307 value_type c0s2 = c0 * s2;
00308 value_type c0c2 = c0 * c2;
00309
00310 if(axis == 0) {
00311 m.set_basis_element(i,i, 0. );
00312 m.set_basis_element(i,j, 0. );
00313 m.set_basis_element(i,k, 0. );
00314 m.set_basis_element(j,i, s1 * c0*c2 + s0*s2);
00315 m.set_basis_element(j,j, s1 * c0*s2 - s0*c2);
00316 m.set_basis_element(j,k, c0 * c1 );
00317 m.set_basis_element(k,i,-s1 * s0*c2 + c0*s2);
00318 m.set_basis_element(k,j,-s1 * s0*s2 - c0*c2);
00319 m.set_basis_element(k,k,-s0 * c1 );
00320 } else if(axis == 1) {
00321 m.set_basis_element(i,i,-s1 * c2 );
00322 m.set_basis_element(i,j,-s1 * s2 );
00323 m.set_basis_element(i,k,-c1 );
00324 m.set_basis_element(j,i, c1 * s0*c2 );
00325 m.set_basis_element(j,j, c1 * s0*s2 );
00326 m.set_basis_element(j,k,-s0 * s1 );
00327 m.set_basis_element(k,i, c1 * c0*c2 );
00328 m.set_basis_element(k,j, c1 * c0*s2 );
00329 m.set_basis_element(k,k,-c0 * s1 );
00330 } else if(axis == 2) {
00331 m.set_basis_element(i,i,-c1 * s2 );
00332 m.set_basis_element(i,j, c1 * c2 );
00333 m.set_basis_element(i,k, 0. );
00334 m.set_basis_element(j,i,-s1 * s0*s2 - c0*c2);
00335 m.set_basis_element(j,j, s1 * s0*c2 - c0*s2);
00336 m.set_basis_element(j,k, 0. );
00337 m.set_basis_element(k,i,-s1 * c0*s2 + s0*c2);
00338 m.set_basis_element(k,j, s1 * c0*c2 + s0*s2);
00339 m.set_basis_element(k,k, 0. );
00340 }
00341 }
00342
00344
00346
00348 template < typename E,class A,class B,class L,class VecT_1,class VecT_2 > void
00349 matrix_rotation_align(
00350 matrix<E,A,B,L>& m,
00351 const VecT_1& align,
00352 const VecT_2& reference,
00353 bool normalize = true,
00354 AxisOrder order = axis_order_zyx)
00355 {
00356 typedef vector< E,fixed<3> > vector_type;
00357
00358 identity_transform(m);
00359
00360 vector_type x, y, z;
00361
00362 orthonormal_basis(align, reference, x, y, z, normalize, order);
00363 matrix_set_basis_vectors(m, x, y, z);
00364 }
00365
00367 template < typename E, class A, class B, class L, class VecT > void
00368 matrix_rotation_align(matrix<E,A,B,L>& m, const VecT& align,
00369 bool normalize = true, AxisOrder order = axis_order_zyx)
00370 {
00371 typedef vector< E,fixed<3> > vector_type;
00372
00373 identity_transform(m);
00374
00375 vector_type x, y, z;
00376
00377 orthonormal_basis(align, x, y, z, normalize, order);
00378 matrix_set_basis_vectors(m, x, y, z);
00379 }
00380
00382 template < typename E,class A,class B,class L,class VecT_1,class VecT_2 > void
00383 matrix_rotation_align_axial(matrix<E,A,B,L>& m, const VecT_1& align,
00384 const VecT_2& axis, bool normalize = true,
00385 AxisOrder order = axis_order_zyx)
00386 {
00387 typedef vector< E,fixed<3> > vector_type;
00388
00389 identity_transform(m);
00390
00391 vector_type x, y, z;
00392
00393 orthonormal_basis_axial(align, axis, x, y, z, normalize, order);
00394 matrix_set_basis_vectors(m, x, y, z);
00395 }
00396
00398 template < typename E, class A, class B, class L, class MatT > void
00399 matrix_rotation_align_viewplane(
00400 matrix<E,A,B,L>& m,
00401 const MatT& view_matrix,
00402 Handedness handedness,
00403 AxisOrder order = axis_order_zyx)
00404 {
00405 typedef vector< E, fixed<3> > vector_type;
00406
00407 identity_transform(m);
00408
00409 vector_type x, y, z;
00410
00411 orthonormal_basis_viewplane(view_matrix, x, y, z, handedness, order);
00412 matrix_set_basis_vectors(m, x, y, z);
00413 }
00414
00416 template < typename E, class A, class B, class L, class MatT > void
00417 matrix_rotation_align_viewplane_LH(
00418 matrix<E,A,B,L>& m,
00419 const MatT& view_matrix,
00420 AxisOrder order = axis_order_zyx)
00421 {
00422 matrix_rotation_align_viewplane(
00423 m,view_matrix,left_handed,order);
00424 }
00425
00427 template < typename E, class A, class B, class L, class MatT > void
00428 matrix_rotation_align_viewplane_RH(
00429 matrix<E,A,B,L>& m,
00430 const MatT& view_matrix,
00431 AxisOrder order = axis_order_zyx)
00432 {
00433 matrix_rotation_align_viewplane(
00434 m,view_matrix,right_handed,order);
00435 }
00436
00438
00440
00442 template < typename E, class A, class B, class L,
00443 class VecT_1, class VecT_2, class VecT_3 > void
00444 matrix_rotation_aim_at(
00445 matrix<E,A,B,L>& m,
00446 const VecT_1& pos,
00447 const VecT_2& target,
00448 const VecT_3& reference,
00449 AxisOrder order = axis_order_zyx)
00450 {
00451 matrix_rotation_align(m, target - pos, reference, true, order);
00452 }
00453
00455 template < typename E, class A, class B, class L,
00456 class VecT_1, class VecT_2 > void
00457 matrix_rotation_aim_at(
00458 matrix<E,A,B,L>& m,
00459 const VecT_1& pos,
00460 const VecT_2& target,
00461 AxisOrder order = axis_order_zyx)
00462 {
00463 matrix_rotation_align(m, target - pos, true, order);
00464 }
00465
00467 template < typename E, class A, class B, class L,
00468 class VecT_1, class VecT_2, class VecT_3 > void
00469 matrix_rotation_aim_at_axial(
00470 matrix<E,A,B,L>& m,
00471 const VecT_1& pos,
00472 const VecT_2& target,
00473 const VecT_3& axis,
00474 AxisOrder order = axis_order_zyx)
00475 {
00476 matrix_rotation_align_axial(m, target - pos, axis, true, order);
00477 }
00478
00480
00482
00484 template < typename E, class A, class B, class L > void
00485 matrix_rotation_2D( matrix<E,A,B,L>& m, E angle)
00486 {
00487 typedef matrix<E,A,B,L> matrix_type;
00488 typedef typename matrix_type::value_type value_type;
00489
00490
00491 detail::CheckMatLinear2D(m);
00492
00493 value_type s = value_type(std::sin(angle));
00494 value_type c = value_type(std::cos(angle));
00495
00496 identity_transform(m);
00497
00498 m.set_basis_element(0,0, c);
00499 m.set_basis_element(0,1, s);
00500 m.set_basis_element(1,0,-s);
00501 m.set_basis_element(1,1, c);
00502 }
00503
00505
00507
00509 template < typename E, class A, class B, class L, class VecT > void
00510 matrix_rotation_align_2D(matrix<E,A,B,L>& m, const VecT& align,
00511 bool normalize = true, AxisOrder2D order = axis_order_xy)
00512 {
00513 typedef vector< E, fixed<2> > vector_type;
00514
00515 identity_transform(m);
00516
00517 vector_type x, y;
00518
00519 orthonormal_basis_2D(align, x, y, normalize, order);
00520 matrix_set_basis_vectors_2D(m, x, y);
00521 }
00522
00524
00526
00528 template < typename E, class A, class B, class L > void
00529 matrix_rotate_about_world_axis(matrix<E,A,B,L>& m, size_t axis, E angle)
00530 {
00531 typedef matrix<E,A,B,L> matrix_type;
00532 typedef typename matrix_type::value_type value_type;
00533
00534
00535 detail::CheckMatLinear3D(m);
00536 detail::CheckIndex3(axis);
00537
00538 size_t i, j, k;
00539 cyclic_permutation(axis, i, j, k);
00540
00541 value_type s = value_type(std::sin(angle));
00542 value_type c = value_type(std::cos(angle));
00543
00544 value_type ij = c * m.basis_element(i,j) - s * m.basis_element(i,k);
00545 value_type jj = c * m.basis_element(j,j) - s * m.basis_element(j,k);
00546 value_type kj = c * m.basis_element(k,j) - s * m.basis_element(k,k);
00547
00548 m.set_basis_element(i,k, s*m.basis_element(i,j) + c*m.basis_element(i,k));
00549 m.set_basis_element(j,k, s*m.basis_element(j,j) + c*m.basis_element(j,k));
00550 m.set_basis_element(k,k, s*m.basis_element(k,j) + c*m.basis_element(k,k));
00551
00552 m.set_basis_element(i,j,ij);
00553 m.set_basis_element(j,j,jj);
00554 m.set_basis_element(k,j,kj);
00555 }
00556
00558 template < typename E, class A, class B, class L > void
00559 matrix_rotate_about_world_x(matrix<E,A,B,L>& m, E angle) {
00560 matrix_rotate_about_world_axis(m,0,angle);
00561 }
00562
00564 template < typename E, class A, class B, class L > void
00565 matrix_rotate_about_world_y(matrix<E,A,B,L>& m, E angle) {
00566 matrix_rotate_about_world_axis(m,1,angle);
00567 }
00568
00570 template < typename E, class A, class B, class L > void
00571 matrix_rotate_about_world_z(matrix<E,A,B,L>& m, E angle) {
00572 matrix_rotate_about_world_axis(m,2,angle);
00573 }
00574
00576
00578
00580 template < typename E, class A, class B, class L > void
00581 matrix_rotate_about_local_axis(matrix<E,A,B,L>& m, size_t axis, E angle)
00582 {
00583 typedef matrix<E,A,B,L> matrix_type;
00584 typedef typename matrix_type::value_type value_type;
00585
00586
00587 detail::CheckMatLinear3D(m);
00588 detail::CheckIndex3(axis);
00589
00590 size_t i, j, k;
00591 cyclic_permutation(axis, i, j, k);
00592
00593 value_type s = value_type(std::sin(angle));
00594 value_type c = value_type(std::cos(angle));
00595
00596 value_type j0 = c * m.basis_element(j,0) + s * m.basis_element(k,0);
00597 value_type j1 = c * m.basis_element(j,1) + s * m.basis_element(k,1);
00598 value_type j2 = c * m.basis_element(j,2) + s * m.basis_element(k,2);
00599
00600 m.set_basis_element(k,0, c*m.basis_element(k,0) - s*m.basis_element(j,0));
00601 m.set_basis_element(k,1, c*m.basis_element(k,1) - s*m.basis_element(j,1));
00602 m.set_basis_element(k,2, c*m.basis_element(k,2) - s*m.basis_element(j,2));
00603
00604 m.set_basis_element(j,0,j0);
00605 m.set_basis_element(j,1,j1);
00606 m.set_basis_element(j,2,j2);
00607 }
00608
00610 template < typename E, class A, class B, class L > void
00611 matrix_rotate_about_local_x(matrix<E,A,B,L>& m, E angle) {
00612 matrix_rotate_about_local_axis(m,0,angle);
00613 }
00614
00616 template < typename E, class A, class B, class L > void
00617 matrix_rotate_about_local_y(matrix<E,A,B,L>& m, E angle) {
00618 matrix_rotate_about_local_axis(m,1,angle);
00619 }
00620
00622 template < typename E, class A, class B, class L > void
00623 matrix_rotate_about_local_z(matrix<E,A,B,L>& m, E angle) {
00624 matrix_rotate_about_local_axis(m,2,angle);
00625 }
00626
00628
00630
00631 template < typename E, class A, class B, class L > void
00632 matrix_rotate_2D(matrix<E,A,B,L>& m, E angle)
00633 {
00634 typedef matrix<E,A,B,L> matrix_type;
00635 typedef typename matrix_type::value_type value_type;
00636
00637
00638 detail::CheckMatLinear2D(m);
00639
00640 value_type s = value_type(std::sin(angle));
00641 value_type c = value_type(std::cos(angle));
00642
00643 value_type m00 = c * m.basis_element(0,0) - s * m.basis_element(0,1);
00644 value_type m10 = c * m.basis_element(1,0) - s * m.basis_element(1,1);
00645
00646 m.set_basis_element(0,1, s*m.basis_element(0,0) + c*m.basis_element(0,1));
00647 m.set_basis_element(1,1, s*m.basis_element(1,0) + c*m.basis_element(1,1));
00648
00649 m.set_basis_element(0,0,m00);
00650 m.set_basis_element(1,0,m10);
00651 }
00652
00654
00656
00662 template < class E,class A,class B,class L,class VecT_1,class VecT_2 > void
00663 matrix_rotation_vec_to_vec(
00664 matrix<E,A,B,L>& m,
00665 const VecT_1& v1,
00666 const VecT_2& v2,
00667 bool unit_length_vectors = false)
00668 {
00669 typedef quaternion< E,fixed<>,vector_first,positive_cross >
00670 quaternion_type;
00671
00672 quaternion_type q;
00673 quaternion_rotation_vec_to_vec(q,v1,v2,unit_length_vectors);
00674 matrix_rotation_quaternion(m,q);
00675 }
00676
00678
00680
00682 template < typename E, class A, class B, class L > void
00683 matrix_scale_rotation_angle(matrix<E,A,B,L>& m, E t,
00684 E tolerance = epsilon<E>::placeholder())
00685 {
00686 typedef vector< E,fixed<3> > vector_type;
00687 typedef typename vector_type::value_type value_type;
00688
00689 vector_type axis;
00690 value_type angle;
00691 matrix_to_axis_angle(m, axis, angle, tolerance);
00692 matrix_rotation_axis_angle(m, axis, angle * t);
00693 }
00694
00696 template < typename E, class A, class B, class L > void
00697 matrix_scale_rotation_angle_2D(
00698 matrix<E,A,B,L>& m, E t, E tolerance = epsilon<E>::placeholder())
00699 {
00700 typedef vector< E,fixed<2> > vector_type;
00701 typedef typename vector_type::value_type value_type;
00702
00703 value_type angle = matrix_to_rotation_2D(m);
00704 matrix_rotation_2D(m, angle * t);
00705 }
00706
00708
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00724 #define MAT_TEMP_3X3 matrix< \
00725 typename et::ScalarPromote< \
00726 typename MatT_1::value_type, \
00727 typename MatT_2::value_type \
00728 >::type, \
00729 fixed<3,3>, \
00730 typename MatT_1::basis_orient, \
00731 row_major \
00732 >
00733
00735 #define MAT_TEMP_2X2 matrix< \
00736 typename et::ScalarPromote< \
00737 typename MatT_1::value_type, \
00738 typename MatT_2::value_type \
00739 >::type, \
00740 fixed<2,2>, \
00741 typename MatT_1::basis_orient, \
00742 row_major \
00743 >
00744
00745 namespace detail {
00746
00748 template < class MatT_1, class MatT_2 > MAT_TEMP_3X3
00749 matrix_concat_rotations(const MatT_1& m1, const MatT_2& m2, row_basis) {
00750 return m1*m2;
00751 }
00752
00754 template < class MatT_1, class MatT_2 > MAT_TEMP_3X3
00755 matrix_concat_rotations(const MatT_1& m1, const MatT_2& m2, col_basis) {
00756 return m2*m1;
00757 }
00758
00760 template < class MatT_1, class MatT_2 > MAT_TEMP_3X3
00761 matrix_concat_rotations(const MatT_1& m1, const MatT_2& m2) {
00762 return matrix_concat_rotations(m1,m2,typename MatT_1::basis_orient());
00763 }
00764
00766 template < class MatT_1, class MatT_2 > MAT_TEMP_2X2
00767 matrix_concat_rotations_2D(const MatT_1& m1, const MatT_2& m2, row_basis) {
00768 return m1*m2;
00769 }
00770
00772 template < class MatT_1, class MatT_2 > MAT_TEMP_2X2
00773 matrix_concat_rotations_2D(const MatT_1& m1, const MatT_2& m2, col_basis) {
00774 return m2*m1;
00775 }
00776
00778 template < class MatT_1, class MatT_2 > MAT_TEMP_2X2
00779 matrix_concat_rotations_2D(const MatT_1& m1, const MatT_2& m2) {
00780 return matrix_concat_rotations_2D(m1,m2,typename MatT_1::basis_orient());
00781 }
00782
00783 }
00784
00786
00788
00790 template < class MatT_1, class MatT_2 > MAT_TEMP_3X3
00791 matrix_rotation_difference(const MatT_1& m1, const MatT_2& m2) {
00792 return detail::matrix_concat_rotations(transpose(m1),m2);
00793 }
00794
00796 template < class MatT_1, class MatT_2 > MAT_TEMP_2X2
00797 matrix_rotation_difference_2D(const MatT_1& m1, const MatT_2& m2) {
00798 return detail::matrix_concat_rotations_2D(transpose(m1),m2);
00799 }
00800
00802
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00819 template < class MatT_1, class MatT_2, typename E > MAT_TEMP_3X3
00820 matrix_slerp(const MatT_1& m1, const MatT_2& m2, E t,
00821 E tolerance = epsilon<E>::placeholder())
00822 {
00823 typedef MAT_TEMP_3X3 temporary_type;
00824
00825 temporary_type m = matrix_rotation_difference(m1,m2);
00826 matrix_scale_rotation_angle(m,t,tolerance);
00827 return detail::matrix_concat_rotations(m1,m);
00828 }
00829
00831 template < class MatT_1, class MatT_2, typename E > MAT_TEMP_2X2
00832 matrix_slerp_2D(const MatT_1& m1, const MatT_2& m2, E t,
00833 E tolerance = epsilon<E>::placeholder())
00834 {
00835 typedef MAT_TEMP_2X2 temporary_type;
00836
00837 temporary_type m = matrix_rotation_difference_2D(m1,m2);
00838 matrix_scale_rotation_angle_2D(m,t,tolerance);
00839 return detail::matrix_concat_rotations_2D(m1,m);
00840 }
00841
00842 #undef MAT_TEMP_3X3
00843 #undef MAT_TEMP_2X2
00844
00846
00848
00850 template < class MatT, typename E, class A > void
00851 matrix_to_axis_angle(
00852 const MatT& m,
00853 vector<E,A >& axis,
00854 E& angle,
00855 E tolerance = epsilon<E>::placeholder())
00856 {
00857 typedef MatT matrix_type;
00858 typedef typename matrix_type::value_type value_type;
00859
00860
00861 detail::CheckMatLinear3D(m);
00862
00863 axis.set(
00864 m.basis_element(1,2) - m.basis_element(2,1),
00865 m.basis_element(2,0) - m.basis_element(0,2),
00866 m.basis_element(0,1) - m.basis_element(1,0)
00867 );
00868 value_type l = length(axis);
00869 value_type tmo = trace_3x3(m) - value_type(1);
00870
00871 if (l > tolerance) {
00872 axis /= l;
00873 angle = std::atan2(l, tmo);
00874 } else if (tmo > value_type(0)) {
00875 axis.zero();
00876 angle = value_type(0);
00877 } else {
00878 size_t largest_diagonal_element =
00879 index_of_max(
00880 m.basis_element(0,0),
00881 m.basis_element(1,1),
00882 m.basis_element(2,2)
00883 );
00884 size_t i, j, k;
00885 cyclic_permutation(largest_diagonal_element, i, j, k);
00886 axis[i] =
00887 std::sqrt(
00888 m.basis_element(i,i) -
00889 m.basis_element(j,j) -
00890 m.basis_element(k,k) +
00891 value_type(1)
00892 ) * value_type(.5);
00893 value_type s = value_type(.5) / axis[i];
00894 axis[j] = m.basis_element(i,j) * s;
00895 axis[k] = m.basis_element(i,k) * s;
00896 angle = constants<value_type>::pi();
00897 }
00898 }
00899
00901 template < class MatT, typename Real >
00902 void matrix_to_euler(
00903 const MatT& m,
00904 Real& angle_0,
00905 Real& angle_1,
00906 Real& angle_2,
00907 EulerOrder order,
00908 Real tolerance = epsilon<Real>::placeholder())
00909 {
00910 typedef MatT matrix_type;
00911 typedef typename matrix_type::value_type value_type;
00912
00913
00914 detail::CheckMatLinear3D(m);
00915
00916 size_t i, j, k;
00917 bool odd, repeat;
00918 detail::unpack_euler_order(order, i, j, k, odd, repeat);
00919
00920 if (repeat) {
00921 value_type s1 = length(m.basis_element(j,i),m.basis_element(k,i));
00922 value_type c1 = m.basis_element(i,i);
00923
00924 angle_1 = std::atan2(s1, c1);
00925 if (s1 > tolerance) {
00926 angle_0 = std::atan2(m.basis_element(j,i),m.basis_element(k,i));
00927 angle_2 = std::atan2(m.basis_element(i,j),-m.basis_element(i,k));
00928 } else {
00929 angle_0 = value_type(0);
00930 angle_2 = sign(c1) *
00931 std::atan2(-m.basis_element(k,j),m.basis_element(j,j));
00932 }
00933 } else {
00934 value_type s1 = -m.basis_element(i,k);
00935 value_type c1 = length(m.basis_element(i,i),m.basis_element(i,j));
00936
00937 angle_1 = std::atan2(s1, c1);
00938 if (c1 > tolerance) {
00939 angle_0 = std::atan2(m.basis_element(j,k),m.basis_element(k,k));
00940 angle_2 = std::atan2(m.basis_element(i,j),m.basis_element(i,i));
00941 } else {
00942 angle_0 = value_type(0);
00943 angle_2 = -sign(s1) *
00944 std::atan2(-m.basis_element(k,j),m.basis_element(j,j));
00945 }
00946 }
00947
00948 if (odd) {
00949 angle_0 = -angle_0;
00950 angle_1 = -angle_1;
00951 angle_2 = -angle_2;
00952 }
00953 }
00954
00956 template < class MatT > typename MatT::value_type
00957 matrix_to_rotation_2D(const MatT& m)
00958 {
00959
00960 detail::CheckMatLinear2D(m);
00961
00962 return std::atan2(m.basis_element(0,1),m.basis_element(0,0));
00963 }
00964
00965 }
00966
00967 #endif