• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Xforms.h

Go to the documentation of this file.
00001 // GMTL is (C) Copyright 2001-2010 by Allen Bierbaum
00002 // Distributed under the GNU Lesser General Public License 2.1 with an
00003 // addendum covering inlined code. (See accompanying files LICENSE and
00004 // LICENSE.addendum or http://www.gnu.org/copyleft/lesser.txt)
00005 
00006 #ifndef _GMTL_XFORMS_H_
00007 #define _GMTL_XFORMS_H_
00008 
00009 #include <gmtl/Point.h>
00010 #include <gmtl/Vec.h>
00011 #include <gmtl/Matrix.h>
00012 #include <gmtl/MatrixOps.h>
00013 #include <gmtl/Quat.h>
00014 #include <gmtl/QuatOps.h>
00015 #include <gmtl/Ray.h>
00016 #include <gmtl/LineSeg.h>
00017 #include <gmtl/Util/StaticAssert.h>
00018 
00019 namespace gmtl
00020 {
00039    template <typename DATA_TYPE>
00040    inline VecBase<DATA_TYPE, 3>& xform( VecBase<DATA_TYPE, 3>& result, const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
00041    {
00042       // check preconditions...
00043       gmtlASSERT( Math::isEqual( length( rot ), (DATA_TYPE)1.0, (DATA_TYPE)0.0001 ) && "must pass a rotation quaternion to xform(result,quat,vec) - by definition, a rotation quaternion is normalized).  if you need non-rotation quaternion support, let us know." );
00044 
00045       // easiest to write and understand (slowest too)
00046       //return result_vec = makeVec( rot * makePure( vector ) * makeConj( rot ) );
00047 
00048       // completely hand expanded
00049       // (faster by 28% in gcc 2.96 debug mode.)
00050       // (faster by 35% in gcc 2.96 opt3 mode (78% for doubles))
00051       Quat<DATA_TYPE> rot_conj( -rot[Xelt], -rot[Yelt], -rot[Zelt], rot[Welt] );
00052       Quat<DATA_TYPE> pure( vector[0], vector[1], vector[2], (DATA_TYPE)0.0 );
00053       Quat<DATA_TYPE> temp(
00054          pure[Welt]*rot_conj[Xelt] + pure[Xelt]*rot_conj[Welt] + pure[Yelt]*rot_conj[Zelt] - pure[Zelt]*rot_conj[Yelt],
00055          pure[Welt]*rot_conj[Yelt] + pure[Yelt]*rot_conj[Welt] + pure[Zelt]*rot_conj[Xelt] - pure[Xelt]*rot_conj[Zelt],
00056          pure[Welt]*rot_conj[Zelt] + pure[Zelt]*rot_conj[Welt] + pure[Xelt]*rot_conj[Yelt] - pure[Yelt]*rot_conj[Xelt],
00057          pure[Welt]*rot_conj[Welt] - pure[Xelt]*rot_conj[Xelt] - pure[Yelt]*rot_conj[Yelt] - pure[Zelt]*rot_conj[Zelt] );
00058 
00059       result.set(
00060          rot[Welt]*temp[Xelt] + rot[Xelt]*temp[Welt] + rot[Yelt]*temp[Zelt] - rot[Zelt]*temp[Yelt],
00061          rot[Welt]*temp[Yelt] + rot[Yelt]*temp[Welt] + rot[Zelt]*temp[Xelt] - rot[Xelt]*temp[Zelt],
00062          rot[Welt]*temp[Zelt] + rot[Zelt]*temp[Welt] + rot[Xelt]*temp[Yelt] - rot[Yelt]*temp[Xelt] );
00063       return result;
00064    }
00065 
00073    template <typename DATA_TYPE>
00074    inline VecBase<DATA_TYPE, 3> operator*( const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
00075    {
00076       VecBase<DATA_TYPE, 3> temporary;
00077       return xform( temporary, rot, vector );
00078    }
00079 
00080 
00087    template <typename DATA_TYPE>
00088    inline VecBase<DATA_TYPE, 3> operator*=(VecBase<DATA_TYPE, 3>& vector, const Quat<DATA_TYPE>& rot)
00089    {
00090       VecBase<DATA_TYPE, 3> temporary = vector;
00091       return xform( vector, rot, temporary);
00092    }
00093 
00094 
00112    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00113    inline Vec<DATA_TYPE, COLS>& xform( Vec<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
00114    {
00115       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00116 
00117       // reset vec to zero...
00118       result = Vec<DATA_TYPE, COLS>();
00119 
00120       for (unsigned iRow = 0; iRow < ROWS; ++iRow)
00121       for (unsigned iCol = 0; iCol < COLS; ++iCol)
00122          result[iRow] += matrix( iRow, iCol ) * vector[iCol];
00123 
00124       return result;
00125    }
00126 
00127 
00138    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00139    inline Vec<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
00140    {
00141       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00142       Vec<DATA_TYPE, COLS> temporary;
00143       return xform( temporary, matrix, vector );
00144    }
00145 
00146 
00147 
00148 
00157    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned VEC_SIZE>
00158    inline Vec<DATA_TYPE, VEC_SIZE>& xform( Vec<DATA_TYPE, VEC_SIZE >& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, VEC_SIZE >& vector )
00159    {
00160       GMTL_STATIC_ASSERT( VEC_SIZE == COLS - 1, Vec_of_wrong_size_for_xform );
00161       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00162 
00163       // copy the point to the correct size.
00164       Vec<DATA_TYPE, COLS> temp_vector, temp_result;
00165       for (unsigned x = 0; x < VEC_SIZE; ++x)
00166          temp_vector[x] = vector[x];
00167       temp_vector[COLS-1] = (DATA_TYPE)0.0; // by definition of a vector, set the last unspecified elt to 0.0
00168 
00169       // transform it.
00170       xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_vector );
00171 
00172       // convert result back to vec<DATA_TYPE, VEC_SIZE>
00173       // some matrices will make the W param large even if this is a true vector,
00174       // we'll need to redistribute it to the other elts if W param is non-zero
00175       if (Math::isEqual( temp_result[VEC_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
00176       {
00177          DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[VEC_SIZE];
00178          for (unsigned x = 0; x < VEC_SIZE; ++x)
00179             result[x] = temp_result[x] * w_coord_div;
00180       }
00181       else
00182       {
00183          for (unsigned x = 0; x < VEC_SIZE; ++x)
00184             result[x] = temp_result[x];
00185       }
00186 
00187       return result;
00188    }
00189 
00198    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00199    inline Vec<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS_MINUS_ONE>& vector )
00200    {
00201       Vec<DATA_TYPE, COLS_MINUS_ONE> temporary;
00202       return xform( temporary, matrix, vector );
00203    }
00204 
00221    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00222    inline Point<DATA_TYPE, COLS>& xform( Point<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
00223    {
00224       // do a standard [m x k] by [k x n] matrix multiplication (n == 1).
00225 
00226       // reset point to zero...
00227       result = Point<DATA_TYPE, COLS>();
00228 
00229       for (unsigned iRow = 0; iRow < ROWS; ++iRow)
00230       for (unsigned iCol = 0; iCol < COLS; ++iCol)
00231          result[iRow] += matrix( iRow, iCol ) * point[iCol];
00232 
00233       return result;
00234    }
00235 
00244    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00245    inline Point<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
00246    {
00247       Point<DATA_TYPE, COLS> temporary;
00248       return xform( temporary, matrix, point );
00249    }
00250 
00251 
00252 
00253 
00263    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned PNT_SIZE>
00264    inline Point<DATA_TYPE, PNT_SIZE>& xform( Point<DATA_TYPE, PNT_SIZE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, PNT_SIZE>& point )
00265    {
00266       //gmtlSERT( PNT_SIZE == COLS - 1 && "The precondition of this method is that the vector size must be one less than the number of columns in the matrix.  eg. if Mat<n,k>, then Vec<k-1>." );
00267       GMTL_STATIC_ASSERT( PNT_SIZE == COLS-1, Point_not_of_size_mat_col_minus_1_as_required_for_xform);
00268 
00269       // copy the point to the correct size.
00270       Point<DATA_TYPE, PNT_SIZE+1> temp_point, temp_result;
00271       for (unsigned x = 0; x < PNT_SIZE; ++x)
00272          temp_point[x] = point[x];
00273       temp_point[PNT_SIZE] = (DATA_TYPE)1.0; // by definition of a point, set the last unspecified elt to 1.0
00274 
00275       // transform it.
00276       xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_point );
00277 
00278       // convert result back to pnt<DATA_TYPE, PNT_SIZE>
00279       // some matrices will make the W param large even if this is a true vector,
00280       // we'll need to redistribute it to the other elts if W param is non-zero
00281       if (Math::isEqual( temp_result[PNT_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
00282       {
00283          DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[PNT_SIZE];
00284          for (unsigned x = 0; x < PNT_SIZE; ++x)
00285             result[x] = temp_result[x] * w_coord_div;
00286       }
00287       else
00288       {
00289          for (unsigned x = 0; x < PNT_SIZE; ++x)
00290             result[x] = temp_result[x];
00291       }
00292 
00293       return result;
00294    }
00295 
00304    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00305    inline Point<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS_MINUS_ONE>& point )
00306    {
00307       Point<DATA_TYPE, COLS_MINUS_ONE> temporary;
00308       return xform( temporary, matrix, point );
00309    }
00310 
00318    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00319    inline Point<DATA_TYPE, COLS> operator*( const Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
00320    {
00321       Point<DATA_TYPE, COLS> temporary;
00322       return xform( temporary, matrix, point );
00323    }
00324 
00325 
00333    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00334    inline Point<DATA_TYPE, COLS> operator*=(Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix)
00335    {
00336       Point<DATA_TYPE, COLS> temporary = point;
00337       return xform( point, matrix, temporary);
00338    }
00339 
00348    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00349    inline Point<DATA_TYPE, COLS_MINUS_ONE>& operator*=( Point<DATA_TYPE, COLS_MINUS_ONE>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
00350    {
00351       Point<DATA_TYPE, COLS_MINUS_ONE> temporary = point;
00352       return xform( point, matrix, temporary);
00353    }
00354 
00355 
00366    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00367    inline Ray<DATA_TYPE>& xform( Ray<DATA_TYPE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Ray<DATA_TYPE>& ray )
00368    {
00369       gmtl::Point<DATA_TYPE, 3> pos;
00370       gmtl::Vec<DATA_TYPE, 3> dir;
00371       result.setOrigin( xform( pos, matrix, ray.getOrigin() ) );
00372       result.setDir( xform( dir, matrix, ray.getDir() ) );
00373       return result;
00374    }
00375 
00383    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00384    inline Ray<DATA_TYPE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Ray<DATA_TYPE>& ray )
00385    {
00386       Ray<DATA_TYPE> temporary;
00387       return xform( temporary, matrix, ray );
00388    }
00389 
00390 
00398    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00399    inline Ray<DATA_TYPE>& operator*=( Ray<DATA_TYPE>& ray, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
00400    {
00401       Ray<DATA_TYPE> temporary = ray;
00402       return xform( ray, matrix, temporary);
00403    }
00404 
00413    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00414    inline LineSeg<DATA_TYPE>& xform( LineSeg<DATA_TYPE>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const LineSeg<DATA_TYPE>& seg )
00415    {
00416       gmtl::Point<DATA_TYPE, 3> pos;
00417       gmtl::Vec<DATA_TYPE, 3> dir;
00418       result.setOrigin( xform( pos, matrix, seg.getOrigin() ) );
00419       result.setDir( xform( dir, matrix, seg.getDir() ) );
00420       return result;
00421    }
00422 
00430    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00431    inline LineSeg<DATA_TYPE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const LineSeg<DATA_TYPE>& seg )
00432    {
00433       LineSeg<DATA_TYPE> temporary;
00434       return xform( temporary, matrix, seg );
00435    }
00436 
00437 
00445    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00446    inline LineSeg<DATA_TYPE>& operator*=( LineSeg<DATA_TYPE>& seg, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
00447    {
00448       LineSeg<DATA_TYPE> temporary = seg;
00449       return xform( seg, matrix, temporary);
00450    }
00451 
00452 
00453 
00454 
00455    // old xform stuff...
00456 /*
00457 // XXX: Assuming that there is no projective portion to the matrix or homogeneous coord
00458 // NOTE: It is a vec, so we don't deal with the translation
00459 Vec3 operator*(const Matrix& mat, const Vec3& vec)
00460 {
00461 
00462    Vec3 ret_vec;
00463    for(int iRow=0;iRow<3;iRow++)
00464    {
00465       ret_vec[iRow] = (vec[0]* (mat[0][iRow]))
00466                     + (vec[1]* (mat[1][iRow]))
00467                     + (vec[2]* (mat[2][iRow]));
00468    }
00469    return ret_vec;
00470 }
00471 
00472 // XXX: Assuming no projective or homogeneous coord to the mat
00473 Point3 operator*(const Matrix& mat, const Point3& point)
00474 {
00475    Point3 ret_pt;
00476    for(int iRow=0;iRow<3;iRow++)
00477    {
00478       ret_pt[iRow] = (point[0]* (mat[0][iRow]))
00479                    + (point[1]* (mat[1][iRow]))
00480                    + (point[2]* (mat[2][iRow]))
00481                    + (mat[3][iRow]);
00482    }
00483    return ret_pt;
00484 }
00485 
00486 // Xform an OOB by a matrix
00487 // NOTE: This will NOT work if the matrix has shear or scale
00488 OOBox operator*(const Matrix& mat, const OOBox& box)
00489 {
00490    OOBox ret_box;
00491 
00492    ret_box.center() = mat * box.center();
00493 
00494    ret_box.axis(0) = mat * ret_box.axis(0);
00495    ret_box.axis(1) = mat * ret_box.axis(1);
00496    ret_box.axis(2) = mat * ret_box.axis(2);
00497 
00498    ret_box.halfLen(0) = box.halfLen(0);
00499    ret_box.halfLen(1) = box.halfLen(1);
00500    ret_box.halfLen(2) = box.halfLen(2);
00501 
00502    return ret_box;
00503 }
00504 */
00505 
00506 }
00507 
00508 #endif

Generated on Sun Sep 19 2010 14:35:14 for GenericMathTemplateLibrary by  doxygen 1.7.1