You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
11 KiB
330 lines
11 KiB
/*===========================================================================*\
|
|
* *
|
|
* OpenFlipper *
|
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
|
* www.openflipper.org *
|
|
* *
|
|
*---------------------------------------------------------------------------*
|
|
* This file is part of OpenFlipper. *
|
|
* *
|
|
* OpenFlipper is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
* published by the Free Software Foundation, either version 3 of *
|
|
* the License, or (at your option) any later version with the *
|
|
* following exceptions: *
|
|
* *
|
|
* If other files instantiate templates or use macros *
|
|
* or inline functions from this file, or you compile this file and *
|
|
* link it with other files to produce an executable, this file does *
|
|
* not by itself cause the resulting executable to be covered by the *
|
|
* GNU Lesser General Public License. This exception does not however *
|
|
* invalidate any other reasons why the executable file might be *
|
|
* covered by the GNU Lesser General Public License. *
|
|
* *
|
|
* OpenFlipper is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU LesserGeneral Public *
|
|
* License along with OpenFlipper. If not, *
|
|
* see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
\*===========================================================================*/
|
|
|
|
/*===========================================================================*\
|
|
* *
|
|
* $Revision: 14430 $ *
|
|
* $Author: ebke $ *
|
|
* $Date: 2012-04-23 12:26:49 +0200 (Mo, 23 Apr 2012) $ *
|
|
* *
|
|
\*===========================================================================*/
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// CLASS Matrix4x4T
|
|
//
|
|
//=============================================================================
|
|
|
|
|
|
#ifndef ACG_MATRIX4X4_HH
|
|
#define ACG_MATRIX4X4_HH
|
|
|
|
|
|
//== INCLUDES =================================================================
|
|
|
|
#include "VectorT.hh"
|
|
#include <math.h>
|
|
#include <iostream>
|
|
|
|
|
|
//== NAMESPACES ==============================================================
|
|
|
|
|
|
namespace ACG {
|
|
|
|
|
|
//== MACROS / HELPERS =========================================================
|
|
|
|
|
|
#define matrixOperator(src, dst, op) { \
|
|
Scalar *_a = dst;\
|
|
const Scalar *_b = src;\
|
|
*_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; \
|
|
*_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; \
|
|
*_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; \
|
|
*_a++ op *_b++; *_a++ op *_b++; *_a++ op *_b++; *_a op *_b ; \
|
|
}
|
|
|
|
#define MAT(m,r,c) ((m)[(r)+((c)<<2)])
|
|
|
|
template<typename Scalar> inline bool checkEpsilon(Scalar x) {
|
|
return fabs(x) < (1e-6);
|
|
}
|
|
|
|
template<> inline bool checkEpsilon(float x) {
|
|
return fabs(x) < (1e-4);
|
|
}
|
|
|
|
|
|
|
|
//== CLASS DEFINITION =========================================================
|
|
|
|
|
|
/** Simple 4x4 Matrix. Inherited by GLMatrix.
|
|
*/
|
|
|
|
template <class Scalar>
|
|
class Matrix4x4T
|
|
{
|
|
public:
|
|
|
|
/// constructor: uninitialized values
|
|
Matrix4x4T() {}
|
|
|
|
/// construct from other matrix type
|
|
template <class OtherScalar>
|
|
inline Matrix4x4T(const Matrix4x4T<OtherScalar> _rhs) {
|
|
operator=(_rhs);
|
|
}
|
|
|
|
/** setup matrix using an array of N*N scalar values.
|
|
elements are ordered 'column first' (like OpenGL) */
|
|
inline Matrix4x4T(const Scalar _array[16]) {
|
|
/*
|
|
* Why aren't we doing a memcpy here?
|
|
*/
|
|
matrixOperator(_array, mat_, =);
|
|
}
|
|
|
|
/// destructor
|
|
~Matrix4x4T() {}
|
|
|
|
|
|
/// assignment from other matrix type
|
|
template<typename otherScalar>
|
|
inline Matrix4x4T<Scalar>& operator=(const Matrix4x4T<otherScalar>& _rhs) {
|
|
for (int i=0; i<4; ++i)
|
|
for (int j=0; j<4; ++j)
|
|
operator()(i,j) = _rhs(i,j);
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
/// access operator (read and write)
|
|
inline Scalar& operator()(unsigned int row, unsigned int col) {
|
|
return MAT(mat_,row,col);
|
|
}
|
|
|
|
/// access operator (read only)
|
|
inline const Scalar& operator()(unsigned int row, unsigned int col) const {
|
|
return MAT(mat_,row,col);
|
|
}
|
|
|
|
|
|
/// compare two matrices (up to some epsilon)
|
|
inline bool operator== (const Matrix4x4T<Scalar>& _rhs) const {
|
|
int i;
|
|
const Scalar *a = mat_;
|
|
const Scalar *b = _rhs.mat_;
|
|
for(i=0;i< 16;i++,a++,b++)
|
|
if(! checkEpsilon( *a - *b ))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/// compare two matrices
|
|
inline bool operator!= (const Matrix4x4T<Scalar>& _rhs) const {
|
|
return !( operator==(_rhs) );
|
|
}
|
|
|
|
|
|
/// self + _rhs
|
|
inline Matrix4x4T operator+ (const Matrix4x4T<Scalar>& _rhs) const {
|
|
Matrix4x4T<Scalar> m(_rhs);
|
|
matrixOperator(mat_, m.mat_, += );
|
|
return m;
|
|
}
|
|
|
|
/// self - _rhs
|
|
inline Matrix4x4T operator- (const Matrix4x4T<Scalar>& _rhs) const {
|
|
Matrix4x4T<Scalar> m(*this);
|
|
matrixOperator(_rhs.mat_, m.mat_, -= );
|
|
return m;
|
|
}
|
|
|
|
/// self * _rhs
|
|
Matrix4x4T operator*(const Matrix4x4T<Scalar>& inst) const;
|
|
|
|
/// self * scalar
|
|
Matrix4x4T operator*(const Scalar& scalar);
|
|
|
|
|
|
/// self += _rhs
|
|
inline Matrix4x4T& operator+= ( const Matrix4x4T<Scalar>& _rhs) {
|
|
matrixOperator(_rhs.mat_, mat_, += );
|
|
return *this;
|
|
}
|
|
|
|
/// self -= _rhs
|
|
inline Matrix4x4T& operator-= ( const Matrix4x4T<Scalar>& _rhs) {
|
|
matrixOperator(_rhs.mat_, mat_, -= );
|
|
return *this;
|
|
}
|
|
|
|
/// self *= _rhs
|
|
Matrix4x4T& operator*= (const Matrix4x4T<Scalar>& _rhs);
|
|
|
|
/// multiply from left: self = _rhs * self
|
|
Matrix4x4T& leftMult(const Matrix4x4T<Scalar>& _rhs);
|
|
|
|
|
|
/// matrix by vector multiplication
|
|
template <typename T>
|
|
inline VectorT<T,4> operator*(const VectorT<T,4>& _v) const;
|
|
|
|
/// transform point (x',y',z',1) = M * (x,y,z,1)
|
|
template <typename T>
|
|
inline VectorT<T,3> transform_point(const VectorT<T,3>& _v) const;
|
|
|
|
/// transform vector (x',y',z',0) = A * (x,y,z,0)
|
|
template <typename T>
|
|
inline VectorT<T,3> transform_vector(const VectorT<T,3>& _v) const;
|
|
|
|
/// sets all elements to zero
|
|
inline void clear();
|
|
|
|
/// setup an identity matrix
|
|
inline void identity();
|
|
|
|
|
|
/// check if the matrix is the identity ( up to an epsilon )
|
|
inline bool is_identity() const {
|
|
int i;
|
|
const Scalar *a = mat_;
|
|
Scalar b = 0.0;
|
|
for(i=0;i< 16;i++,a++,b++) {
|
|
if ( ( i == 0) || ( i == 5 ) || ( i == 10 ) || ( i == 15 ) )
|
|
b = 1.0;
|
|
else
|
|
b = 0.0;
|
|
if(! checkEpsilon( *a - b ))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/// transpose matrix
|
|
inline void transpose();
|
|
|
|
|
|
/// matrix inversion (returns true on success)
|
|
bool invert();
|
|
|
|
Scalar determinant() const {
|
|
return mat_[12] * mat_[9] * mat_[6] * mat_[3] - mat_[8] * mat_[13] * mat_[6] * mat_[3] -
|
|
mat_[12] * mat_[5] * mat_[10] * mat_[3] + mat_[4] * mat_[13] * mat_[10] * mat_[3] +
|
|
mat_[8] * mat_[5] * mat_[14] * mat_[3] - mat_[4] * mat_[9] * mat_[14] * mat_[3] -
|
|
mat_[12] * mat_[9] * mat_[2] * mat_[7] + mat_[8] * mat_[13] * mat_[2] * mat_[7] +
|
|
mat_[12] * mat_[1] * mat_[10] * mat_[7] - mat_[0] * mat_[13] * mat_[10] * mat_[7] -
|
|
mat_[8] * mat_[1] * mat_[14] * mat_[7] + mat_[0] * mat_[9] * mat_[14] * mat_[7] +
|
|
mat_[12] * mat_[5] * mat_[2] * mat_[11] - mat_[4] * mat_[13] * mat_[2] * mat_[11] -
|
|
mat_[12] * mat_[1] * mat_[6] * mat_[11] + mat_[0] * mat_[13] * mat_[6] * mat_[11] +
|
|
mat_[4] * mat_[1] * mat_[14] * mat_[11] - mat_[0] * mat_[5] * mat_[14] * mat_[11] -
|
|
mat_[8] * mat_[5] * mat_[2] * mat_[15] + mat_[4] * mat_[9] * mat_[2] * mat_[15] +
|
|
mat_[8] * mat_[1] * mat_[6] * mat_[15] - mat_[0] * mat_[9] * mat_[6] * mat_[15] -
|
|
mat_[4] * mat_[1] * mat_[10] * mat_[15] + mat_[0] * mat_[5] * mat_[10] * mat_[15];
|
|
}
|
|
|
|
|
|
/** access to data array. not very nice, but in case of 4x4 matrices
|
|
this member can be used to pass matrices to OpenGL
|
|
e.g. glLoadMatrixf(m.get_raw_data()); */
|
|
inline const Scalar* get_raw_data() const { return mat_; }
|
|
inline const Scalar* raw() const { return mat_; }
|
|
inline const Scalar* data() const { return mat_; }
|
|
|
|
protected:
|
|
|
|
Scalar mat_[16];
|
|
};
|
|
|
|
|
|
/// typedef
|
|
typedef Matrix4x4T<float> Matrix4x4f;
|
|
/// typedef
|
|
typedef Matrix4x4T<double> Matrix4x4d;
|
|
|
|
|
|
|
|
|
|
//== IO to/from streams =======================================================
|
|
|
|
|
|
/// output matrix to ostream os
|
|
template<typename Scalar>
|
|
inline std::ostream&
|
|
operator<<(std::ostream& os, const Matrix4x4T<Scalar>& m)
|
|
{
|
|
for(int i=0; i<4; i++)
|
|
{
|
|
for(int j=0; j<4; j++)
|
|
os << m(i,j) << " ";
|
|
os << "\n";
|
|
}
|
|
return os;
|
|
}
|
|
|
|
|
|
/// read the space-separated components of a vector from a stream */
|
|
template<typename Scalar>
|
|
inline std::istream&
|
|
operator>>(std::istream& is, Matrix4x4T<Scalar>& m)
|
|
{
|
|
for(int i=0; i<4; i++)
|
|
for(int j=0; j<4; j++)
|
|
is >> m(i,j);
|
|
return is;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
|
|
#undef matrixOperator
|
|
#undef MAT
|
|
|
|
//=============================================================================
|
|
} // namespace ACG
|
|
//=============================================================================
|
|
#if defined(INCLUDE_TEMPLATES) && !defined(ACG_MATRIX4X4_C)
|
|
#define ACG_MATRIX4X4_TEMPLATES
|
|
#include "Matrix4x4T.cc"
|
|
#endif
|
|
//=============================================================================
|
|
#endif // ACG_MATRIX4X4_HH defined
|
|
//=============================================================================
|
|
|
|
|