From 50c1239917f5e443b8ec91773c85ceb3db7da67b Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Fri, 4 Sep 2009 20:17:02 -0600 Subject: [PATCH] cml version bump to 1.0.1 --- src/Moof/cml/constants.h | 28 ++-- src/Moof/cml/core/meta/common.h | 30 ++++ src/Moof/cml/et/scalar_promotions.h | 126 ++++++++++++++- src/Moof/cml/mathlib/frustum.h | 43 ++++-- src/Moof/cml/mathlib/matrix_rotation.h | 97 +++++++++++- src/Moof/cml/mathlib/matrix_translation.h | 38 +++++ src/Moof/cml/mathlib/typedef.h | 26 ++++ src/Moof/cml/mathlib/vector_ortho.h | 52 +++---- src/Moof/cml/matrix/dynamic.h | 10 ++ src/Moof/cml/matrix/external.h | 12 ++ src/Moof/cml/matrix/fixed.h | 10 ++ src/Moof/cml/matrix/matrix_promotions.h | 180 ++++++++++++---------- src/Moof/cml/matrix/matrix_unroller.h | 18 ++- src/Moof/cml/quaternion/quaternion.h | 7 + src/Moof/cml/util.h | 46 +++++- src/Moof/cml/vector/dynamic.h | 3 + src/Moof/cml/vector/external.h | 9 ++ src/Moof/cml/vector/fixed.h | 20 +++ src/Moof/cml/vector/vector_print.h | 4 - 19 files changed, 610 insertions(+), 149 deletions(-) diff --git a/src/Moof/cml/constants.h b/src/Moof/cml/constants.h index 060705c..d3392ef 100644 --- a/src/Moof/cml/constants.h +++ b/src/Moof/cml/constants.h @@ -37,19 +37,21 @@ namespace cml { */ template struct constants { - static Float pi() { return M_PI; } - static Float two_pi() { return 2.*M_PI; } - static Float inv_pi() { return 1./M_PI; } - static Float inv_two_pi() { return 1./(2.*M_PI); } - static Float pi_over_2() { return M_PI/2.; } - static Float pi_over_4() { return M_PI/4.; } - static Float deg_per_rad() { return 180./M_PI; } - static Float rad_per_deg() { return M_PI/180.; } - static Float sqrt_2() { return M_SQRT2; } - static Float sqrt_3() { return 1.732050807568877293527446341505; } - static Float sqrt_5() { return 2.236067977499789696409173668731; } - static Float sqrt_6() { return 2.449489742783178098197284074705; } - static Float e() { return M_E; } + static Float pi() { return Float(M_PI); } + static Float two_pi() { return Float(2.*M_PI); } + static Float inv_pi() { return Float(1./M_PI); } + static Float inv_two_pi() { return Float(1./(2.*M_PI)); } + static Float pi_over_2() { return Float(M_PI/2.); } + static Float pi_over_4() { return Float(M_PI/4.); } + static Float deg_per_rad() { return Float(180./M_PI); } + static Float rad_per_deg() { return Float(M_PI/180.); } + + static Float sqrt_2() { return Float(M_SQRT2); } + static Float sqrt_3() { return Float(1.732050807568877293527446341505); } + static Float sqrt_5() { return Float(2.236067977499789696409173668731); } + static Float sqrt_6() { return Float(2.449489742783178098197284074705); } + + static Float e() { return Float(M_E); } }; #else diff --git a/src/Moof/cml/core/meta/common.h b/src/Moof/cml/core/meta/common.h index 6d9b876..08c129d 100644 --- a/src/Moof/cml/core/meta/common.h +++ b/src/Moof/cml/core/meta/common.h @@ -80,6 +80,36 @@ template<> struct same_type { enum { is_true = true, is_false = false }; }; +/** Remove a reference qualifier from a type. */ +template struct remove_reference { + template struct helper { + typedef Q type; + }; + + template struct helper { + typedef Q type; + }; + + template struct helper { + typedef const Q type; + }; + + typedef typename helper::type type; +}; + +/** Remove a const qualifier from a type. */ +template struct remove_const { + template struct helper { + typedef Q type; + }; + + template struct helper { + typedef Q type; + }; + + typedef typename helper::type type; +}; + } // namespace cml #endif diff --git a/src/Moof/cml/et/scalar_promotions.h b/src/Moof/cml/et/scalar_promotions.h index 55d033c..bb6f8a2 100644 --- a/src/Moof/cml/et/scalar_promotions.h +++ b/src/Moof/cml/et/scalar_promotions.h @@ -13,11 +13,135 @@ Boost Software License, v1.0 (see cml/LICENSE for details). #ifndef scalar_promotions_h #define scalar_promotions_h +#include #include namespace cml { namespace et { +// #define CML_USE_OLD_SCALAR_PROMOTIONS +#if !defined(CML_USE_OLD_SCALAR_PROMOTIONS) + +/* The type promotion code below is a slightly modified version of: + * http://ubiety.uwaterloo.ca/~tveldhui/papers/techniques/techniques01.html + */ +namespace detail { + +template +struct precision_trait { + enum { precisionRank = 0, + knowPrecisionRank = 0 }; +}; + +#define DECLARE_PRECISION(T,rank) \ + template<> \ + struct precision_trait< T > { \ + enum { precisionRank = rank, \ + knowPrecisionRank = 1 }; \ + }; + +DECLARE_PRECISION(int,100) +DECLARE_PRECISION(unsigned int,200) +DECLARE_PRECISION(long,300) +DECLARE_PRECISION(unsigned long,400) + +DECLARE_PRECISION(long long,425) +DECLARE_PRECISION(unsigned long long,475) + +DECLARE_PRECISION(float,500) +DECLARE_PRECISION(double,600) +DECLARE_PRECISION(long double,700) +DECLARE_PRECISION(std::complex,800) +DECLARE_PRECISION(std::complex,900) +DECLARE_PRECISION(std::complex,1000) + +template +struct autopromote_trait { + typedef T T_numtype; +}; + +#define DECLARE_AUTOPROMOTE(T1,T2) \ + template<> \ + struct autopromote_trait { \ + typedef T2 T_numtype; \ + }; + +// These are the odd cases where small integer types +// are automatically promoted to int or unsigned int for +// arithmetic. +DECLARE_AUTOPROMOTE(bool, int) +DECLARE_AUTOPROMOTE(char, int) +DECLARE_AUTOPROMOTE(unsigned char, int) +DECLARE_AUTOPROMOTE(short int, int) +DECLARE_AUTOPROMOTE(short unsigned int, unsigned int) + +template +struct promote2 { + typedef T1 T_promote; +}; + +template +struct promote2 { + typedef T2 T_promote; +}; + +template +struct promote_trait { + // Handle promotion of small integers to int/unsigned int + typedef typename autopromote_trait::T_numtype T1; + typedef typename autopromote_trait::T_numtype T2; + + // True if T1 is higher ranked + enum { + T1IsBetter = + (int) precision_trait::precisionRank > + (int) precision_trait::precisionRank, + + // True if we know ranks for both T1 and T2 + knowBothRanks = + precision_trait::knowPrecisionRank + && precision_trait::knowPrecisionRank, + + // True if we know T1 but not T2 + knowT1butNotT2 = precision_trait::knowPrecisionRank + && !(precision_trait::knowPrecisionRank), + + // True if we know T2 but not T1 + knowT2butNotT1 = precision_trait::knowPrecisionRank + && !(precision_trait::knowPrecisionRank), + + // True if T1 is bigger than T2 + T1IsLarger = sizeof(T1) >= sizeof(T2), + + // We know T1 but not T2: true + // We know T2 but not T1: false + // Otherwise, if T1 is bigger than T2: true + defaultPromotion = knowT1butNotT2 ? false : + (knowT2butNotT1 ? true : T1IsLarger) + }; + + // If we have both ranks, then use them. + // If we have only one rank, then use the unknown type. + // If we have neither rank, then promote to the larger type. + + enum { + promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion) + ? 1 : 0 + }; + + typedef typename promote2::T_promote T_promote; +}; + +} // namespace detail + +/** Defers to detail::promote_trait<>. */ +template struct ScalarPromote +{ + typedef typename detail::promote_trait::T_promote type; +}; + +#else + namespace detail { /** @class IntPromote @@ -43,7 +167,6 @@ template struct IntPromote */ template struct ScalarPromote { - /* Integral-promote the types (if possible). */ typedef typename detail::IntPromote::result E1; typedef typename detail::IntPromote::result E2; @@ -110,6 +233,7 @@ template struct ScalarPromote same_type::is_true, int_filter, float_filter>::result type; }; +#endif } // namespace et } // namespace cml diff --git a/src/Moof/cml/mathlib/frustum.h b/src/Moof/cml/mathlib/frustum.h index 6a707af..43eb41f 100644 --- a/src/Moof/cml/mathlib/frustum.h +++ b/src/Moof/cml/mathlib/frustum.h @@ -108,18 +108,7 @@ extract_frustum_planes( planes[5][3] = m.basis_element(3,3) - m.basis_element(3,2); /* Near: [03+02, 13+12, 23+22, 33+32] : [02, 12, 22, 32] */ - - if (z_clip == z_clip_neg_one) { - planes[4][0] = m.basis_element(0,3) + m.basis_element(0,2); - planes[4][1] = m.basis_element(1,3) + m.basis_element(1,2); - planes[4][2] = m.basis_element(2,3) + m.basis_element(2,2); - planes[4][3] = m.basis_element(3,3) + m.basis_element(3,2); - } else { // z_clip == z_clip_zero - planes[4][0] = m.basis_element(0,2); - planes[4][1] = m.basis_element(1,2); - planes[4][2] = m.basis_element(2,2); - planes[4][3] = m.basis_element(3,2); - } + extract_near_frustum_plane(m, planes[4], z_clip); /* @todo: This will be handled by the plane class */ if (normalize) { @@ -136,6 +125,36 @@ extract_frustum_planes( } } +/** Extract the near plane of a frustum given a concatenated modelview and + * projection matrix with the given near z-clipping range. The plane is + * not normalized. + * + * @note The plane is in ax+by+cz+d = 0 form. + * + * @warning The matrix is assumed to be a homogeneous transformation + * matrix. + */ +template < class MatT, class PlaneT > void +extract_near_frustum_plane( + const MatT& m, + PlaneT& plane, + ZClip z_clip + ) +{ + /* Near: [03+02, 13+12, 23+22, 33+32] : [02, 12, 22, 32] */ + if (z_clip == z_clip_neg_one) { + plane[0] = m.basis_element(0,3) + m.basis_element(0,2); + plane[1] = m.basis_element(1,3) + m.basis_element(1,2); + plane[2] = m.basis_element(2,3) + m.basis_element(2,2); + plane[3] = m.basis_element(3,3) + m.basis_element(3,2); + } else { // z_clip == z_clip_zero + plane[0] = m.basis_element(0,2); + plane[1] = m.basis_element(1,2); + plane[2] = m.basis_element(2,2); + plane[3] = m.basis_element(3,2); + } +} + namespace detail { /* This is currently only in support of finding the corners of a frustum. diff --git a/src/Moof/cml/mathlib/matrix_rotation.h b/src/Moof/cml/mathlib/matrix_rotation.h index 9c3821d..2298c22 100644 --- a/src/Moof/cml/mathlib/matrix_rotation.h +++ b/src/Moof/cml/mathlib/matrix_rotation.h @@ -186,8 +186,11 @@ matrix_rotation_quaternion(matrix& m, const QuatT& q) * euler_order_zyx * euler_order_zxz * euler_order_zyz + * + * e.g. euler_order_xyz means compute the column-basis rotation matrix + * equivalent to R_x * R_y * R_z, where R_i is the rotation matrix above + * axis i (the row-basis matrix would be R_z * R_y * R_x). */ - template < typename E, class A, class B, class L > void matrix_rotation_euler(matrix& m, E angle_0, E angle_1, E angle_2, EulerOrder order) @@ -245,6 +248,98 @@ matrix_rotation_euler(matrix& m, E angle_0, E angle_1, E angle_2, } } +/** Build a matrix of derivatives of Euler angles about the specified axis. + * + * The rotation derivatives are applied about the cardinal axes in the + * order specified by the 'order' argument, where 'order' is one of the + * following enumerants: + * + * euler_order_xyz + * euler_order_xzy + * euler_order_yzx + * euler_order_yxz + * euler_order_zxy + * euler_order_zyx + * + * e.g. euler_order_xyz means compute the column-basis rotation matrix + * equivalent to R_x * R_y * R_z, where R_i is the rotation matrix above + * axis i (the row-basis matrix would be R_z * R_y * R_x). + * + * The derivative is taken with respect to the specified 'axis', which is + * the position of the axis in the triple; e.g. if order = euler_order_xyz, + * then axis = 0 would mean take the derivative with respect to x. Note + * that repeated axes are not currently supported. + */ +template < typename E, class A, class B, class L > void +matrix_rotation_euler_derivatives( + matrix& m, int axis, E angle_0, E angle_1, E angle_2, + EulerOrder order) +{ + typedef matrix matrix_type; + typedef typename matrix_type::value_type value_type; + + /* Checking */ + detail::CheckMatLinear3D(m); + + identity_transform(m); + + size_t i, j, k; + bool odd, repeat; + detail::unpack_euler_order(order, i, j, k, odd, repeat); + if(repeat) throw std::invalid_argument( + "matrix_rotation_euler_derivatives does not support repeated axes"); + + if (odd) { + angle_0 = -angle_0; + angle_1 = -angle_1; + angle_2 = -angle_2; + } + + value_type s0 = std::sin(angle_0); + value_type c0 = std::cos(angle_0); + value_type s1 = std::sin(angle_1); + value_type c1 = std::cos(angle_1); + value_type s2 = std::sin(angle_2); + value_type c2 = std::cos(angle_2); + + value_type s0s2 = s0 * s2; + value_type s0c2 = s0 * c2; + value_type c0s2 = c0 * s2; + value_type c0c2 = c0 * c2; + + if(axis == 0) { + m.set_basis_element(i,i, 0. ); + m.set_basis_element(i,j, 0. ); + m.set_basis_element(i,k, 0. ); + m.set_basis_element(j,i, s1 * c0*c2 + s0*s2); + m.set_basis_element(j,j, s1 * c0*s2 - s0*c2); + m.set_basis_element(j,k, c0 * c1 ); + m.set_basis_element(k,i,-s1 * s0*c2 + c0*s2); + m.set_basis_element(k,j,-s1 * s0*s2 - c0*c2); + m.set_basis_element(k,k,-s0 * c1 ); + } else if(axis == 1) { + m.set_basis_element(i,i,-s1 * c2 ); + m.set_basis_element(i,j,-s1 * s2 ); + m.set_basis_element(i,k,-c1 ); + m.set_basis_element(j,i, c1 * s0*c2 ); + m.set_basis_element(j,j, c1 * s0*s2 ); + m.set_basis_element(j,k,-s0 * s1 ); + m.set_basis_element(k,i, c1 * c0*c2 ); + m.set_basis_element(k,j, c1 * c0*s2 ); + m.set_basis_element(k,k,-c0 * s1 ); + } else if(axis == 2) { + m.set_basis_element(i,i,-c1 * s2 ); + m.set_basis_element(i,j, c1 * c2 ); + m.set_basis_element(i,k, 0. ); + m.set_basis_element(j,i,-s1 * s0*s2 - c0*c2); + m.set_basis_element(j,j, s1 * s0*c2 - c0*s2); + m.set_basis_element(j,k, 0. ); + m.set_basis_element(k,i,-s1 * c0*s2 + s0*c2); + m.set_basis_element(k,j, s1 * c0*c2 + s0*s2); + m.set_basis_element(k,k, 0. ); + } +} + ////////////////////////////////////////////////////////////////////////////// // 3D rotation to align with a vector, multiple vectors, or the view plane ////////////////////////////////////////////////////////////////////////////// diff --git a/src/Moof/cml/mathlib/matrix_translation.h b/src/Moof/cml/mathlib/matrix_translation.h index dadf4c5..664c577 100644 --- a/src/Moof/cml/mathlib/matrix_translation.h +++ b/src/Moof/cml/mathlib/matrix_translation.h @@ -104,6 +104,26 @@ matrix_get_translation(const MatT& m) ); } +/** Get the translation of a 3D affine transform */ +template < class MatT > void +matrix_get_translation( + const MatT& m, + typename MatT::value_type& t1, + typename MatT::value_type& t2, + typename MatT::value_type& t3 + ) +{ + typedef typename MatT::value_type value_type; + typedef vector< value_type, fixed<3> > vector_type; + + /* Checking */ + detail::CheckMatAffine3D(m); + + t1 = m.basis_element(3,0); + t2 = m.basis_element(3,1); + t3 = m.basis_element(3,2); +} + /** Get the translation of a 2D affine transform */ template < class MatT > vector< typename MatT::value_type, fixed<2> > matrix_get_translation_2D(const MatT& m) @@ -117,6 +137,24 @@ matrix_get_translation_2D(const MatT& m) return vector_type(m.basis_element(2,0), m.basis_element(2,1)); } +/** Get the translation of a 2D affine transform */ +template < class MatT > void +matrix_get_translation_2D( + const MatT& m, + typename MatT::value_type& t1, + typename MatT::value_type& t2 + ) +{ + typedef typename MatT::value_type value_type; + typedef vector< value_type, fixed<2> > vector_type; + + /* Checking */ + detail::CheckMatAffine2D(m); + + t1 = m.basis_element(2,0); + t2 = m.basis_element(2,1); +} + ////////////////////////////////////////////////////////////////////////////// // Function for getting the translation of a 3D view matrix ////////////////////////////////////////////////////////////////////////////// diff --git a/src/Moof/cml/mathlib/typedef.h b/src/Moof/cml/mathlib/typedef.h index f34843e..902a331 100644 --- a/src/Moof/cml/mathlib/typedef.h +++ b/src/Moof/cml/mathlib/typedef.h @@ -35,6 +35,11 @@ typedef vector< float, fixed<4> > vector4f; typedef vector< double, fixed<4> > vector4d; /* fixed-size matrices */ + +typedef matrix< int, fixed<2,2> > matrix22i; +typedef matrix< float, fixed<2,2> > matrix22f; +typedef matrix< double, fixed<2,2> > matrix22d; + typedef matrix< int, fixed<2,2>, row_basis, row_major > matrix22i_r; typedef matrix< int, fixed<2,2>, col_basis, col_major > matrix22i_c; typedef matrix< float, fixed<2,2>, row_basis, row_major > matrix22f_r; @@ -42,6 +47,11 @@ typedef matrix< float, fixed<2,2>, col_basis, col_major > matrix22f_c; typedef matrix< double, fixed<2,2>, row_basis, row_major > matrix22d_r; typedef matrix< double, fixed<2,2>, col_basis, col_major > matrix22d_c; + +typedef matrix< int, fixed<3,3> > matrix33i; +typedef matrix< float, fixed<3,3> > matrix33f; +typedef matrix< double, fixed<3,3> > matrix33d; + typedef matrix< int, fixed<3,3>, row_basis, row_major > matrix33i_r; typedef matrix< int, fixed<3,3>, col_basis, col_major > matrix33i_c; typedef matrix< float, fixed<3,3>, row_basis, row_major > matrix33f_r; @@ -49,6 +59,11 @@ typedef matrix< float, fixed<3,3>, col_basis, col_major > matrix33f_c; typedef matrix< double, fixed<3,3>, row_basis, row_major > matrix33d_r; typedef matrix< double, fixed<3,3>, col_basis, col_major > matrix33d_c; + +typedef matrix< int, fixed<4,4> > matrix44i; +typedef matrix< float, fixed<4,4> > matrix44f; +typedef matrix< double, fixed<4,4> > matrix44d; + typedef matrix< int, fixed<4,4>, row_basis, row_major > matrix44i_r; typedef matrix< int, fixed<4,4>, col_basis, col_major > matrix44i_c; typedef matrix< float, fixed<4,4>, row_basis, row_major > matrix44f_r; @@ -56,6 +71,7 @@ typedef matrix< float, fixed<4,4>, col_basis, col_major > matrix44f_c; typedef matrix< double, fixed<4,4>, row_basis, row_major > matrix44d_r; typedef matrix< double, fixed<4,4>, col_basis, col_major > matrix44d_c; + typedef matrix< int, fixed<3,2>, row_basis, row_major > matrix32i_r; typedef matrix< float, fixed<3,2>, row_basis, row_major > matrix32f_r; typedef matrix< double, fixed<3,2>, row_basis, row_major > matrix32d_r; @@ -72,6 +88,7 @@ typedef matrix< int, fixed<3,4>, col_basis, col_major > matrix34i_c; typedef matrix< float, fixed<3,4>, col_basis, col_major > matrix34f_c; typedef matrix< double, fixed<3,4>, col_basis, col_major > matrix34d_c; + /* quaternions */ typedef quaternion,vector_first,negative_cross> quaternionf_n; @@ -81,13 +98,21 @@ typedef quaternion,vector_first,negative_cross> quaterniond_n; typedef quaternion,vector_first,positive_cross> quaterniond_p; +typedef quaternion quaternionf; +typedef quaternion quaterniond; + /* dynamically resizable vectors */ typedef vector< int, dynamic<> > vectori; typedef vector< float, dynamic<> > vectorf; typedef vector< double, dynamic<> > vectord; + /* dynamically resizable matrices */ +typedef matrix< int, dynamic<> > matrixi; +typedef matrix< float, dynamic<> > matrixf; +typedef matrix< double, dynamic<> > matrixd; + typedef matrix< int, dynamic<>, row_basis, row_major > matrixi_r; typedef matrix< int, dynamic<>, col_basis, col_major > matrixi_c; typedef matrix< float, dynamic<>, row_basis, row_major > matrixf_r; @@ -95,6 +120,7 @@ typedef matrix< float, dynamic<>, col_basis, col_major > matrixf_c; typedef matrix< double, dynamic<>, row_basis, row_major > matrixd_r; typedef matrix< double, dynamic<>, col_basis, col_major > matrixd_c; + /* constants */ typedef constants constantsf; typedef constants constantsd; diff --git a/src/Moof/cml/mathlib/vector_ortho.h b/src/Moof/cml/mathlib/vector_ortho.h index 88506f5..3983264 100644 --- a/src/Moof/cml/mathlib/vector_ortho.h +++ b/src/Moof/cml/mathlib/vector_ortho.h @@ -7,7 +7,9 @@ Boost Software License, v1.0 (see cml/LICENSE for details). *-----------------------------------------------------------------------*/ /** @file - * @brief + * + * Functions for orthonormalizing a set of basis vectors in 3D or 2D, and for + * constructing an orthonormal basis given various input parameters. */ #ifndef vector_ortho_h @@ -16,13 +18,14 @@ Boost Software License, v1.0 (see cml/LICENSE for details). #include #include -/* Functions for orthonormalizing a set of basis vector in 3D or 2D, and for - * constructing an orthonormal basis given various input parameters. - */ - namespace cml { -/* Orthonormalize 3 basis vectors in R3. +////////////////////////////////////////////////////////////////////////////// +// Orthonormalization in 3D and 2D +////////////////////////////////////////////////////////////////////////////// + + +/** Orthonormalize 3 basis vectors in R3. * * Called with the default values, this function performs a single Gram- * Schmidt step to orthonormalize the input vectors. By default, the direction @@ -36,11 +39,6 @@ namespace cml { * In most cases, the default arguments can be ignored, leaving only the three * input vectors. */ - -////////////////////////////////////////////////////////////////////////////// -// Orthonormalization in 3D and 2D -////////////////////////////////////////////////////////////////////////////// - template < typename E, class A > void orthonormalize(vector& v0, vector& v1, vector& v2, size_t stable_axis = 2, size_t num_iter = 0, E s = E(1)) @@ -92,7 +90,7 @@ orthonormalize(vector& v0, vector& v1, vector& v2, v2 = v[2]; } -/* Orthonormalize 2 basis vectors in R2 */ +/** Orthonormalize 2 basis vectors in R2 */ template < typename E, class A > void orthonormalize(vector& v0, vector& v1, size_t stable_axis = 0, size_t num_iter = 0, E s = E(1)) @@ -138,27 +136,25 @@ orthonormalize(vector& v0, vector& v1, // Orthonormal basis construction in 3D and 2D ////////////////////////////////////////////////////////////////////////////// -/* This version of orthonormal_basis() ultimately does the work for all +/** This version of orthonormal_basis() ultimately does the work for all * orthonormal_basis_*() functions. Given input vectors 'align' and - * 'reference', and an order 'axis_order_', it constructs an + * 'reference', and an order 'axis_order_\\\', it constructs an * orthonormal basis such that the i'th basis vector is aligned with (parallel * to and pointing in the same direction as) 'align', and the j'th basis * vector is maximally aligned with 'reference'. The k'th basis vector is * chosen such that the basis has a determinant of +1. * - * Note that the algorithm fails when 'align' is nearly parallel to + * @note The algorithm fails when 'align' is nearly parallel to * 'reference'; this should be checked for and handled externally if it's a * case that may occur. - */ - -/* Note: This is an example of the 'non-const argument modification + * + * @internal This is an example of the 'non-const argument modification * invalidates expression' gotcha. If x, y or z were to be assigned to before * we were 'done' with align and reference, and if one of them were the same * object as align or reference, then the algorithm could fail. As is the * basis vectors are assigned at the end of the function from a temporary * array, so all is well. */ - template < class VecT_1, class VecT_2, typename E, class A > void orthonormal_basis( const VecT_1& align, @@ -193,7 +189,7 @@ orthonormal_basis( z = axis[2]; } -/* This version of orthonormal_basis() constructs in arbitrary basis given a +/** This version of orthonormal_basis() constructs in arbitrary basis given a * vector with which to align the i'th basis vector. To avoid the failure * case, the reference vector is always chosen so as to not be parallel to * 'align'. This means the algorithm will always generate a valid basis, which @@ -201,7 +197,6 @@ orthonormal_basis( * basis will likely 'pop' as the alignment vector changes, and so may not be * suitable for billboarding or other similar applications. */ - template < class VecT, typename E, class A > void orthonormal_basis( const VecT& align, @@ -223,7 +218,7 @@ void orthonormal_basis( ); } -/* orthonormal_basis_axial() generates a basis in which the j'th basis vector +/** orthonormal_basis_axial() generates a basis in which the j'th basis vector * is aligned with 'axis' and the i'th basis vector is maximally aligned (as * 'aligned as possible') with 'align'. This can be used for e.g. axial * billboarding for, say, trees or beam effects. @@ -232,11 +227,10 @@ void orthonormal_basis( * of orthonormal_basis(), with the parameters adjusted so that the alignment * is axial. * - * With this algorithm the failure case is when 'align' and 'axis' are nearly - * parallel; if this is likely, it should be checked for and handled - * externally. + * @note With this algorithm the failure case is when 'align' and 'axis' + * are nearly parallel; if this is likely, it should be checked for and + * handled externally. */ - template < class VecT_1, class VecT_2, typename E, class A > void orthonormal_basis_axial( const VecT_1& align, @@ -257,11 +251,11 @@ void orthonormal_basis_axial( detail::swap_axis_order(order)); } -/* orthonormal_basis_viewplane() builds a basis aligned with a viewplane, as +/** orthonormal_basis_viewplane() builds a basis aligned with a viewplane, as * extracted from the input view matrix. The function takes into account the * handedness of the input view matrix and orients the basis accordingly. * - * The generated basis will always be valid. + * @note The generated basis will always be valid. */ template < class MatT, typename E, class A > void orthonormal_basis_viewplane( @@ -309,7 +303,7 @@ void orthonormal_basis_viewplane_RH( view_matrix,x,y,z,right_handed,order); } -/* Build a 2D orthonormal basis. */ +/** Build a 2D orthonormal basis. */ template < class VecT, typename E, class A > void orthonormal_basis_2D( const VecT& align, diff --git a/src/Moof/cml/matrix/dynamic.h b/src/Moof/cml/matrix/dynamic.h index 1362210..4092bfe 100644 --- a/src/Moof/cml/matrix/dynamic.h +++ b/src/Moof/cml/matrix/dynamic.h @@ -205,6 +205,16 @@ class matrix,BasisOrient,Layout> set_basis_element(i,j,s,basis_orient()); } + /** Set the matrix row from the given vector. */ + void set_row(size_t i, const row_vector_type& row) { + for(size_t j = 0; j < this->cols(); ++ j) (*this)(i,j) = row[j]; + } + + /** Set the matrix column from the given vector. */ + void set_col(size_t j, const col_vector_type& col) { + for(size_t i = 0; i < this->rows(); ++ i) (*this)(i,j) = col[i]; + } + public: diff --git a/src/Moof/cml/matrix/external.h b/src/Moof/cml/matrix/external.h index 36c225a..1af9266 100644 --- a/src/Moof/cml/matrix/external.h +++ b/src/Moof/cml/matrix/external.h @@ -221,6 +221,16 @@ class matrix,BasisOrient,Layout> set_basis_element(i,j,s,basis_orient()); } + /** Set the matrix row from the given vector. */ + void set_row(size_t i, const row_vector_type& row) { + for(size_t j = 0; j < this->cols(); ++ j) (*this)(i,j) = row[j]; + } + + /** Set the matrix column from the given vector. */ + void set_col(size_t j, const col_vector_type& col) { + for(size_t i = 0; i < this->rows(); ++ i) (*this)(i,j) = col[i]; + } + public: @@ -440,6 +450,8 @@ class matrix,BasisOrient,Layout> * responsible for doing any necessary memory management. * * @param ptr specify the external pointer. + * @param rows the number of rows in the C array. + * @param cols the number of columns in the C array. * * @throws same as the ArrayType constructor. */ diff --git a/src/Moof/cml/matrix/fixed.h b/src/Moof/cml/matrix/fixed.h index d20ccfa..f35bf1c 100644 --- a/src/Moof/cml/matrix/fixed.h +++ b/src/Moof/cml/matrix/fixed.h @@ -198,6 +198,16 @@ class matrix,BasisOrient,Layout> set_basis_element(i,j,s,basis_orient()); } + /** Set the matrix row from the given vector. */ + void set_row(size_t i, const row_vector_type& row) { + for(size_t j = 0; j < this->cols(); ++ j) (*this)(i,j) = row[j]; + } + + /** Set the matrix column from the given vector. */ + void set_col(size_t j, const col_vector_type& col) { + for(size_t i = 0; i < this->rows(); ++ i) (*this)(i,j) = col[i]; + } + public: diff --git a/src/Moof/cml/matrix/matrix_promotions.h b/src/Moof/cml/matrix/matrix_promotions.h index 18e94bb..8be57cb 100644 --- a/src/Moof/cml/matrix/matrix_promotions.h +++ b/src/Moof/cml/matrix/matrix_promotions.h @@ -33,34 +33,102 @@ struct outer_promote_expects_properly_oriented_args_error; namespace cml { namespace et { -/* Default matrix type promotion template. */ -template struct MatrixPromote; - -/** Type promotion for two matrix types. - * - * @note This always uses the basis orientation of the left-hand matrix. - * @bug This always uses the basis orientation of the left-hand matrix, - * which is not always correct. - */ -template -struct MatrixPromote< cml::matrix, cml::matrix > +/** Promote two types to a matrixt type. */ +template struct MatrixPromote { - /* Promote the arrays: */ - typedef typename ArrayPromote< - typename cml::matrix::array_type, + /* Default matrix type promotion template. */ + template struct MatrixPromoteHelper; + + /** Type promotion for two matrix types. + * + * @note This always uses the basis orientation of the left-hand matrix. + * @bug This always uses the basis orientation of the left-hand matrix, + * which is not always correct. + */ + template + struct MatrixPromoteHelper< + cml::matrix, cml::matrix + > + { + /* Promote the arrays: */ + typedef typename ArrayPromote< + typename cml::matrix::array_type, typename cml::matrix::array_type - >::type promoted_array; + >::type promoted_array; + + /* The deduced matrix result type: */ + typedef cml::matrix< + typename promoted_array::value_type, + typename promoted_array::generator_type, + BO1, + typename promoted_array::layout + > type; + + /* The deduced temporary type: */ + typedef typename type::temporary_type temporary_type; + }; + + /** Type promotion for a matrix and a scalar. */ + template + struct MatrixPromoteHelper, S> + { + /* The deduced matrix result type (the array type is the same): */ + typedef cml::matrix::type, AT, BO, L> type; + + /* The deduced temporary type: */ + typedef typename type::temporary_type temporary_type; + }; + + /** Type promotion for a scalar and a matrix. */ + template + struct MatrixPromoteHelper > + { + /* The deduced matrix result type (the array type is the same): */ + typedef cml::matrix::type, AT, BO, L> type; - /* The deduced matrix result type: */ - typedef cml::matrix< - typename promoted_array::value_type, - typename promoted_array::generator_type, - BO1, - typename promoted_array::layout - > type; + /* The deduced temporary type: */ + typedef typename type::temporary_type temporary_type; + }; + + /** Type promotion for outer product. */ + template + struct MatrixPromoteHelper< cml::vector, cml::vector > + { + typedef cml::vector left_type; + typedef cml::vector right_type; + typedef CML_DEFAULT_BASIS_ORIENTATION basis_orient; + + /* Get matrix size: */ + enum { + array_rows = left_type::array_size, + array_cols = right_type::array_size + }; + + /* Deduce the corresponding matrix types for the vectors: */ + typedef CML_DEFAULT_ARRAY_LAYOUT layout; + typedef typename select_if< + array_rows == -1, dynamic<>, fixed + >::result left_storage; + typedef cml::matrix left_matrix; + + typedef typename select_if< + array_cols == -1, dynamic<>, fixed<1,array_cols> + >::result right_storage; + typedef cml::matrix right_matrix; + + /* Finally, promote the matrix types to get the result: */ + typedef typename et::MatrixPromote::type type; + typedef typename type::temporary_type temporary_type; + }; + + /** Remove const and & from the to-be-promoted types. */ + typedef typename remove_const< + typename remove_reference::type>::type LeftBaseT; + typedef typename remove_const< + typename remove_reference::type>::type RightBaseT; - /* The deduced temporary type: */ + typedef typename MatrixPromoteHelper::type type; typedef typename type::temporary_type temporary_type; }; @@ -75,7 +143,7 @@ struct MatrixPromote2 { typedef typename MatrixPromote< typename Mat1_T::temporary_type, typename Mat2_T::temporary_type - >::temporary_type temporary_type; + >::temporary_type temporary_type; typedef typename temporary_type::value_type value_type; }; @@ -86,9 +154,10 @@ struct MatrixPromote3 typedef typename MatrixPromote< typename Mat1_T::temporary_type, typename MatrixPromote< - typename Mat2_T::temporary_type, typename Mat3_T::temporary_type + typename Mat2_T::temporary_type, + typename Mat3_T::temporary_type >::temporary_type - >::temporary_type temporary_type; + >::temporary_type temporary_type; typedef typename temporary_type::value_type value_type; }; @@ -104,64 +173,11 @@ struct MatrixPromote4 typename Mat3_T::temporary_type, typename Mat4_T::temporary_type >::temporary_type - >::temporary_type - >::temporary_type temporary_type; + >::temporary_type + >::temporary_type temporary_type; typedef typename temporary_type::value_type value_type; }; -/** Type promotion for a matrix and a scalar. */ -template -struct MatrixPromote, S> -{ - /* The deduced matrix result type (the array type is the same): */ - typedef cml::matrix::type, AT, BO, L> type; - - /* The deduced temporary type: */ - typedef typename type::temporary_type temporary_type; -}; - -/** Type promotion for a scalar and a matrix. */ -template -struct MatrixPromote > -{ - /* The deduced matrix result type (the array type is the same): */ - typedef cml::matrix::type, AT, BO, L> type; - - /* The deduced temporary type: */ - typedef typename type::temporary_type temporary_type; -}; - -/** Type promotion for outer product. */ -template -struct MatrixPromote< cml::vector, cml::vector > -{ - typedef cml::vector left_type; - typedef cml::vector right_type; - typedef CML_DEFAULT_BASIS_ORIENTATION basis_orient; - - /* Get matrix size: */ - enum { - array_rows = left_type::array_size, - array_cols = right_type::array_size - }; - - /* Deduce the corresponding matrix types for the vectors: */ - typedef CML_DEFAULT_ARRAY_LAYOUT layout; - typedef typename select_if< - array_rows == -1, dynamic<>, fixed - >::result left_storage; - typedef cml::matrix left_matrix; - - typedef typename select_if< - array_cols == -1, dynamic<>, fixed<1,array_cols> - >::result right_storage; - typedef cml::matrix right_matrix; - - /* Finally, promote the matrix types to get the result: */ - typedef typename et::MatrixPromote::type type; - typedef typename type::temporary_type temporary_type; -}; - } // namespace et } // namespace cml diff --git a/src/Moof/cml/matrix/matrix_unroller.h b/src/Moof/cml/matrix/matrix_unroller.h index 388abcf..ab85945 100644 --- a/src/Moof/cml/matrix/matrix_unroller.h +++ b/src/Moof/cml/matrix/matrix_unroller.h @@ -194,11 +194,18 @@ class MatrixAssignmentUnroller private: /* XXX Blah, a temp. hack to fix the auto-resizing stuff below. */ - matrix_size hack_actual_size(const SrcT& /*src*/, scalar_result_tag) { - return matrix_size(1,1); + matrix_size hack_actual_size( + matrix_type& dest, const SrcT& /*src*/, scalar_result_tag + ) + { + typedef ExprTraits dest_traits; + return dest_traits().size(dest); } - matrix_size hack_actual_size(const SrcT& src, matrix_result_tag) { + matrix_size hack_actual_size( + matrix_type& /*dest*/, const SrcT& src, matrix_result_tag + ) + { typedef ExprTraits src_traits; return src_traits().size(src); } @@ -209,7 +216,7 @@ class MatrixAssignmentUnroller #if defined(CML_AUTOMATIC_MATRIX_RESIZE_ON_ASSIGNMENT) /* Get the size of src. This also causes src to check its size: */ matrix_size N = hack_actual_size( - src, typename src_traits::result_tag()); + dest, src, typename src_traits::result_tag()); /* Set the destination matrix's size: */ dest.resize(N.first,N.second); @@ -224,7 +231,8 @@ class MatrixAssignmentUnroller { return CheckedSize(dest,src,dynamic_size_tag()); } - /* XXX Blah, a temp. hack to fix the auto-resizing stuff below. */ + + public: diff --git a/src/Moof/cml/quaternion/quaternion.h b/src/Moof/cml/quaternion/quaternion.h index 771f34a..6f320f3 100644 --- a/src/Moof/cml/quaternion/quaternion.h +++ b/src/Moof/cml/quaternion/quaternion.h @@ -445,6 +445,13 @@ class quaternion return (*this = *this * e); } + /** Return access to the data as a raw pointer. */ + typename vector_type::pointer data() { return m_q.data(); } + + /** Return access to the data as a const raw pointer. */ + const typename vector_type::pointer data() const { return m_q.data(); } + + /* NOTE: Quaternion division no longer supported, but I'm leaving the code here for reference (Jesse) */ diff --git a/src/Moof/cml/util.h b/src/Moof/cml/util.h index 0fcca00..8517c34 100644 --- a/src/Moof/cml/util.h +++ b/src/Moof/cml/util.h @@ -17,6 +17,13 @@ Boost Software License, v1.0 (see cml/LICENSE for details). #include // For std::rand. #include +#if defined(_MSC_VER) +#pragma push_macro("min") +#pragma push_macro("max") +#undef min +#undef max +#endif + namespace cml { /** Sign of input value as double. */ @@ -34,7 +41,7 @@ T clamp(T value, T min, T max) { /** Test input value for inclusion in [min, max]. */ template < typename T > bool in_range(T value, T min, T max) { - return value >= min && value <= max; + return !(value < min) && !(value > max); } /** Map input value from [min1, max1] to [min2, max2]. */ @@ -63,12 +70,18 @@ T sqrt_safe(T value) { } -/** For convenient squaring of expressions. */ +/** Square a value. */ template < typename T > T sqr(T value) { return value * value; } +/** Cube a value. */ +template < typename T > +T cub(T value) { + return value * value * value; +} + /** Inverse square root. */ template < typename T > T inv_sqrt(T value) { @@ -247,6 +260,30 @@ T length(T x, T y, T z) { return std::sqrt(length_squared(x,y,z)); } +/** Index of maximum of 2 values. */ +template < typename T > +size_t index_of_max(T a, T b) { + return a > b ? 0 : 1; +} + +/** Index of maximum of 2 values by magnitude. */ +template < typename T > +size_t index_of_max_abs(T a, T b) { + return index_of_max(std::fabs(a),std::fabs(b)); +} + +/** Index of minimum of 2 values. */ +template < typename T > +size_t index_of_min(T a, T b) { + return a < b ? 0 : 1; +} + +/** Index of minimum of 2 values by magnitude. */ +template < typename T > +size_t index_of_min_abs(T a, T b) { + return index_of_min(std::fabs(a),std::fabs(b)); +} + /** Index of maximum of 3 values. */ template < typename T > size_t index_of_max(T a, T b, T c) { @@ -320,6 +357,11 @@ T fov_to_zoom(T fov) { } // namespace cml +#if defined(_MSC_VER) +#pragma pop_macro("min") +#pragma pop_macro("max") +#endif + #endif // ------------------------------------------------------------------------- diff --git a/src/Moof/cml/vector/dynamic.h b/src/Moof/cml/vector/dynamic.h index 0fa800c..4fba063 100644 --- a/src/Moof/cml/vector/dynamic.h +++ b/src/Moof/cml/vector/dynamic.h @@ -37,6 +37,9 @@ class vector< Element, dynamic > /* Shorthand for the type of this vector: */ typedef vector vector_type; + /* The vector coordinate type: */ + typedef Element coordinate_type; + /* For integration into the expression template code: */ typedef vector_type expr_type; diff --git a/src/Moof/cml/vector/external.h b/src/Moof/cml/vector/external.h index bc9bc3f..43c4c46 100644 --- a/src/Moof/cml/vector/external.h +++ b/src/Moof/cml/vector/external.h @@ -42,6 +42,9 @@ class vector< Element, external > /* Shorthand for the type of this vector: */ typedef vector vector_type; + /* The vector coordinate type: */ + typedef Element coordinate_type; + /* For integration into the expression template code: */ typedef vector_type expr_type; @@ -74,6 +77,12 @@ class vector< Element, external > typedef cml::et::assignable_tag assignable_tag; + public: + + /** Static constant containing the vector's space dimension. */ + enum { dimension = Size }; + + public: /** Return square of the length. */ diff --git a/src/Moof/cml/vector/fixed.h b/src/Moof/cml/vector/fixed.h index b065938..6ec9d20 100644 --- a/src/Moof/cml/vector/fixed.h +++ b/src/Moof/cml/vector/fixed.h @@ -39,6 +39,9 @@ class vector< Element, fixed > /* Shorthand for the type of this vector: */ typedef vector vector_type; + /* The vector coordinate type: */ + typedef Element coordinate_type; + /* For integration into the expression template code: */ typedef vector_type expr_type; @@ -68,6 +71,12 @@ class vector< Element, fixed > typedef cml::et::assignable_tag assignable_tag; + public: + + /** Static constant containing the vector's space dimension. */ + enum { dimension = Size }; + + public: /** Return square of the length. */ @@ -124,6 +133,17 @@ class vector< Element, fixed > } } + /** Return a subvector by removing element i. + * + * @internal This is horribly inefficient... + */ + subvector_type subvector(size_t i) const { + subvector_type s; + for(size_t m = 0, n = 0; m < this->size(); ++ m) + if(m != i) s[n++] = (*this)[m]; + return s; + }; + public: diff --git a/src/Moof/cml/vector/vector_print.h b/src/Moof/cml/vector/vector_print.h index cbb4764..7106b32 100644 --- a/src/Moof/cml/vector/vector_print.h +++ b/src/Moof/cml/vector/vector_print.h @@ -21,11 +21,9 @@ namespace cml { template inline std::ostream& operator<<(std::ostream& os, const vector& v) { - os << "["; for (size_t i = 0; i < v.size(); ++i) { os << " " << v[i]; } - os << " ]"; return os; } @@ -33,11 +31,9 @@ operator<<(std::ostream& os, const vector& v) template< class XprT > inline std::ostream& operator<<(std::ostream& os, const et::VectorXpr& v) { - os << "["; for (size_t i = 0; i < v.size(); ++i) { os << " " << v[i]; } - os << " ]"; return os; } -- 2.43.0