33 #ifndef __VMML__MATRIX__HPP__
34 #define __VMML__MATRIX__HPP__
36 #include <vmmlib/enable_if.hpp>
37 #include <vmmlib/types.hpp>
51 template<
size_t R,
size_t C,
typename T >
class Matrix
64 Matrix(
const T* begin,
const T* end );
70 explicit Matrix(
const std::vector< T >&
data );
84 typename enable_if< R == S+1 && C == S+1 && S == 3 >::type* = 0 );
93 typename enable_if< R == S+1 && C == S+1 && S == 3 >::type* = 0 );
104 bool equals(
const Matrix& other,
105 T tolerance = std::numeric_limits< T >::epsilon( ))
const;
117 #ifdef VMMLIB_USE_CXX03
118 template<
size_t O,
size_t P >
119 typename enable_if< R == C && O == P && R == O >::type*
121 template<
size_t O,
size_t P,
122 typename =
typename enable_if< R == C && O == P && R == O >::type >
128 Matrix
operator+(
const Matrix& other )
const;
131 Matrix
operator-(
const Matrix& other )
const;
149 T&
operator()(
size_t rowIndex,
size_t colIndex );
152 T
operator()(
size_t rowIndex,
size_t colIndex )
const;
158 template<
size_t O,
size_t P >
160 typename enable_if< O <= R && P <= C >::type* = 0 )
const;
175 template<
size_t P,
size_t Q >
183 void operator=(
const std::vector< T >& data );
201 vector< C-1, T > getTranslation()
const;
213 typename enable_if< R == S+1 && C == S+1 && S == 3 >::type* = 0 )
const;
223 template<
size_t O,
size_t P >
227 template<
size_t O,
size_t P >
228 typename enable_if< O == P && R == C && O == R && R >= 2 >::type*
232 template<
size_t O,
size_t P >
238 template<
typename TT >
240 typename enable_if< R == C && R == 4, TT >::type* = 0 );
242 template<
typename TT >
244 typename enable_if< R == C && R == 4, TT >::type* = 0 );
246 template<
typename TT >
248 typename enable_if< R == C && R == 4, TT >::type* = 0 );
250 template<
typename TT >
252 typename enable_if< R == C && R == 4, TT >::type* = 0 );
254 template<
typename TT >
256 typename enable_if< R == C && R == 4, TT >::type* = 0 );
258 template<
typename TT >
260 typename enable_if< R == C && R == 4, TT >::type* = 0 );
262 template<
typename TT >
264 typename enable_if< R == C && R == 4, TT >::type* = 0 );
266 template<
typename TT >
268 typename enable_if< R == C && R == 4, TT >::type* = 0 );
271 friend std::ostream& operator << ( std::ostream& os,
274 const std::ios::fmtflags flags = os.flags();
275 const int prec = os.precision();
277 os.setf( std::ios::right, std::ios::adjustfield );
280 for(
size_t rowIndex = 0; rowIndex< R; ++rowIndex )
283 for(
size_t colIndex = 0; colIndex < C; ++colIndex )
285 os << std::setw(10) << matrix( rowIndex, colIndex ) <<
" ";
287 os <<
"|" << std::endl;
289 os.precision( prec );
298 #include <vmmlib/quaternion.hpp>
299 #include <vmmlib/vector.hpp>
305 template<
typename T >
306 inline T computeDeterminant(
const Matrix< 1, 1, T >& matrix_ )
308 return matrix_.array[ 0 ];
311 template<
typename T >
312 inline T computeDeterminant(
const Matrix< 2, 2, T >& matrix_ )
314 return matrix_( 0, 0 ) * matrix_( 1, 1 ) - matrix_( 0, 1 ) * matrix_( 1, 0);
317 template<
typename T >
318 inline T computeDeterminant(
const Matrix< 3, 3, T >& m_ )
320 return m_( 0,0 ) * ( m_( 1,1 ) * m_( 2,2 ) - m_( 1,2 ) * m_( 2,1 )) +
321 m_( 0,1 ) * ( m_( 1,2 ) * m_( 2,0 ) - m_( 1,0 ) * m_( 2,2 )) +
322 m_( 0,2 ) * ( m_( 1,0 ) * m_( 2,1 ) - m_( 1,1 ) * m_( 2,0 ));
325 template<
typename T >
326 inline T computeDeterminant(
const Matrix< 4, 4, T >& m )
328 return m( 0, 3 ) * m( 1, 2 ) * m( 2, 1 ) * m( 3, 0 )
329 - m( 0, 2 ) * m( 1, 3 ) * m( 2, 1 ) * m( 3, 0 )
330 - m( 0, 3 ) * m( 1, 1 ) * m( 2, 2 ) * m( 3, 0 )
331 + m( 0, 1 ) * m( 1, 3 ) * m( 2, 2 ) * m( 3, 0 )
332 + m( 0, 2 ) * m( 1, 1 ) * m( 2, 3 ) * m( 3, 0 )
333 - m( 0, 1 ) * m( 1, 2 ) * m( 2, 3 ) * m( 3, 0 )
334 - m( 0, 3 ) * m( 1, 2 ) * m( 2, 0 ) * m( 3, 1 )
335 + m( 0, 2 ) * m( 1, 3 ) * m( 2, 0 ) * m( 3, 1 )
336 + m( 0, 3 ) * m( 1, 0 ) * m( 2, 2 ) * m( 3, 1 )
337 - m( 0, 0 ) * m( 1, 3 ) * m( 2, 2 ) * m( 3, 1 )
338 - m( 0, 2 ) * m( 1, 0 ) * m( 2, 3 ) * m( 3, 1 )
339 + m( 0, 0 ) * m( 1, 2 ) * m( 2, 3 ) * m( 3, 1 )
340 + m( 0, 3 ) * m( 1, 1 ) * m( 2, 0 ) * m( 3, 2 )
341 - m( 0, 1 ) * m( 1, 3 ) * m( 2, 0 ) * m( 3, 2 )
342 - m( 0, 3 ) * m( 1, 0 ) * m( 2, 1 ) * m( 3, 2 )
343 + m( 0, 0 ) * m( 1, 3 ) * m( 2, 1 ) * m( 3, 2 )
344 + m( 0, 1 ) * m( 1, 0 ) * m( 2, 3 ) * m( 3, 2 )
345 - m( 0, 0 ) * m( 1, 1 ) * m( 2, 3 ) * m( 3, 2 )
346 - m( 0, 2 ) * m( 1, 1 ) * m( 2, 0 ) * m( 3, 3 )
347 + m( 0, 1 ) * m( 1, 2 ) * m( 2, 0 ) * m( 3, 3 )
348 + m( 0, 2 ) * m( 1, 0 ) * m( 2, 1 ) * m( 3, 3 )
349 - m( 0, 0 ) * m( 1, 2 ) * m( 2, 1 ) * m( 3, 3 )
350 - m( 0, 1 ) * m( 1, 0 ) * m( 2, 2 ) * m( 3, 3 )
351 + m( 0, 0 ) * m( 1, 1 ) * m( 2, 2 ) * m( 3, 3 );
354 template<
typename T >
355 Matrix< 1, 1, T > computeInverse(
const Matrix< 1, 1, T >& m_ )
357 return Matrix< 1, 1, T >( std::vector< T >( T(1) / m_( 0, 0 ), 1 ));
360 template<
typename T >
361 Matrix< 2, 2, T > computeInverse(
const Matrix< 2, 2, T >& m_ )
363 const T det = computeDeterminant( m_ );
364 if( std::abs( det ) < std::numeric_limits< T >::epsilon( ))
365 return Matrix< 2, 2, T >(
366 std::vector< T >( 4, std::numeric_limits< T >::quiet_NaN( )));
368 Matrix< 2, 2, T > inverse;
369 m_.getAdjugate( inverse );
370 const T detinv = 1 / det;
371 inverse( 0, 0 ) *= detinv;
372 inverse( 0, 1 ) *= detinv;
373 inverse( 1, 0 ) *= detinv;
374 inverse( 1, 1 ) *= detinv;
378 template<
typename T >
379 Matrix< 3, 3, T > computeInverse(
const Matrix< 3, 3, T >& m_ )
383 Matrix< 3, 3, T > inverse;
384 inverse( 0, 0 ) = m_( 1, 1 ) * m_( 2, 2 ) - m_( 1, 2 ) * m_( 2, 1 );
385 inverse( 0, 1 ) = m_( 0, 2 ) * m_( 2, 1 ) - m_( 0, 1 ) * m_( 2, 2 );
386 inverse( 0, 2 ) = m_( 0, 1 ) * m_( 1, 2 ) - m_( 0, 2 ) * m_( 1, 1 );
387 inverse( 1, 0 ) = m_( 1, 2 ) * m_( 2, 0 ) - m_( 1, 0 ) * m_( 2, 2 );
388 inverse( 1, 1 ) = m_( 0, 0 ) * m_( 2, 2 ) - m_( 0, 2 ) * m_( 2, 0 );
389 inverse( 1, 2 ) = m_( 0, 2 ) * m_( 1, 0 ) - m_( 0, 0 ) * m_( 1, 2 );
390 inverse( 2, 0 ) = m_( 1, 0 ) * m_( 2, 1 ) - m_( 1, 1 ) * m_( 2, 0 );
391 inverse( 2, 1 ) = m_( 0, 1 ) * m_( 2, 0 ) - m_( 0, 0 ) * m_( 2, 1 );
392 inverse( 2, 2 ) = m_( 0, 0 ) * m_( 1, 1 ) - m_( 0, 1 ) * m_( 1, 0 );
394 const T determinant = m_( 0, 0 ) * inverse( 0, 0 ) +
395 m_( 0, 1 ) * inverse( 1, 0 ) +
396 m_( 0, 2 ) * inverse( 2, 0 );
398 if ( std::abs( determinant ) <= std::numeric_limits< T >::epsilon( ))
399 return Matrix< 3, 3, T >(
400 std::vector< T >( 9, std::numeric_limits< T >::quiet_NaN( )));
402 const T detinv =
static_cast< T
>( 1.0 ) / determinant;
404 inverse( 0, 0 ) *= detinv;
405 inverse( 0, 1 ) *= detinv;
406 inverse( 0, 2 ) *= detinv;
407 inverse( 1, 0 ) *= detinv;
408 inverse( 1, 1 ) *= detinv;
409 inverse( 1, 2 ) *= detinv;
410 inverse( 2, 0 ) *= detinv;
411 inverse( 2, 1 ) *= detinv;
412 inverse( 2, 2 ) *= detinv;
416 template<
typename T >
417 Matrix< 4, 4, T > computeInverse(
const Matrix< 4, 4, T >& m_ )
419 const T* array = m_.array;
423 const T t1[6] = { array[ 2] * array[ 7] - array[ 6] * array[ 3],
424 array[ 2] * array[11] - array[10] * array[ 3],
425 array[ 2] * array[15] - array[14] * array[ 3],
426 array[ 6] * array[11] - array[10] * array[ 7],
427 array[ 6] * array[15] - array[14] * array[ 7],
428 array[10] * array[15] - array[14] * array[11] };
431 Matrix< 4, 4, T > inv;
432 inv.array[0] = array[ 5] * t1[5] - array[ 9] * t1[4] + array[13] * t1[3];
433 inv.array[1] = array[ 9] * t1[2] - array[13] * t1[1] - array[ 1] * t1[5];
434 inv.array[2] = array[13] * t1[0] - array[ 5] * t1[2] + array[ 1] * t1[4];
435 inv.array[3] = array[ 5] * t1[1] - array[ 1] * t1[3] - array[ 9] * t1[0];
436 inv.array[4] = array[ 8] * t1[4] - array[ 4] * t1[5] - array[12] * t1[3];
437 inv.array[5] = array[ 0] * t1[5] - array[ 8] * t1[2] + array[12] * t1[1];
438 inv.array[6] = array[ 4] * t1[2] - array[12] * t1[0] - array[ 0] * t1[4];
439 inv.array[7] = array[ 0] * t1[3] - array[ 4] * t1[1] + array[ 8] * t1[0];
442 const T t2[6] = { array[ 0] * array[ 5] - array[ 4] * array[ 1],
443 array[ 0] * array[ 9] - array[ 8] * array[ 1],
444 array[ 0] * array[13] - array[12] * array[ 1],
445 array[ 4] * array[ 9] - array[ 8] * array[ 5],
446 array[ 4] * array[13] - array[12] * array[ 5],
447 array[ 8] * array[13] - array[12] * array[ 9] };
450 inv.array[8] = array[ 7] * t2[5] - array[11] * t2[4] + array[15] * t2[3];
451 inv.array[9] = array[11] * t2[2] - array[15] * t2[1] - array[ 3] * t2[5];
452 inv.array[10] = array[15] * t2[0] - array[ 7] * t2[2] + array[ 3] * t2[4];
453 inv.array[11] = array[ 7] * t2[1] - array[ 3] * t2[3] - array[11] * t2[0];
454 inv.array[12] = array[10] * t2[4] - array[ 6] * t2[5] - array[14] * t2[3];
455 inv.array[13] = array[ 2] * t2[5] - array[10] * t2[2] + array[14] * t2[1];
456 inv.array[14] = array[ 6] * t2[2] - array[14] * t2[0] - array[ 2] * t2[4];
457 inv.array[15] = array[ 2] * t2[3] - array[ 6] * t2[1] + array[10] * t2[0];
460 const T determinant = array[0] * inv.array[0] + array[4] * inv.array[1] +
461 array[8] * inv.array[2] + array[12] * inv.array[3];
463 if( std::abs( determinant ) <= std::numeric_limits< T >::epsilon( ))
464 return Matrix< 4, 4, T >(
465 std::vector< T >( 16, std::numeric_limits< T >::quiet_NaN( )));
468 const T detinv = T( 1 ) / determinant;
469 for(
size_t i = 0; i != 16; ++i )
470 inv.array[i] *= detinv;
474 template<
size_t R,
size_t C,
typename T >
475 Matrix< R, C, T > computeInverse(
const Matrix< R, C, T >& )
477 throw std::runtime_error(
"Can't compute inverse of this matrix" );
481 template<
size_t R,
size_t C,
typename T >
inline
485 for(
size_t row = 0; row< R; ++row )
486 for(
size_t col = 0; col < C; ++col )
487 transposed( col, row ) = matrix( row, col );
492 template<
size_t R,
size_t C,
typename T >
497 for(
size_t i = 0; i < R; ++i )
501 template<
size_t R,
size_t C,
typename T >
505 const T* to = std::min( end_, begin_ + R * C );
506 ::memcpy( array, begin_, (to - begin_) *
sizeof( T ));
509 template<
size_t R,
size_t C,
typename T >
515 template<
size_t R,
size_t C,
typename T >
516 template<
size_t P,
size_t Q >
522 template<
size_t R,
size_t C,
typename T >
template<
size_t O >
525 typename enable_if< R == O+1 && C == O+1 && O == 3 >::type* )
528 setTranslation( translation );
535 template<
size_t R,
size_t C,
typename T >
template<
size_t S >
539 typename enable_if< R == S+1 && C == S+1 && S == 3 >::type* )
546 (*this)( 0, 0 ) = s.x();
547 (*this)( 0, 1 ) = s.y();
548 (*this)( 0, 2 ) = s.z();
549 (*this)( 1, 0 ) = u.x();
550 (*this)( 1, 1 ) = u.y();
551 (*this)( 1, 2 ) = u.z();
552 (*this)( 2, 0 ) = -f.x();
553 (*this)( 2, 1 ) = -f.y();
554 (*this)( 2, 2 ) = -f.z();
555 (*this)( 0, 3 ) = -vmml::dot( s, eye );
556 (*this)( 1, 3 ) = -vmml::dot( u, eye );
557 (*this)( 2, 3 ) = vmml::dot( f, eye );
561 template<
size_t R,
size_t C,
typename T >
inline
564 if ( rowIndex >= R || colIndex >= C )
565 throw std::runtime_error(
"matrix( row, column ) index out of bounds" );
566 return array[ colIndex * R + rowIndex ];
569 template<
size_t R,
size_t C,
typename T >
inline
572 if ( rowIndex >= R || colIndex >= C )
573 throw std::runtime_error(
"matrix( row, column ) index out of bounds" );
574 return array[ colIndex * R + rowIndex ];
577 template<
size_t R,
size_t C,
typename T >
580 for(
size_t i = 0; i < R * C; ++i )
581 if( array[ i ] != other.
array[ i ])
586 template<
size_t R,
size_t C,
typename T >
589 return ! operator==( other );
592 template<
size_t R,
size_t C,
typename T >
594 const T tolerance )
const
596 for(
size_t i = 0; i < R * C; ++i )
597 if( std::abs( array[ i ] - other.
array[ i ]) > tolerance )
605 ::memcpy( array, source.
array, R * C *
sizeof( T ));
609 template<
size_t R,
size_t C,
typename T >
template<
size_t P,
size_t Q >
610 const Matrix< R, C, T >&
611 Matrix< R, C, T >::operator=(
const Matrix< P, Q, T >& source )
613 const size_t minL = std::min( P, R );
614 const size_t minC = std::min( Q, C );
616 for (
size_t i = 0 ; i < minL ; ++i )
617 for (
size_t j = 0 ; j < minC ; ++j )
618 (*
this)( i, j ) = source( i, j );
619 for (
size_t i = minL ; i< R ; ++i )
620 for (
size_t j = minC ; j < C ; ++j )
625 template<
size_t R,
size_t C,
typename T >
626 void Matrix< R, C, T >::operator=(
const std::vector< T >& values )
628 const size_t to = std::min( R * C, values.size( ));
629 ::memcpy( array, values.data(), to *
sizeof( T ));
633 ::memset( array + to, 0, (R * C - to) *
sizeof( T ));
635 ::bzero( array + to, (R * C - to) *
sizeof( T ));
640 template<
size_t R,
size_t C,
typename T >
template<
size_t P >
650 for(
size_t rowIndex = 0; rowIndex< R; ++rowIndex )
652 for(
size_t colIndex = 0; colIndex < C; ++colIndex )
654 T& component = (*this)( rowIndex, colIndex );
655 component =
static_cast< T
>( 0.0 );
656 for(
size_t p = 0; p < P; p++)
657 component += left( rowIndex, p ) * right( p, colIndex );
663 template<
size_t R,
size_t C,
typename T >
template<
size_t P >
668 return result.
multiply( *
this, other );
671 #ifdef VMMLIB_USE_CXX03
672 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
673 typename enable_if< R == C && O == P && R == O >::type*
675 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P,
typename >
681 multiply( copy, right );
682 #ifdef VMMLIB_USE_CXX03
689 template<
size_t R,
size_t C,
typename T >
695 for(
size_t i = 0; i< R; ++i )
698 for(
size_t j = 0; j < C; ++j )
699 tmp += (*
this)( i, j ) * vec( j );
705 template<
size_t R,
size_t C,
typename T >
inline
709 for(
size_t i = 0; i< R * C; ++i )
710 result.
array[ i ] = -array[ i ];
714 template<
size_t R,
size_t C,
typename T >
718 throw std::runtime_error(
"getColumn() - index out of bounds." );
720 ::memcpy( &column.
array[0], &array[ R * index ], R *
sizeof( T ));
724 template<
size_t R,
size_t C,
typename T >
725 void Matrix< R, C, T >::setColumn(
size_t index,
const vector< R, T >& column )
728 throw std::runtime_error(
"setColumn() - index out of bounds." );
729 memcpy( array + R * index, column.array, R *
sizeof( T ) );
732 template<
size_t R,
size_t C,
typename T >
733 vector< C, T > Matrix< R, C, T >::getRow(
size_t index )
const
736 throw std::runtime_error(
"getRow() - index out of bounds." );
739 for(
size_t colIndex = 0; colIndex < C; ++colIndex )
740 row( colIndex ) = (*this)( index, colIndex );
744 template<
size_t R,
size_t C,
typename T >
745 void Matrix< R, C, T >::setRow(
size_t rowIndex,
const vector< C, T >& row )
748 throw std::runtime_error(
"setRow() - index out of bounds." );
750 for(
size_t colIndex = 0; colIndex < C; ++colIndex )
751 (*
this)( rowIndex, colIndex ) = row( colIndex );
754 template<
size_t R,
size_t C,
typename T >
inline
763 template<
size_t R,
size_t C,
typename T >
766 for(
size_t i = 0; i < R * C; ++i )
767 array[i] += other.
array[i];
770 template<
size_t R,
size_t C,
typename T >
inline
779 template<
size_t R,
size_t C,
typename T >
782 for(
size_t i = 0; i < R * C; ++i )
783 array[i] -= other.
array[i];
786 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
789 typename enable_if< O <= R && P <= C >::type* )
const
792 if ( O + rowOffset > R || P + colOffset > C )
793 throw std::runtime_error(
"index out of bounds." );
795 for(
size_t row = 0; row < O; ++row )
796 for(
size_t col = 0; col < P; ++col )
797 result( row, col ) = (*this)( rowOffset + row, colOffset + col );
802 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
805 size_t rowOffset,
size_t colOffset )
807 for(
size_t row = 0; row < O; ++row )
808 for(
size_t col = 0; col < P; ++col )
809 (*
this)( rowOffset + row, colOffset + col ) = sub_matrix( row, col);
813 template<
size_t R,
size_t C,
typename T >
814 Matrix< R, C, T > Matrix< R, C, T >::inverse()
const
816 return computeInverse( *
this );
819 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
820 typename enable_if< O == P && R == C && O == R && R >= 2 >::type*
821 Matrix< R, C, T >::getAdjugate( Matrix< O, P, T >& adjugate )
const
823 getCofactors( adjugate );
828 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
829 typename enable_if< O == P && R == C && O == R && R >= 2 >::type*
832 Matrix< R-1, C-1, T > minor_;
834 const size_t _negate = 1u;
835 for(
size_t rowIndex = 0; rowIndex< R; ++rowIndex )
836 for(
size_t colIndex = 0; colIndex < C; ++colIndex )
837 if ( ( rowIndex + colIndex ) & _negate )
838 cofactors( rowIndex, colIndex ) = -getMinor( minor_, rowIndex, colIndex );
840 cofactors( rowIndex, colIndex ) = getMinor( minor_, rowIndex, colIndex );
845 template<
size_t R,
size_t C,
typename T >
template<
size_t O,
size_t P >
846 T Matrix< R, C, T >::getMinor( Matrix< O, P, T >& minor_,
size_t row_to_cut,
848 typename enable_if< O == R-1 && P == C-1 && R == C && R >= 2 >::type* )
const
850 size_t rowOffset = 0;
851 size_t colOffset = 0;
852 for(
size_t rowIndex = 0; rowIndex< R; ++rowIndex )
854 if ( rowIndex == row_to_cut )
858 for(
size_t colIndex = 0; colIndex < R; ++colIndex )
860 if ( colIndex == col_to_cut )
863 minor_( rowIndex + rowOffset, colIndex + colOffset )
864 = (*this)( rowIndex, colIndex );
869 return computeDeterminant( minor_ );
872 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
873 Matrix< R, C, T >& Matrix< R, C, T >::rotate_x(
const TT angle_,
874 typename enable_if< R == C && R == 4, TT >::type* )
876 const T angle =
static_cast< T
>( angle_ );
877 const T sine = std::sin( angle );
878 const T cosine = std::cos( angle );
882 tmp = array[ 4 ] * cosine + array[ 8 ] * sine;
883 array[ 8 ] = - array[ 4 ] * sine + array[ 8 ] * cosine;
886 tmp = array[ 5 ] * cosine + array[ 9 ] * sine;
887 array[ 9 ] = - array[ 5 ] * sine + array[ 9 ] * cosine;
890 tmp = array[ 6 ] * cosine + array[ 10 ] * sine;
891 array[ 10 ] = - array[ 6 ] * sine + array[ 10 ] * cosine;
894 tmp = array[ 7 ] * cosine + array[ 11 ] * sine;
895 array[ 11 ] = - array[ 7 ] * sine + array[ 11 ] * cosine;
901 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
902 Matrix< R, C, T >& Matrix< R, C, T >::rotate_y(
const TT angle_,
903 typename enable_if< R == C && R == 4, TT >::type* )
905 const T angle =
static_cast< T
>( angle_ );
906 const T sine = std::sin( angle );
907 const T cosine = std::cos( angle );
911 tmp = array[ 0 ] * cosine - array[ 8 ] * sine;
912 array[ 8 ] = array[ 0 ] * sine + array[ 8 ] * cosine;
915 tmp = array[ 1 ] * cosine - array[ 9 ] * sine;
916 array[ 9 ] = array[ 1 ] * sine + array[ 9 ] * cosine;
919 tmp = array[ 2 ] * cosine - array[ 10 ] * sine;
920 array[ 10 ] = array[ 2 ] * sine + array[ 10 ] * cosine;
923 tmp = array[ 3 ] * cosine - array[ 11 ] * sine;
924 array[ 11 ] = array[ 3 ] * sine + array[ 11 ] * cosine;
930 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
931 Matrix< R, C, T >& Matrix< R, C, T >::rotate_z(
const TT angle_,
932 typename enable_if< R == C && R == 4, TT >::type* )
934 const T angle =
static_cast< T
>( angle_ );
935 const T sine = std::sin( angle );
936 const T cosine = std::cos( angle );
940 tmp = array[ 0 ] * cosine + array[ 4 ] * sine;
941 array[ 4 ] = - array[ 0 ] * sine + array[ 4 ] * cosine;
944 tmp = array[ 1 ] * cosine + array[ 5 ] * sine;
945 array[ 5 ] = - array[ 1 ] * sine + array[ 5 ] * cosine;
948 tmp = array[ 2 ] * cosine + array[ 6 ] * sine;
949 array[ 6 ] = - array[ 2 ] * sine + array[ 6 ] * cosine;
952 tmp = array[ 3 ] * cosine + array[ 7 ] * sine;
953 array[ 7 ] = - array[ 3 ] * sine + array[ 7 ] * cosine;
959 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
960 Matrix< R, C, T >& Matrix< R, C, T >::pre_rotate_x(
const TT angle_,
961 typename enable_if< R == C && R == 4, TT >::type* )
963 const T angle =
static_cast< T
>( angle_ );
964 const T sine = std::sin( angle );
965 const T cosine = std::cos( angle );
970 array[ 1 ] = array[ 1 ] * cosine + array[ 2 ] * sine;
971 array[ 2 ] = tmp * -sine + array[ 2 ] * cosine;
974 array[ 5 ] = array[ 5 ] * cosine + array[ 6 ] * sine;
975 array[ 6 ] = tmp * -sine + array[ 6 ] * cosine;
978 array[ 9 ] = array[ 9 ] * cosine + array[ 10 ] * sine;
979 array[ 10 ] = tmp * -sine + array[ 10 ] * cosine;
982 array[ 13 ] = array[ 13 ] * cosine + array[ 14 ] * sine;
983 array[ 14 ] = tmp * -sine + array[ 14 ] * cosine;
988 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
989 Matrix< R, C, T >& Matrix< R, C, T >::pre_rotate_y(
const TT angle_,
990 typename enable_if< R == C && R == 4, TT >::type* )
992 const T angle =
static_cast< T
>( angle_ );
993 const T sine = std::sin( angle );
994 const T cosine = std::cos( angle );
999 array[ 0 ] = array[ 0 ] * cosine - array[ 2 ] * sine;
1000 array[ 2 ] = tmp * sine + array[ 2 ] * cosine;
1003 array[ 4 ] = array[ 4 ] * cosine - array[ 6 ] * sine;
1004 array[ 6 ] = tmp * sine + array[ 6 ] * cosine;
1007 array[ 8 ] = array[ 8 ] * cosine - array[ 10 ] * sine;
1008 array[ 10 ] = tmp * sine + array[ 10 ] * cosine;
1011 array[ 12 ] = array[ 12 ] * cosine - array[ 14 ] * sine;
1012 array[ 14 ] = tmp * sine + array[ 14 ] * cosine;
1017 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
1018 Matrix< R, C, T >& Matrix< R, C, T >::pre_rotate_z(
const TT angle_,
1019 typename enable_if< R == C && R == 4, TT >::type* )
1021 const T angle =
static_cast< T
>( angle_ );
1022 const T sine = std::sin( angle );
1023 const T cosine = std::cos( angle );
1028 array[ 0 ] = array[ 0 ] * cosine + array[ 1 ] * sine;
1029 array[ 1 ] = tmp * -sine + array[ 1 ] * cosine;
1032 array[ 4 ] = array[ 4 ] * cosine + array[ 5 ] * sine;
1033 array[ 5 ] = tmp * -sine + array[ 5 ] * cosine;
1036 array[ 8 ] = array[ 8 ] * cosine + array[ 9 ] * sine;
1037 array[ 9 ] = tmp * -sine + array[ 9 ] * cosine;
1040 array[ 12 ] = array[ 12 ] * cosine + array[ 13 ] * sine;
1041 array[ 13 ] = tmp * -sine + array[ 13 ] * cosine;
1046 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
inline
1047 Matrix< R, C, T >& Matrix< R, C, T >::scale(
const vector< 3, TT >& scale_,
1048 typename enable_if< R == C && R == 4, TT >::type* )
1050 array[0] *= scale_[ 0 ];
1051 array[1] *= scale_[ 0 ];
1052 array[2] *= scale_[ 0 ];
1053 array[3] *= scale_[ 0 ];
1054 array[4] *= scale_[ 1 ];
1055 array[5] *= scale_[ 1 ];
1056 array[6] *= scale_[ 1 ];
1057 array[7] *= scale_[ 1 ];
1058 array[8] *= scale_[ 2 ];
1059 array[9] *= scale_[ 2 ];
1060 array[10] *= scale_[ 2 ];
1061 array[11] *= scale_[ 2 ];
1066 template<
size_t R,
size_t C,
typename T >
template<
typename TT >
inline
1067 Matrix< R, C, T >& Matrix< R, C, T >::scaleTranslation(
1068 const vector< 3, TT >& scale_,
1069 typename enable_if< R == C && R == 4, TT >::type* )
1071 array[12] *=
static_cast< T
>( scale_[0] );
1072 array[13] *=
static_cast< T
>( scale_[1] );
1073 array[14] *=
static_cast< T
>( scale_[2] );
1078 template<
size_t R,
size_t C,
typename T >
inline Matrix< R, C, T >&
1079 Matrix< R, C, T >::setTranslation(
const vector< C-1, T >& trans )
1081 for(
size_t i = 0; i < C-1; ++i )
1082 array[ i + R * (C - 1) ] = trans[ i ];
1086 template<
size_t R,
size_t C,
typename T >
inline
1087 vector< C-1, T > Matrix< R, C, T >::getTranslation()
const
1089 vector< C-1, T > result;
1090 for(
size_t i = 0; i < C-1; ++i )
1091 result[ i ] = array[ i + R * (C - 1) ];
1095 template<
size_t R,
size_t C,
typename T >
template<
size_t S >
1096 void Matrix< R, C, T >::getLookAt( vector< S, T >& eye, vector< S, T >& lookAt,
1098 typename enable_if< R == S+1 && C == S+1 && S == 3 >::type* )
const
1100 const Matrix< 4, 4, T >& inv = inverse();
1101 const Matrix< 3, 3, T > rotation(
transpose( Matrix< 3, 3, T >( *
this )));
1103 eye = inv * vector< 3, T >::ZERO;
1104 up = rotation * vector< 3, T >::UP;
1105 lookAt = rotation * vector< 3, T >::FORWARD;
1107 lookAt = eye + lookAt;
Matrix< R, P, T > operator*(const Matrix< C, P, T > &other) const
Matrix operator+(const Matrix &other) const
Element-wise addition of two matrices.
enable_if< O<=R &&P<=C >::type *setSubMatrix(const Matrix< O, P, T > &sub_matrix, size_t rowOffset, size_t colOffset);const Matrix &operator=(const Matrix< R, C, T > &source_);template< size_t P, size_t Q > const Matrix &operator=(const Matrix< P, Q, T > &source_);void operator=(const std::vector< T > &data);Matrix< R, C, T > operator-() const ;vector< R, T > getColumn(size_t columnIndex) const ;void setColumn(size_t index, const vector< R, T > &column);vector< C, T > getRow(size_t index) const ;void setRow(size_t index, const vector< C, T > &row);vector< C-1, T > getTranslation() const ;Matrix< R, C, T > &setTranslation(const vector< C-1, T > &t);template< size_t S > void getLookAt(vector< S, T > &eye, vector< S, T > &lookAt, vector< S, T > &up, typename enable_if< R==S+1 &&C==S+1 &&S==3 >::type *=0) const ;Matrix< R, C, T > inverse() const ;template< size_t O, size_t P > typename enable_if< O==P &&R==C &&O==R &&R >=2 >::type *getAdjugate(Matrix< O, P, T > &adjugate) const ;template< size_t O, size_t P > typename enable_if< O==P &&R==C &&O==R &&R >=2 >::type * getCofactors(Matrix< O, P, T > &cofactors) const
Set the sub matrix of size OxP at the given start indices.
bool operator==(const Matrix &other) const
Matrix< R, C, T > & operator*=(const Matrix< O, P, T > &right)
Multiply two square matrices.
Matrix()
Construct a zero-initialized matrix.
T array[R *C]
column by column storage
Matrix operator-(const Matrix &other) const
Element-wise substraction of two matrices.
bool equals(const Matrix &other, T tolerance=std::numeric_limits< T >::epsilon()) const
heavily inspired by boost::enable_if http://www.boost.org, file: boost/utility/enable_if.hpp, Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine
void operator-=(const Matrix &other)
Element-wise substraction of two matrices.
T & operator()(size_t rowIndex, size_t colIndex)
Matrix< C, R, T > transpose(const Matrix< R, C, T > &matrix)
Matrix< 3, 3, T > getRotationMatrix() const
bool operator!=(const Matrix &other) const
Matrix< O, P, T > getSubMatrix(size_t rowOffset, size_t colOffset, typename enable_if< O<=R &&P<=C >::type *=0) const
Matrix< R, C, T > & multiply(const Matrix< R, P, T > &left, const Matrix< P, C, T > &right)
Set this to the product of the two matrices (left_RxP * right_PxC)
void operator+=(const Matrix &other)
Element-wise addition of two matrices.
Matrix with R rows and C columns of element type T.