interpolation.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00013 #ifndef interpolation_h
00014 #define interpolation_h
00015 
00016 #include <cml/mathlib/matrix_rotation.h>
00017 
00018 /* Interpolation functions.
00019  *
00020  * @todo: This code works, but it needs a lot of cleanup.
00021  */
00022 
00023 namespace cml {
00024 
00025 struct function_expects_args_of_same_type_error;
00026 
00027 namespace detail {
00028 
00030 // Helper struct to promote vectors, quaternions, and matrices
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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     /* @todo: This should be VectorPromote<> for symmetry with the other
00068      * type promotions.
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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     /* Check that results are of the same type */
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 // Helper functions to resize a vector, quaternion or matrix
00211 
00212 // Should be able to catch all no-ops with a generic function template...
00213 
00214 template < class T1, class T2, class SizeTag > void
00215 InterpResize(T1& t1, const T2& t2, SizeTag) {}
00216 
00217 // Catch vector and matrix resizes...
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 // Construction of 'intermediate' quaternions and matrices for use with squad
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 // Spherical linear interpolation of two vectors of any size
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 // Spherical linear interpolation of two quaternions
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         // Turning this off temporarily to test squad...
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 // Helper struct for spherical linear interpolation of 3x3 and 2x2 matrices
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 // Spherical linear interpolation of two matrices of size 3x3 or 2x2
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 // Normalized linear interpolation of two vectors of any size
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 // Normalized linear interpolation of two quaternions
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 // Helper struct for normalized linear interpolation of 3x3 and 2x2 matrices
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 // Normalized linear interpolation of two matrices of size 3x3 or 2x2
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 } // namespace detail
00788 
00790 // Construction of 'intermediate' quaternions and matrices for use with squad
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     // HACK: See note above...
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 // Spherical quadrangle interpolation of two quaternions or matrices
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     // HACK: See note above...
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 // Spherical linear interpolation of two vectors, quaternions or matrices
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 // Normalized linear interpolation of two vectors, quaternions or matrices
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 // Linear interpolation of two values of any qualified type
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 // Bilinear interpolation of four values of any qualified type
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 // Trilinear interpolation of eight values of any qualified type
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 } // namespace cml
01128 
01129 #endif

Generated on Sat Jul 18 19:35:22 2009 for CML 1.0 by  doxygen 1.5.9