Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Xforms.h

Go to the documentation of this file.
00001 /************************************************************** ggt-head beg
00002  *
00003  * GGT: Generic Graphics Toolkit
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile: Xforms.h,v $
00010  * Date modified: $Date: 2003/03/10 19:22:02 $
00011  * Version:       $Revision: 1.31 $
00012  * -----------------------------------------------------------------
00013  *
00014  *********************************************************** ggt-head end */
00015 /*************************************************************** ggt-cpr beg
00016 *
00017 * GGT: The Generic Graphics Toolkit
00018 * Copyright (C) 2001,2002 Allen Bierbaum
00019 *
00020 * This library is free software; you can redistribute it and/or
00021 * modify it under the terms of the GNU Lesser General Public
00022 * License as published by the Free Software Foundation; either
00023 * version 2.1 of the License, or (at your option) any later version.
00024 *
00025 * This library is distributed in the hope that it will be useful,
00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00028 * Lesser General Public License for more details.
00029 *
00030 * You should have received a copy of the GNU Lesser General Public
00031 * License along with this library; if not, write to the Free Software
00032 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033 *
00034  ************************************************************ ggt-cpr end */
00035 #ifndef _GMTL_XFORMS_H_
00036 #define _GMTL_XFORMS_H_
00037 
00038 #include <gmtl/Point.h>
00039 #include <gmtl/Vec.h>
00040 #include <gmtl/Matrix.h>
00041 #include <gmtl/MatrixOps.h>
00042 #include <gmtl/Quat.h>
00043 #include <gmtl/QuatOps.h>
00044 #include <gmtl/Generate.h>
00045 
00046 namespace gmtl
00047 {
00066    template <typename DATA_TYPE>
00067    inline VecBase<DATA_TYPE, 3>& xform( VecBase<DATA_TYPE, 3>& result, const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
00068    {
00069       // check preconditions...
00070       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." );
00071 
00072       // easiest to write and understand (slowest too)
00073       //return result_vec = makeVec( rot * makePure( vector ) * makeConj( rot ) );
00074 
00075       // completely hand expanded
00076       // (faster by 28% in gcc 2.96 debug mode.)
00077       // (faster by 35% in gcc 2.96 opt3 mode (78% for doubles))
00078       Quat<DATA_TYPE> rot_conj( -rot[Xelt], -rot[Yelt], -rot[Zelt], rot[Welt] );
00079       Quat<DATA_TYPE> pure( vector[0], vector[1], vector[2], (DATA_TYPE)0.0 );
00080       Quat<DATA_TYPE> temp(
00081          pure[Welt]*rot_conj[Xelt] + pure[Xelt]*rot_conj[Welt] + pure[Yelt]*rot_conj[Zelt] - pure[Zelt]*rot_conj[Yelt],
00082          pure[Welt]*rot_conj[Yelt] + pure[Yelt]*rot_conj[Welt] + pure[Zelt]*rot_conj[Xelt] - pure[Xelt]*rot_conj[Zelt],
00083          pure[Welt]*rot_conj[Zelt] + pure[Zelt]*rot_conj[Welt] + pure[Xelt]*rot_conj[Yelt] - pure[Yelt]*rot_conj[Xelt],
00084          pure[Welt]*rot_conj[Welt] - pure[Xelt]*rot_conj[Xelt] - pure[Yelt]*rot_conj[Yelt] - pure[Zelt]*rot_conj[Zelt] );
00085 
00086       result.set(
00087          rot[Welt]*temp[Xelt] + rot[Xelt]*temp[Welt] + rot[Yelt]*temp[Zelt] - rot[Zelt]*temp[Yelt],
00088          rot[Welt]*temp[Yelt] + rot[Yelt]*temp[Welt] + rot[Zelt]*temp[Xelt] - rot[Xelt]*temp[Zelt],
00089          rot[Welt]*temp[Zelt] + rot[Zelt]*temp[Welt] + rot[Xelt]*temp[Yelt] - rot[Yelt]*temp[Xelt] );
00090       return result;
00091    }
00092 
00100    template <typename DATA_TYPE>
00101    inline VecBase<DATA_TYPE, 3> operator*( const Quat<DATA_TYPE>& rot, const VecBase<DATA_TYPE, 3>& vector )
00102    {
00103       VecBase<DATA_TYPE, 3> temporary;
00104       return xform( temporary, rot, vector );
00105    }
00106 
00107 
00114    template <typename DATA_TYPE>
00115    inline VecBase<DATA_TYPE, 3> operator*=(VecBase<DATA_TYPE, 3>& vector, const Quat<DATA_TYPE>& rot)
00116    {
00117       VecBase<DATA_TYPE, 3> temporary = vector;
00118       return xform( vector, rot, temporary);
00119    }
00120 
00121 
00139    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00140    inline Vec<DATA_TYPE, COLS>& xform( Vec<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
00141    {
00142       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00143 
00144       // reset vec to zero...
00145       result = Vec<DATA_TYPE, COLS>();
00146 
00147       for (unsigned iRow = 0; iRow < ROWS; ++iRow)
00148       for (unsigned iCol = 0; iCol < COLS; ++iCol)
00149          result[iRow] += matrix( iRow, iCol ) * vector[iCol];
00150 
00151       return result;
00152    }
00153 
00154 
00165    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00166    inline Vec<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS>& vector )
00167    {
00168       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00169       Vec<DATA_TYPE, COLS> temporary;
00170       return xform( temporary, matrix, vector );
00171    }
00172 
00173 
00174 
00175 
00184    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned VEC_SIZE>
00185    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 )
00186    {
00187       gmtlASSERT( VEC_SIZE == COLS - 1 );
00188       // do a standard [m x k] by [k x n] matrix multiplication (where n == 0).
00189 
00190       // copy the point to the correct size.
00191       Vec<DATA_TYPE, COLS> temp_vector, temp_result;
00192       for (unsigned x = 0; x < VEC_SIZE; ++x)
00193          temp_vector[x] = vector[x];
00194       temp_vector[COLS-1] = (DATA_TYPE)0.0; // by definition of a vector, set the last unspecified elt to 0.0
00195 
00196       // transform it.
00197       xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_vector );
00198 
00199       // convert result back to vec<DATA_TYPE, VEC_SIZE>
00200       // some matrices will make the W param large even if this is a true vector,
00201       // we'll need to redistribute it to the other elts if W param is non-zero
00202       if (Math::isEqual( temp_result[VEC_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
00203       {
00204          DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[VEC_SIZE];
00205          for (unsigned x = 0; x < VEC_SIZE; ++x)
00206             result[x] = temp_result[x] * w_coord_div;
00207       }
00208       else
00209       {
00210          for (unsigned x = 0; x < VEC_SIZE; ++x)
00211             result[x] = temp_result[x];
00212       }
00213 
00214       return result;
00215    }
00216 
00225    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00226    inline Vec<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Vec<DATA_TYPE, COLS_MINUS_ONE>& vector )
00227    {
00228       Vec<DATA_TYPE, COLS_MINUS_ONE> temporary;
00229       return xform( temporary, matrix, vector );
00230    }
00231 
00248    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00249    inline Point<DATA_TYPE, COLS>& xform( Point<DATA_TYPE, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
00250    {
00251       // do a standard [m x k] by [k x n] matrix multiplication (n == 1).
00252 
00253       // reset point to zero...
00254       result = Point<DATA_TYPE, COLS>();
00255 
00256       for (unsigned iRow = 0; iRow < ROWS; ++iRow)
00257       for (unsigned iCol = 0; iCol < COLS; ++iCol)
00258          result[iRow] += matrix( iRow, iCol ) * point[iCol];
00259 
00260       return result;
00261    }
00262 
00271    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00272    inline Point<DATA_TYPE, COLS> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS>& point )
00273    {
00274       Point<DATA_TYPE, COLS> temporary;
00275       return xform( temporary, matrix, point );
00276    }
00277 
00278 
00279 
00280 
00290    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned PNT_SIZE>
00291    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 )
00292    {
00293       gmtlASSERT( 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>." );
00294 
00295       // copy the point to the correct size.
00296       Point<DATA_TYPE, PNT_SIZE+1> temp_point, temp_result;
00297       for (unsigned x = 0; x < PNT_SIZE; ++x)
00298          temp_point[x] = point[x];
00299       temp_point[PNT_SIZE] = (DATA_TYPE)1.0; // by definition of a point, set the last unspecified elt to 1.0
00300 
00301       // transform it.
00302       xform<DATA_TYPE, ROWS, COLS>( temp_result, matrix, temp_point );
00303 
00304       // convert result back to pnt<DATA_TYPE, PNT_SIZE>
00305       // some matrices will make the W param large even if this is a true vector,
00306       // we'll need to redistribute it to the other elts if W param is non-zero
00307       if (Math::isEqual( temp_result[PNT_SIZE], (DATA_TYPE)0, (DATA_TYPE)0.0001 ) == false)
00308       {
00309          DATA_TYPE w_coord_div = DATA_TYPE( 1.0 ) / temp_result[PNT_SIZE];
00310          for (unsigned x = 0; x < PNT_SIZE; ++x)
00311             result[x] = temp_result[x] * w_coord_div;
00312       }
00313       else
00314       {
00315          for (unsigned x = 0; x < PNT_SIZE; ++x)
00316             result[x] = temp_result[x];
00317       }
00318 
00319       return result;
00320    }
00321 
00330    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00331    inline Point<DATA_TYPE, COLS_MINUS_ONE> operator*( const Matrix<DATA_TYPE, ROWS, COLS>& matrix, const Point<DATA_TYPE, COLS_MINUS_ONE>& point )
00332    {
00333       Point<DATA_TYPE, COLS_MINUS_ONE> temporary;
00334       return xform( temporary, matrix, point );
00335    }
00336 
00344    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00345    inline Point<DATA_TYPE, COLS> operator*( const Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix )
00346    {
00347       Point<DATA_TYPE, COLS> temporary;
00348       return xform( temporary, matrix, point );
00349    }
00350 
00351 
00359    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00360    inline Point<DATA_TYPE, COLS> operator*=(Point<DATA_TYPE, COLS>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix)
00361    {
00362       Point<DATA_TYPE, COLS> temporary = point;
00363       return xform( point, matrix, temporary);
00364    }
00365 
00374    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS, unsigned COLS_MINUS_ONE>
00375    inline Point<DATA_TYPE, COLS_MINUS_ONE> operator*=(Point<DATA_TYPE, COLS_MINUS_ONE>& point, const Matrix<DATA_TYPE, ROWS, COLS>& matrix)
00376    {
00377       Point<DATA_TYPE, COLS_MINUS_ONE> temporary = point;
00378       return xform( point, matrix, temporary);
00379    }
00380 
00381 
00385    // old xform stuff...
00386 /*
00387 // XXX: Assuming that there is no projective portion to the matrix or homogeneous coord
00388 // NOTE: It is a vec, so we don't deal with the translation
00389 Vec3 operator*(const Matrix& mat, const Vec3& vec)
00390 {
00391 
00392    Vec3 ret_vec;
00393    for(int iRow=0;iRow<3;iRow++)
00394    {
00395       ret_vec[iRow] = (vec[0]* (mat[0][iRow]))
00396                     + (vec[1]* (mat[1][iRow]))
00397                     + (vec[2]* (mat[2][iRow]));
00398    }
00399    return ret_vec;
00400 }
00401 
00402 // XXX: Assuming no projective or homogeneous coord to the mat
00403 Point3 operator*(const Matrix& mat, const Point3& point)
00404 {
00405    Point3 ret_pt;
00406    for(int iRow=0;iRow<3;iRow++)
00407    {
00408       ret_pt[iRow] = (point[0]* (mat[0][iRow]))
00409                    + (point[1]* (mat[1][iRow]))
00410                    + (point[2]* (mat[2][iRow]))
00411                    + (mat[3][iRow]);
00412    }
00413    return ret_pt;
00414 }
00415 
00416 // Xform an OOB by a matrix
00417 // NOTE: This will NOT work if the matrix has shear or scale
00418 OOBox operator*(const Matrix& mat, const OOBox& box)
00419 {
00420    OOBox ret_box;
00421 
00422    ret_box.center() = mat * box.center();
00423 
00424    ret_box.axis(0) = mat * ret_box.axis(0);
00425    ret_box.axis(1) = mat * ret_box.axis(1);
00426    ret_box.axis(2) = mat * ret_box.axis(2);
00427 
00428    ret_box.halfLen(0) = box.halfLen(0);
00429    ret_box.halfLen(1) = box.halfLen(1);
00430    ret_box.halfLen(2) = box.halfLen(2);
00431 
00432    return ret_box;
00433 }
00434 */
00435 
00436 };
00437 
00438 #endif

Generated on Mon Apr 7 15:28:55 2003 for GenericMathTemplateLibrary by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002