00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef interpolation_h
00014 #define interpolation_h
00015
00016 #include <cml/mathlib/matrix_rotation.h>
00017
00018
00019
00020
00021
00022
00023 namespace cml {
00024
00025 struct function_expects_args_of_same_type_error;
00026
00027 namespace detail {
00028
00030
00032
00033 template< class T1, class T2, class ResultT > struct TypePromote;
00034
00035 template< class T >
00036 struct TypePromote< T,T,et::scalar_result_tag > {
00037 typedef T temporary_type;
00038 };
00039
00040 template< class T1, class T2 >
00041 struct TypePromote< T1,T2,et::scalar_result_tag > {
00042 typedef et::ExprTraits<T1> traits_1;
00043 typedef et::ExprTraits<T2> traits_2;
00044 typedef typename traits_1::result_tag result_type_1;
00045 typedef typename traits_2::result_tag result_type_2;
00046
00047
00048 CML_STATIC_REQUIRE_M(
00049 (same_type<result_type_1, result_type_2>::is_true),
00050 function_expects_args_of_same_type_error);
00051
00052 typedef typename et::ScalarPromote<T1,T2>::type temporary_type;
00053 };
00054
00055 template< class T1, class T2 >
00056 struct TypePromote< T1,T2,et::vector_result_tag > {
00057 typedef et::ExprTraits<T1> traits_1;
00058 typedef et::ExprTraits<T2> traits_2;
00059 typedef typename traits_1::result_tag result_type_1;
00060 typedef typename traits_2::result_tag result_type_2;
00061
00062
00063 CML_STATIC_REQUIRE_M(
00064 (same_type<result_type_1, result_type_2>::is_true),
00065 function_expects_args_of_same_type_error);
00066
00067
00068
00069
00070 typedef typename CrossPromote<T1,T2>::promoted_vector temporary_type;
00071 };
00072
00073 template< class T1, class T2 >
00074 struct TypePromote< T1,T2,et::matrix_result_tag > {
00075 typedef et::ExprTraits<T1> traits_1;
00076 typedef et::ExprTraits<T2> traits_2;
00077 typedef typename traits_1::result_tag result_type_1;
00078 typedef typename traits_2::result_tag result_type_2;
00079
00080
00081 CML_STATIC_REQUIRE_M(
00082 (same_type<result_type_1, result_type_2>::is_true),
00083 function_expects_args_of_same_type_error);
00084
00085 typedef typename et::MatrixPromote2<T1,T2>::temporary_type temporary_type;
00086 };
00087
00088 template< class T1, class T2 >
00089 struct TypePromote< T1,T2,et::quaternion_result_tag > {
00090 typedef et::ExprTraits<T1> traits_1;
00091 typedef et::ExprTraits<T2> traits_2;
00092 typedef typename traits_1::result_tag result_type_1;
00093 typedef typename traits_2::result_tag result_type_2;
00094
00095
00096 CML_STATIC_REQUIRE_M(
00097 (same_type<result_type_1, result_type_2>::is_true),
00098 function_expects_args_of_same_type_error);
00099
00100 typedef typename et::QuaternionPromote2<T1,T2>::temporary_type
00101 temporary_type;
00102 };
00103
00104 template< class T1, class T2, class T3, class ResultT > struct TypePromote3;
00105
00106 template< class T1, class T2, class T3 >
00107 struct TypePromote3< T1,T2,T3,et::matrix_result_tag > {
00108 typedef et::ExprTraits<T1> traits_1;
00109 typedef et::ExprTraits<T2> traits_2;
00110 typedef et::ExprTraits<T3> traits_3;
00111 typedef typename traits_1::result_tag result_type_1;
00112 typedef typename traits_2::result_tag result_type_2;
00113 typedef typename traits_3::result_tag result_type_3;
00114
00115
00116 CML_STATIC_REQUIRE_M(
00117 (same_type<result_type_1, result_type_2>::is_true),
00118 function_expects_args_of_same_type_error);
00119 CML_STATIC_REQUIRE_M(
00120 (same_type<result_type_1, result_type_3>::is_true),
00121 function_expects_args_of_same_type_error);
00122
00123 typedef typename et::MatrixPromote3<T1,T2,T3>::temporary_type
00124 temporary_type;
00125 typedef typename temporary_type::value_type value_type;
00126 };
00127
00128 template< class T1, class T2, class T3 >
00129 struct TypePromote3< T1,T2,T3,et::quaternion_result_tag > {
00130 typedef et::ExprTraits<T1> traits_1;
00131 typedef et::ExprTraits<T2> traits_2;
00132 typedef et::ExprTraits<T3> traits_3;
00133 typedef typename traits_1::result_tag result_type_1;
00134 typedef typename traits_2::result_tag result_type_2;
00135 typedef typename traits_3::result_tag result_type_3;
00136
00137
00138 CML_STATIC_REQUIRE_M(
00139 (same_type<result_type_1, result_type_2>::is_true),
00140 function_expects_args_of_same_type_error);
00141 CML_STATIC_REQUIRE_M(
00142 (same_type<result_type_1, result_type_3>::is_true),
00143 function_expects_args_of_same_type_error);
00144
00145 typedef typename et::QuaternionPromote3<T1,T2,T3>::temporary_type
00146 temporary_type;
00147 typedef typename temporary_type::value_type value_type;
00148 };
00149
00150 template <
00151 class T1, class T2, class T3, class T4, class ResultT
00152 > struct TypePromote4;
00153
00154 template< class T1, class T2, class T3, class T4 >
00155 struct TypePromote4< T1,T2,T3,T4,et::matrix_result_tag > {
00156 typedef et::ExprTraits<T1> traits_1;
00157 typedef et::ExprTraits<T2> traits_2;
00158 typedef et::ExprTraits<T3> traits_3;
00159 typedef et::ExprTraits<T4> traits_4;
00160 typedef typename traits_1::result_tag result_type_1;
00161 typedef typename traits_2::result_tag result_type_2;
00162 typedef typename traits_3::result_tag result_type_3;
00163 typedef typename traits_4::result_tag result_type_4;
00164
00165
00166 CML_STATIC_REQUIRE_M(
00167 (same_type<result_type_1, result_type_2>::is_true),
00168 function_expects_args_of_same_type_error);
00169 CML_STATIC_REQUIRE_M(
00170 (same_type<result_type_1, result_type_3>::is_true),
00171 function_expects_args_of_same_type_error);
00172 CML_STATIC_REQUIRE_M(
00173 (same_type<result_type_1, result_type_4>::is_true),
00174 function_expects_args_of_same_type_error);
00175
00176 typedef typename et::MatrixPromote4<T1,T2,T3,T4>::temporary_type
00177 temporary_type;
00178 typedef typename temporary_type::value_type value_type;
00179 };
00180
00181 template< class T1, class T2, class T3, class T4 >
00182 struct TypePromote4< T1,T2,T3,T4,et::quaternion_result_tag > {
00183 typedef et::ExprTraits<T1> traits_1;
00184 typedef et::ExprTraits<T2> traits_2;
00185 typedef et::ExprTraits<T3> traits_3;
00186 typedef et::ExprTraits<T4> traits_4;
00187 typedef typename traits_1::result_tag result_type_1;
00188 typedef typename traits_2::result_tag result_type_2;
00189 typedef typename traits_3::result_tag result_type_3;
00190 typedef typename traits_4::result_tag result_type_4;
00191
00192
00193 CML_STATIC_REQUIRE_M(
00194 (same_type<result_type_1, result_type_2>::is_true),
00195 function_expects_args_of_same_type_error);
00196 CML_STATIC_REQUIRE_M(
00197 (same_type<result_type_1, result_type_3>::is_true),
00198 function_expects_args_of_same_type_error);
00199 CML_STATIC_REQUIRE_M(
00200 (same_type<result_type_1, result_type_4>::is_true),
00201 function_expects_args_of_same_type_error);
00202
00203 typedef typename et::QuaternionPromote4<T1,T2,T3,T4>::temporary_type
00204 temporary_type;
00205 typedef typename temporary_type::value_type value_type;
00206 };
00207
00209
00211
00212
00213
00214 template < class T1, class T2, class SizeTag > void
00215 InterpResize(T1& t1, const T2& t2, SizeTag) {}
00216
00217
00218
00219 template< typename E, class A, class VecT > void
00220 InterpResize(vector<E,A>& v, const VecT& target, dynamic_size_tag) {
00221 v.resize(target.size());
00222 }
00223
00224 template< typename E, class A, class B, class L, class MatT > void
00225 InterpResize(matrix<E,A,B,L>& m, const MatT& target, dynamic_size_tag) {
00226 m.resize(target.rows(),target.cols());
00227 }
00228
00230
00232
00233 #if 0
00234 template < class QuatT_1, class QuatT_2 >
00235 typename et::QuaternionPromote2<QuatT_1,QuatT_2>::temporary_type
00236 concatenate_quaternions(
00237 const QuatT_1& q1,
00238 const QuatT_2& q2,
00239 positive_cross)
00240 {
00241 return q2 * q1;
00242 }
00243
00244 template < class QuatT_1, class QuatT_2 >
00245 typename et::QuaternionPromote2<QuatT_1,QuatT_2>::temporary_type
00246 concatenate_quaternions(
00247 const QuatT_1& q1,
00248 const QuatT_2& q2,
00249 negative_cross)
00250 {
00251 return q1 * q2;
00252 }
00253
00254 template< class T1, class T2, class T3, class SizeT >
00255 typename detail::TypePromote3<
00256 T1,T2,T3,typename et::ExprTraits<T1>::result_tag
00257 >::temporary_type
00258 squad_intermediate(
00259 const T1& t1,
00260 const T2& t2,
00261 const T3& t3,
00262 typename detail::TypePromote3<
00263 T1, T2, T3, typename et::ExprTraits<T1>::result_tag
00264 >::value_type tolerance,
00265 et::quaternion_result_tag,
00266 SizeT)
00267 {
00268 typedef et::ExprTraits<T1> traits_1;
00269 typedef typename traits_1::result_tag result_type_1;
00270
00271 typedef typename detail::TypePromote3<T1,T2,T3,result_type_1>::temporary_type
00272 temporary_type;
00273 typedef typename temporary_type::value_type value_type;
00274 typedef typename temporary_type::cross_type cross_type;
00275 typedef et::ExprTraits<temporary_type> result_traits;
00276 typedef typename result_traits::size_tag size_tag;
00277
00287 temporary_type result;
00288 detail::InterpResize(result, t1, size_tag());
00289
00290 temporary_type t2_inverse = conjugate(t2);
00291 temporary_type temp1 = concatenate_quaternions(t1, t2_inverse, cross_type());
00292 temporary_type temp2 = concatenate_quaternions(t3, t2_inverse, cross_type());
00293 result = concatenate_quaternions(
00294 exp(-(log(temp1) + log(temp2)) * value_type(.25)), t2, cross_type());
00295 return result;
00296 }
00297
00315 template< class MatT_1, class MatT_2, class MatT_3, size_t N >
00316 struct squad_intermediate_f;
00317
00318 template< class MatT_1, class MatT_2, class MatT_3 >
00319 struct squad_intermediate_f<MatT_1,MatT_2,MatT_3,3>
00320 {
00321 template< typename Real >
00322 typename et::MatrixPromote3< MatT_1,MatT_2,MatT_3 >::temporary_type
00323 operator()(
00324 const MatT_1& m1,
00325 const MatT_2& m2,
00326 const MatT_3& m3,
00327 Real tolerance)
00328 {
00329 typedef typename et::MatrixPromote3<
00330 MatT_1,MatT_2,MatT_3 >::temporary_type temporary_type;
00331 typedef typename temporary_type::value_type value_type;
00332 typedef quaternion< value_type > quaternion_type;
00333
00334 quaternion_type q1, q2, q3;
00335 quaternion_rotation_matrix(q1, m1);
00336 quaternion_rotation_matrix(q2, m2);
00337 quaternion_rotation_matrix(q3, m3);
00338
00339 quaternion_type q4 = squad_intermediate(q1, q2, q3, tolerance);
00340
00341 temporary_type m;
00342 et::detail::Resize(m,3,3);
00343
00344 matrix_rotation_quaternion(m, q4);
00345
00346 return m;
00347 }
00348 };
00349
00350 template< class MatT_1, class MatT_2, class MatT_3 >
00351 struct squad_intermediate_f<MatT_1,MatT_2,MatT_3,2>
00352 {
00353 template< typename Real >
00354 typename et::MatrixPromote3< MatT_1,MatT_2,MatT_3 >::temporary_type
00355 operator()(
00356 const MatT_1& m1,
00357 const MatT_2& m2,
00358 const MatT_3& m3,
00359 Real tolerance)
00360 {
00361 typedef typename et::MatrixPromote3<
00362 MatT_1,MatT_2,MatT_3 >::temporary_type temporary_type;
00363 typedef typename temporary_type::value_type value_type;
00364 typedef quaternion< value_type > quaternion_type;
00365 typedef vector< value_type, fixed<3> > vector_type;
00366
00367 value_type angle1 = matrix_to_rotation_2D(m1);
00368 value_type angle2 = matrix_to_rotation_2D(m2);
00369 value_type angle3 = matrix_to_rotation_2D(m3);
00370 vector_type axis(value_type(0), value_type(0), value_type(1));
00371
00372 quaternion_type q1, q2, q3;
00373 quaternion_rotation_axis_angle(q1, axis, angle1);
00374 quaternion_rotation_axis_angle(q2, axis, angle2);
00375 quaternion_rotation_axis_angle(q3, axis, angle3);
00376
00377 quaternion_type q4 = squad_intermediate(q1, q2, q3, tolerance);
00378
00379 value_type angle;
00380 quaternion_to_axis_angle(q4, axis, angle);
00381
00382 temporary_type m;
00383 et::detail::Resize(m,2,2);
00384
00385 matrix_rotation_2D(m, angle);
00386
00387 return m;
00388 }
00389 };
00390
00391 template< class MatT_1, class MatT_2, class MatT_3, typename Real >
00392 typename et::MatrixPromote3< MatT_1,MatT_2,MatT_3 >::temporary_type
00393 squad_intermediate(
00394 const MatT_1& m1,
00395 const MatT_2& m2,
00396 const MatT_3& m3,
00397 Real tolerance,
00398 et::matrix_result_tag,
00399 fixed_size_tag)
00400 {
00401 return squad_intermediate_f<MatT_1,MatT_2,MatT_3,MatT_1::array_rows>()(
00402 m1,m2,m3,tolerance);
00403 }
00404
00405 template< class MatT_1, class MatT_2, class MatT_3, typename Real >
00406 typename et::MatrixPromote3< MatT_1,MatT_2,MatT_3 >::temporary_type
00407 squad_intermediate(
00408 const MatT_1& m1,
00409 const MatT_2& m2,
00410 const MatT_3& m3,
00411 Real tolerance,
00412 et::matrix_result_tag,
00413 dynamic_size_tag)
00414 {
00415 typedef typename et::MatrixPromote3<
00416 MatT_1,MatT_2,MatT_3 >::temporary_type temporary_type;
00417
00418 temporary_type m;
00419 et::detail::Resize(m,m1.rows(),m1.cols());
00420
00421 switch (m1.rows()) {
00422 case 3:
00423 m = squad_intermediate_f<MatT_1,MatT_2,MatT_3,3>()(m1,m2,m3,tolerance);
00424 break;
00425 case 2:
00426 m = squad_intermediate_f<MatT_1,MatT_2,MatT_3,2>()(m1,m2,m3,tolerance);
00427 break;
00428 default:
00429 throw std::invalid_argument(
00430 "matrix squad_intermediate_f() expects sizes 3x3 or 2x2");
00431 break;
00432 }
00433 return m;
00434 }
00435 #endif
00436
00438
00440
00441 template< class VecT_1, class VecT_2, typename Real, class SizeT >
00442 typename detail::TypePromote<
00443 VecT_1,VecT_2,typename et::ExprTraits<VecT_1>::result_tag
00444 >::temporary_type
00445 slerp(
00446 const VecT_1& v1,
00447 const VecT_2& v2,
00448 Real t,
00449 Real tolerance,
00450 et::vector_result_tag,
00451 SizeT)
00452 {
00453 typedef et::ExprTraits<VecT_1> type_traits;
00454 typedef typename type_traits::result_tag result_type;
00455 typedef typename
00456 detail::TypePromote<VecT_1,VecT_2,result_type>::temporary_type
00457 temporary_type;
00458 typedef typename temporary_type::value_type value_type;
00459 typedef et::ExprTraits<temporary_type> result_traits;
00460 typedef typename result_traits::size_tag size_tag;
00461
00462 temporary_type result;
00463 detail::InterpResize(result, v1, size_tag());
00464
00465 value_type omega = acos_safe(dot(v1,v2));
00466 value_type s = std::sin(omega);
00467 if (s < tolerance) {
00468 result = nlerp(v1,v2,t);
00469 } else {
00470 result = (value_type(std::sin((value_type(1)-t)*omega))*v1 +
00471 value_type(std::sin(t*omega))*v2) / s;
00472 }
00473 return result;
00474 }
00475
00477
00479
00480 template< class QuatT_1, class QuatT_2, typename Real, class SizeT >
00481 typename detail::TypePromote<
00482 QuatT_1,QuatT_2,typename et::ExprTraits<QuatT_1>::result_tag
00483 >::temporary_type
00484 slerp(
00485 const QuatT_1& q1,
00486 const QuatT_2& q2,
00487 Real t,
00488 Real tolerance,
00489 et::quaternion_result_tag,
00490 SizeT)
00491 {
00492 typedef et::ExprTraits<QuatT_1> type_traits;
00493 typedef typename type_traits::result_tag result_type;
00494 typedef typename
00495 detail::TypePromote<QuatT_1,QuatT_2,result_type>::temporary_type
00496 temporary_type;
00497 typedef typename temporary_type::value_type value_type;
00498
00499 temporary_type q3 = q2;
00500 value_type c = dot(q1,q3);
00501 if (c < value_type(0)) {
00502
00503 q3 = -q3;
00504 c = -c;
00505 }
00506
00507 value_type omega = acos_safe(c);
00508 value_type s = std::sin(omega);
00509
00510 return (s < tolerance) ?
00511 normalize(lerp(q1,q3,t)) :
00512 (value_type(std::sin((value_type(1) - t) * omega)) * q1+
00513 value_type(std::sin(t * omega)) * q3) / s;
00514 }
00515
00517
00519
00520 template< class MatT_1, class MatT_2, size_t N > struct slerp_f;
00521
00522 template< class MatT_1, class MatT_2 > struct slerp_f<MatT_1,MatT_2,3>
00523 {
00524 template< typename Real >
00525 typename detail::TypePromote<
00526 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00527 >::temporary_type
00528 operator()(
00529 const MatT_1& m1,
00530 const MatT_2& m2,
00531 Real t,
00532 Real tolerance)
00533 {
00534 typedef typename detail::TypePromote<
00535 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00536 >::temporary_type temporary_type;
00537
00538 temporary_type m;
00539 et::detail::Resize(m,3,3);
00540 m = matrix_rotation_difference(m1,m2);
00541 matrix_scale_rotation_angle(m,t,tolerance);
00542 m = detail::matrix_concat_rotations(m1,m);
00543 return m;
00544 }
00545 };
00546
00547 template< class MatT_1, class MatT_2 > struct slerp_f<MatT_1,MatT_2,2>
00548 {
00549 template< typename Real >
00550 typename detail::TypePromote<
00551 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00552 >::temporary_type
00553 operator()(
00554 const MatT_1& m1,
00555 const MatT_2& m2,
00556 Real t,
00557 Real tolerance)
00558 {
00559 typedef typename detail::TypePromote<
00560 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00561 >::temporary_type temporary_type;
00562
00563 temporary_type m;
00564 et::detail::Resize(m,2,2);
00565 m = matrix_rotation_difference_2D(m1,m2);
00566 matrix_scale_rotation_angle_2D(m,t,tolerance);
00567 m = detail::matrix_concat_rotations_2D(m1,m);
00568 return m;
00569 }
00570 };
00571
00573
00575
00576 template< class MatT_1, class MatT_2, typename Real >
00577 typename detail::TypePromote<
00578 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00579 >::temporary_type
00580 slerp(
00581 const MatT_1& m1,
00582 const MatT_2& m2,
00583 Real t,
00584 Real tolerance,
00585 et::matrix_result_tag,
00586 fixed_size_tag)
00587 {
00588 return slerp_f<MatT_1,MatT_2,MatT_1::array_rows>()(m1,m2,t,tolerance);
00589 }
00590
00591 template< class MatT_1, class MatT_2, typename Real >
00592 typename detail::TypePromote<
00593 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00594 >::temporary_type
00595 slerp(
00596 const MatT_1& m1,
00597 const MatT_2& m2,
00598 Real t,
00599 Real tolerance,
00600 et::matrix_result_tag,
00601 dynamic_size_tag)
00602 {
00603 typedef typename detail::TypePromote<
00604 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00605 >::temporary_type temporary_type;
00606
00607 temporary_type m;
00608 et::detail::Resize(m,m1.rows(),m1.cols());
00609
00610 switch (m1.rows()) {
00611 case 3:
00612 m = slerp_f<MatT_1,MatT_2,3>()(m1,m2,t,tolerance);
00613 break;
00614 case 2:
00615 m = slerp_f<MatT_1,MatT_2,2>()(m1,m2,t,tolerance);
00616 break;
00617 default:
00618 throw std::invalid_argument(
00619 "matrix slerp() expects sizes 3x3 or 2x2");
00620 break;
00621 }
00622 return m;
00623 }
00624
00626
00628
00629 template< class VecT_1, class VecT_2, typename Real, class SizeT >
00630 typename detail::TypePromote<
00631 VecT_1,VecT_2,typename et::ExprTraits<VecT_1>::result_tag
00632 >::temporary_type
00633 nlerp(
00634 const VecT_1& v1,
00635 const VecT_2& v2,
00636 Real t,
00637 et::vector_result_tag,
00638 SizeT)
00639 {
00640 typedef et::ExprTraits<VecT_1> type_traits;
00641 typedef typename type_traits::result_tag result_type;
00642 typedef typename
00643 detail::TypePromote<VecT_1,VecT_2,result_type>::temporary_type
00644 temporary_type;
00645 typedef typename temporary_type::value_type value_type;
00646 typedef et::ExprTraits<temporary_type> result_traits;
00647 typedef typename result_traits::size_tag size_tag;
00648
00649 temporary_type result;
00650 detail::InterpResize(result, v1, size_tag());
00651
00652 result = (value_type(1)-t)*v1+t*v2;
00653 result.normalize();
00654 return result;
00655 }
00656
00658
00660
00661 template< class QuatT_1, class QuatT_2, typename Real, class SizeT >
00662 typename detail::TypePromote<
00663 QuatT_1,QuatT_2,typename et::ExprTraits<QuatT_1>::result_tag
00664 >::temporary_type
00665 nlerp(
00666 const QuatT_1& q1,
00667 const QuatT_2& q2,
00668 Real t,
00669 et::quaternion_result_tag,
00670 SizeT)
00671 {
00672 typedef et::ExprTraits<QuatT_1> type_traits;
00673 typedef typename type_traits::result_tag result_type;
00674 typedef typename
00675 detail::TypePromote<QuatT_1,QuatT_2,result_type>::temporary_type
00676 temporary_type;
00677 typedef typename temporary_type::value_type value_type;
00678
00679 return normalize(lerp(q1, (dot(q1,q2) < value_type(0)) ? -q2 : q2, t));
00680 }
00681
00683
00685
00686 template< class MatT_1, class MatT_2, size_t N > struct nlerp_f;
00687
00688 template< class MatT_1, class MatT_2 > struct nlerp_f<MatT_1,MatT_2,3>
00689 {
00690 template< typename Real >
00691 typename detail::TypePromote<
00692 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00693 >::temporary_type
00694 operator()(
00695 const MatT_1& m1,
00696 const MatT_2& m2,
00697 Real t)
00698 {
00699 typedef typename detail::TypePromote<
00700 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00701 >::temporary_type temporary_type;
00702 typedef typename temporary_type::value_type value_type;
00703
00704 temporary_type m;
00705 et::detail::Resize(m,3,3);
00706 m = lerp(m1,m2,t);
00707 matrix_orthogonalize_3x3(m);
00708 return m;
00709 }
00710 };
00711
00712 template< class MatT_1, class MatT_2 > struct nlerp_f<MatT_1,MatT_2,2>
00713 {
00714 template< typename Real >
00715 typename detail::TypePromote<
00716 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00717 >::temporary_type
00718 operator()(
00719 const MatT_1& m1,
00720 const MatT_2& m2,
00721 Real t)
00722 {
00723 typedef typename detail::TypePromote<
00724 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00725 >::temporary_type temporary_type;
00726 typedef typename temporary_type::value_type value_type;
00727
00728 temporary_type m;
00729 et::detail::Resize(m,2,2);
00730 m = lerp(m1,m2,t);
00731 matrix_orthogonalize_2x2(m);
00732 return m;
00733 }
00734 };
00735
00737
00739
00740 template< class MatT_1, class MatT_2, typename Real >
00741 typename detail::TypePromote<
00742 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00743 >::temporary_type
00744 nlerp(
00745 const MatT_1& m1,
00746 const MatT_2& m2,
00747 Real t,
00748 et::matrix_result_tag,
00749 fixed_size_tag)
00750 {
00751 return nlerp_f<MatT_1,MatT_2,MatT_1::array_rows>()(m1,m2,t);
00752 }
00753
00754 template< class MatT_1, class MatT_2, typename Real >
00755 typename detail::TypePromote<
00756 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00757 >::temporary_type
00758 nlerp(
00759 const MatT_1& m1,
00760 const MatT_2& m2,
00761 Real t,
00762 et::matrix_result_tag,
00763 dynamic_size_tag)
00764 {
00765 typedef typename detail::TypePromote<
00766 MatT_1,MatT_2,typename et::ExprTraits<MatT_1>::result_tag
00767 >::temporary_type temporary_type;
00768
00769 temporary_type m;
00770 et::detail::Resize(m,m1.rows(),m1.cols());
00771
00772 switch (m1.rows()) {
00773 case 3:
00774 m = nlerp_f<MatT_1,MatT_2,3>()(m1,m2,t);
00775 break;
00776 case 2:
00777 m = nlerp_f<MatT_1,MatT_2,2>()(m1,m2,t);
00778 break;
00779 default:
00780 throw std::invalid_argument(
00781 "matrix nlerp() expects sizes 3x3 or 2x2");
00782 break;
00783 }
00784 return m;
00785 }
00786
00787 }
00788
00790
00792
00807 #if 0
00808 template< class T1, class T2, class T3 >
00809 typename detail::TypePromote3<
00810 T1,T2,T3,typename et::ExprTraits<T1>::result_tag
00811 >::temporary_type
00812 squad_intermediate(
00813 const T1& t1,
00814 const T2& t2,
00815 const T3& t3,
00816 typename detail::TypePromote3<
00817 T1, T2, T3, typename et::ExprTraits<T1>::result_tag
00818 >::value_type tolerance =
00819 epsilon <
00820 typename detail::TypePromote3<
00821 T1, T2, T3, typename et::ExprTraits<T1>::result_tag
00822 >::value_type
00823 >::placeholder())
00824 {
00825
00826 detail::CheckQuat(t1);
00827 detail::CheckQuat(t2);
00828 detail::CheckQuat(t3);
00829
00830 typedef et::ExprTraits<T1> traits_1;
00831 typedef typename traits_1::result_tag result_type_1;
00832
00833 typedef typename detail::TypePromote3<T1,T2,T3,result_type_1>::temporary_type
00834 temporary_type;
00835 typedef et::ExprTraits<temporary_type> result_traits;
00836 typedef typename result_traits::size_tag size_tag;
00837
00838 temporary_type result;
00839 detail::InterpResize(result, t1, size_tag());
00840
00841 result = detail::squad_intermediate(
00842 t1,t2,t3,tolerance,result_type_1(),size_tag());
00843 return result;
00844 }
00845
00847
00849
00871 template< class T1, class T2, class T3, class T4, typename Real >
00872 typename detail::TypePromote4<
00873 T1,T2,T3,T4,typename et::ExprTraits<T1>::result_tag
00874 >::temporary_type
00875 squad(
00876 const T1& t1,
00877 const T2& t1_intermediate,
00878 const T3& t2_intermediate,
00879 const T4& t2,
00880 Real t,
00881 Real tolerance = epsilon<Real>::placeholder())
00882 {
00883
00884 detail::CheckQuat(t1);
00885 detail::CheckQuat(t1_intermediate);
00886 detail::CheckQuat(t2_intermediate);
00887 detail::CheckQuat(t2);
00888
00889 typedef et::ExprTraits<T1> traits_1;
00890 typedef typename traits_1::result_tag result_type_1;
00891
00892 typedef typename detail::TypePromote4<
00893 T1,T2,T3,T4,result_type_1>::temporary_type temporary_type;
00894 typedef typename temporary_type::value_type value_type;
00895 typedef et::ExprTraits<temporary_type> result_traits;
00896 typedef typename result_traits::size_tag size_tag;
00897
00898 temporary_type result;
00899 detail::InterpResize(result, t1, size_tag());
00900
00901 result = slerp(
00902 slerp(t1, t2, t, tolerance),
00903 slerp(t1_intermediate, t2_intermediate, t, tolerance),
00904 value_type(2) * t * (value_type(1) - t),
00905 tolerance
00906 );
00907
00908 return result;
00909 }
00910 #endif
00911
00913
00915
00916 template< class T1, class T2, typename Real >
00917 typename detail::TypePromote<
00918 T1,T2,typename et::ExprTraits<T1>::result_tag
00919 >::temporary_type
00920 slerp(
00921 const T1& t1,
00922 const T2& t2,
00923 Real t,
00924 Real tolerance = epsilon<Real>::placeholder())
00925 {
00926 typedef et::ExprTraits<T1> traits_1;
00927 typedef typename traits_1::result_tag result_type_1;
00928
00929 typedef typename detail::TypePromote<T1,T2,result_type_1>::temporary_type
00930 temporary_type;
00931 typedef et::ExprTraits<temporary_type> result_traits;
00932 typedef typename result_traits::size_tag size_tag;
00933
00934 temporary_type result;
00935 detail::InterpResize(result, t1, size_tag());
00936
00937 result = detail::slerp(t1,t2,t,tolerance,result_type_1(),size_tag());
00938 return result;
00939 }
00940
00942
00944
00945 template< class T1, class T2, typename Real >
00946 typename detail::TypePromote<
00947 T1,T2,typename et::ExprTraits<T1>::result_tag
00948 >::temporary_type
00949 nlerp(const T1& t1, const T2& t2, Real t)
00950 {
00951 typedef et::ExprTraits<T1> traits_1;
00952 typedef typename traits_1::result_tag result_type_1;
00953
00954 typedef typename detail::TypePromote<T1,T2,result_type_1>::temporary_type
00955 temporary_type;
00956 typedef et::ExprTraits<temporary_type> result_traits;
00957 typedef typename result_traits::size_tag size_tag;
00958
00959 temporary_type result;
00960 detail::InterpResize(result, t1, size_tag());
00961
00962 result = detail::nlerp(t1,t2,t,result_type_1(),size_tag());
00963 return result;
00964 }
00965
00967
00969
00975 template< class T1, class T2, typename Scalar >
00976 typename detail::TypePromote<
00977 T1,T2,typename et::ExprTraits<T1>::result_tag
00978 >::temporary_type
00979 lerp(const T1& val0, const T2& val1, Scalar u)
00980 {
00981 typedef
00982 typename detail::TypePromote<
00983 T1,T2,typename et::ExprTraits<T1>::result_tag
00984 >::temporary_type temporary_type;
00985
00986 typedef et::ExprTraits<temporary_type> result_traits;
00987 typedef typename result_traits::size_tag size_tag;
00988
00989 temporary_type result;
00990 detail::InterpResize(result, val1, size_tag());
00991
00992 result = (Scalar(1) - u) * val0 + u * val1;
00993 return result;
00994 }
00995
00997
00999
01000 template < class T1, class T2, class T3, class T4, typename Scalar >
01001 typename detail::TypePromote<
01002 typename detail::TypePromote<
01003 T1,T2,typename et::ExprTraits<T1>::result_tag
01004 >::temporary_type,
01005 typename detail::TypePromote<
01006 T3,T4,typename et::ExprTraits<T3>::result_tag
01007 >::temporary_type,
01008 typename et::ExprTraits<T1>::result_tag
01009 >::temporary_type
01010 bilerp(const T1& val00, const T2& val10,
01011 const T3& val01, const T4& val11,
01012 Scalar u, Scalar v)
01013 {
01014 typedef
01015 typename detail::TypePromote<
01016 typename detail::TypePromote<
01017 T1,T2,typename et::ExprTraits<T1>::result_tag
01018 >::temporary_type,
01019 typename detail::TypePromote<
01020 T3,T4,typename et::ExprTraits<T1>::result_tag
01021 >::temporary_type,
01022 typename et::ExprTraits<T1>::result_tag
01023 >::temporary_type temporary_type;
01024
01025 typedef et::ExprTraits<temporary_type> result_traits;
01026 typedef typename result_traits::size_tag size_tag;
01027
01028 temporary_type result;
01029 detail::InterpResize(result, val00, size_tag());
01030
01031 Scalar uv = u * v;
01032 result = (
01033 (Scalar(1.0) - u - v + uv) * val00 +
01034 (u - uv) * val10 +
01035 (v - uv) * val01 +
01036 uv * val11
01037 );
01038 return result;
01039 }
01040
01042
01044
01050 template < class T1, class T2, class T3, class T4,
01051 class T5, class T6, class T7, class T8,
01052 typename Scalar >
01053 typename detail::TypePromote<
01054 typename detail::TypePromote<
01055 typename detail::TypePromote<
01056 T1,T2,typename et::ExprTraits<T1>::result_tag
01057 >::temporary_type,
01058 typename detail::TypePromote<
01059 T3,T4,typename et::ExprTraits<T3>::result_tag
01060 >::temporary_type,
01061 typename et::ExprTraits<T1>::result_tag
01062 >::temporary_type,
01063 typename detail::TypePromote<
01064 typename detail::TypePromote<
01065 T5,T6,typename et::ExprTraits<T5>::result_tag
01066 >::temporary_type,
01067 typename detail::TypePromote<
01068 T7,T8,typename et::ExprTraits<T7>::result_tag
01069 >::temporary_type,
01070 typename et::ExprTraits<T1>::result_tag
01071 >::temporary_type,
01072 typename et::ExprTraits<T1>::result_tag
01073 >::temporary_type
01074 trilerp(const T1& val000, const T2& val100,
01075 const T3& val010, const T4& val110,
01076 const T5& val001, const T6& val101,
01077 const T7& val011, const T8& val111,
01078 Scalar u, Scalar v, Scalar w)
01079 {
01080 typedef
01081 typename detail::TypePromote<
01082 typename detail::TypePromote<
01083 typename detail::TypePromote<
01084 T1,T2,typename et::ExprTraits<T1>::result_tag
01085 >::temporary_type,
01086 typename detail::TypePromote<
01087 T3,T4,typename et::ExprTraits<T1>::result_tag
01088 >::temporary_type,
01089 typename et::ExprTraits<T1>::result_tag
01090 >::temporary_type,
01091 typename detail::TypePromote<
01092 typename detail::TypePromote<
01093 T5,T6,typename et::ExprTraits<T1>::result_tag
01094 >::temporary_type,
01095 typename detail::TypePromote<
01096 T7,T8,typename et::ExprTraits<T1>::result_tag
01097 >::temporary_type,
01098 typename et::ExprTraits<T1>::result_tag
01099 >::temporary_type,
01100 typename et::ExprTraits<T1>::result_tag
01101 >::temporary_type temporary_type;
01102
01103 typedef et::ExprTraits<temporary_type> result_traits;
01104 typedef typename result_traits::size_tag size_tag;
01105
01106 temporary_type result;
01107 detail::InterpResize(result, val000, size_tag());
01108
01109 Scalar uv = u * v;
01110 Scalar vw = v * w;
01111 Scalar wu = w * u;
01112 Scalar uvw = uv * w;
01113
01114 result = (
01115 (Scalar(1.0) - u - v - w + uv + vw + wu - uvw) * val000 +
01116 (u - uv - wu + uvw) * val100 +
01117 (v - uv - vw + uvw) * val010 +
01118 (uv - uvw) * val110 +
01119 (w - vw - wu + uvw) * val001 +
01120 (wu - uvw) * val101 +
01121 (vw - uvw) * val011 +
01122 uvw * val111
01123 );
01124 return result;
01125 }
01126
01127 }
01128
01129 #endif