480 lines
12 KiB
C++
480 lines
12 KiB
C++
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// OpenGL Mathematics Copyright (c) 2005 - 2010 G-Truc Creation (www.g-truc.net)
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Created : 2007-02-21
|
|
// Updated : 2007-02-21
|
|
// Licence : This source is under MIT License
|
|
// File : glm/gtx/matx.inl
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <cassert>
|
|
#include <algorithm>
|
|
|
|
namespace glm{
|
|
namespace detail{
|
|
|
|
template <int N, typename T> const typename _xmatxGTX<N, T>::size_type _xmatxGTX<N, T>::value_size = N;
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// _xmatxGTX constructors
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>::_xmatxGTX()
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i][i] = T(0);
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>::_xmatxGTX(const T f)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i][i] = f;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
// _xmatxGTX operators
|
|
|
|
// This function shouldn't required but it seems that VC7.1 have an optimisation bug if this operator wasn't declared
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator= (const _xmatxGTX<N, T>& m)
|
|
{
|
|
//memcpy could be faster
|
|
//memcpy(&this->value, &m.value, 16 * sizeof(T));
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] = m[i];
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator+= (const T s)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] += s;
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator+= (const _xmatxGTX<N, T>& m)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] += m[i];
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator-= (const T s)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] -= s;
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator-= (const _xmatxGTX<N, T>& m)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] -= m[i];
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator*= (const T s)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] *= s;
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator*= (const _xmatxGTX<N, T>& m)
|
|
{
|
|
return (*this = *this * m);
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator/= (const T s)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
this->value[i] /= s;
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator/= (const _xmatxGTX<N, T>& m)
|
|
{
|
|
return (*this = *this / m);
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator-- ()
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
--this->value[i];
|
|
return *this;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T>& _xmatxGTX<N, T>::operator++ ()
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
++this->value[i];
|
|
return *this;
|
|
}
|
|
|
|
// Private functions
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> _xmatxGTX<N, T>::_inverse() const
|
|
{
|
|
_xmatxGTX<N, T> Result = *this;
|
|
|
|
int ColIndex[N];
|
|
int RowIndex[N];
|
|
bool Pivoted[N];
|
|
memset(ColIndex, 0, N * sizeof(int));
|
|
memset(RowIndex, 0, N * sizeof(int));
|
|
memset(Pivoted, 0, N * sizeof(bool));
|
|
|
|
int iRow = 0, iCol = 0;
|
|
|
|
// elimination by full pivoting
|
|
for(int i0 = 0; i0 < N; i0++)
|
|
{
|
|
// search matrix (excluding pivoted rows) for maximum absolute entry
|
|
T fMax = T(0);
|
|
for(int i1 = 0; i1 < N; i1++)
|
|
{
|
|
if(Pivoted[i1])
|
|
continue;
|
|
|
|
for(int i2 = 0; i2 < N; i2++)
|
|
{
|
|
if(Pivoted[i2])
|
|
continue;
|
|
|
|
T Abs = abs(Result[i1][i2]);
|
|
if(Abs > fMax)
|
|
{
|
|
fMax = Abs;
|
|
iRow = i1;
|
|
iCol = i2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fMax == T(0))
|
|
{
|
|
return _xmatxGTX<N, T>(1.0f); // Error
|
|
}
|
|
|
|
Pivoted[iCol] = true;
|
|
|
|
// swap rows so that A[iCol][iCol] contains the pivot entry
|
|
if(iRow != iCol)
|
|
{
|
|
_xvecxGTX<N, T> Row = rowGTX(Result, iRow);
|
|
_xvecxGTX<N, T> Col = rowGTX(Result, iCol);
|
|
rowGTX(Result, iRow, Col);
|
|
rowGTX(Result, iCol, Row);
|
|
}
|
|
|
|
// keep track of the permutations of the rows
|
|
RowIndex[i0] = iRow;
|
|
ColIndex[i0] = iCol;
|
|
|
|
// scale the row so that the pivot entry is 1
|
|
T fInv = T(1) / Result[iCol][iCol];
|
|
Result[iCol][iCol] = T(1);
|
|
for(int i2 = 0; i2 < N; i2++)
|
|
Result[iCol][i2] *= fInv;
|
|
|
|
// zero out the pivot column locations in the other rows
|
|
for(int i1 = 0; i1 < N; ++i1)
|
|
{
|
|
if(i1 == iCol)
|
|
continue;
|
|
|
|
T Tmp = Result[i1][iCol];
|
|
Result[i1][iCol] = T(0);
|
|
for(int i2 = 0; i2 < N; i2++)
|
|
Result[i1][i2] -= Result[iCol][i2] * Tmp;
|
|
}
|
|
}
|
|
|
|
// reorder rows so that A[][] stores the inverse of the original matrix
|
|
for(int i1 = N-1; i1 >= 0; --i1)
|
|
{
|
|
if(RowIndex[i1] == ColIndex[i1])
|
|
continue;
|
|
for(int i2 = 0; i2 < N; ++i2)
|
|
std::swap(Result[i2][RowIndex[i1]], Result[i2][ColIndex[i1]]);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
// Binary operators
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator+ (const _xmatxGTX<N, T>& m, const T s)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] + s;
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator+ (const T s, const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = s + m[i];
|
|
return result;
|
|
}
|
|
/*
|
|
template <int N, typename T>
|
|
inline tvec4<T> operator+ (const _xmatxGTX<N, T>& m, const tvec4<T>& v)
|
|
{
|
|
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline tvec4<T> operator+ (const tvec4<T>& v, const _xmatxGTX<N, T>& m)
|
|
{
|
|
|
|
}
|
|
*/
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator+ (const _xmatxGTX<N, T>& m1, const _xmatxGTX<N, T>& m2)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m1[i] + m2[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator- (const _xmatxGTX<N, T>& m, const T s)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] - s;
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator- (const T s, const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = s - m[i];
|
|
return result;
|
|
}
|
|
/*
|
|
template <int N, typename T>
|
|
inline tvec4<T> operator- (const _xmatxGTX<N, T>& m, const tvec4<T>& v)
|
|
{
|
|
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline tvec4<T> operator- (const tvec4<T>& v, const _xmatxGTX<N, T>& m)
|
|
{
|
|
|
|
}
|
|
*/
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator- (const _xmatxGTX<N, T>& m1, const _xmatxGTX<N, T>& m2)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m1[i] - m2[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator* (const _xmatxGTX<N, T>& m, const T s)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] * s;
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator* (const T s, const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = s * m[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xvecxGTX<N, T> operator* (const _xmatxGTX<N, T>& m, const _xvecxGTX<N, T>& v)
|
|
{
|
|
_xvecxGTX<N, T> result(T(0));
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
result[j] += m[i][j] * v[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xvecxGTX<N, T> operator* (const _xvecxGTX<N, T>& v, const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xvecxGTX<N, T> result(T(0));
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
result[j] += m[j][i] * v[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator* (const _xmatxGTX<N, T>& m1, const _xmatxGTX<N, T>& m2)
|
|
{
|
|
_xmatxGTX<N, T> Result(T(0));
|
|
for(int k = 0; k < N; ++k)
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
Result[k][j] += m1[i][j] * m2[k][i];
|
|
return Result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator/ (const _xmatxGTX<N, T>& m, const T s)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] / s;
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator/ (const T s, const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = s / m[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xvecxGTX<N, T> operator/ (const _xmatxGTX<N, T>& m, const _xvecxGTX<N, T>& v)
|
|
{
|
|
return m._inverse() * v;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xvecxGTX<N, T> operator/ (const _xvecxGTX<N, T>& v, const _xmatxGTX<N, T>& m)
|
|
{
|
|
return v * m._inverse();
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline _xmatxGTX<N, T> operator/ (const _xmatxGTX<N, T>& m1, const _xmatxGTX<N, T>& m2)
|
|
{
|
|
return m1 * m2._inverse();
|
|
}
|
|
|
|
// Unary constant operators
|
|
template <int N, typename T>
|
|
inline const _xmatxGTX<N, T> operator- (const _xmatxGTX<N, T>& m)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = -m[i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline const _xmatxGTX<N, T> operator++ (const _xmatxGTX<N, T>& m, int)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] + T(1);
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline const _xmatxGTX<N, T> operator-- (const _xmatxGTX<N, T>& m, int)
|
|
{
|
|
_xmatxGTX<N, T> result;
|
|
for(int i = 0; i < N; ++i)
|
|
result[i] = m[i] - T(1);
|
|
return result;
|
|
}
|
|
}//namespace detail
|
|
|
|
// Matrix Functions
|
|
template <int N, typename T>
|
|
inline detail::_xmatxGTX<N, T> matrixCompMultGTX(const detail::_xmatxGTX<N, T>& x, const detail::_xmatxGTX<N, T>& y)
|
|
{
|
|
detail::_xmatxGTX<N, T> result;
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
result[j][i] = x[j][i] * y[j][i];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline detail::_xmatxGTX<N, T> outerProductGTX(const detail::_xvecxGTX<N, T>& c, const detail::_xvecxGTX<N, T>& r)
|
|
{
|
|
detail::_xmatxGTX<N, T> result;
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
result[j][i] = c[i] * r[j];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline detail::_xmatxGTX<N, T> transposeGTX(const detail::_xmatxGTX<N, T>& m)
|
|
{
|
|
detail::_xmatxGTX<N, T> result;
|
|
for(int j = 0; j < N; ++j)
|
|
for(int i = 0; i < N; ++i)
|
|
result[j][i] = m[i][j];
|
|
return result;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline T determinantGTX(const detail::_xmatxGTX<N, T>& m)
|
|
{
|
|
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline detail::_xmatxGTX<N, T> inverseTransposeGTX(const detail::_xmatxGTX<N, T>& m)
|
|
{
|
|
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline void columnGTX(detail::_xmatxGTX<N, T>& m, int ColIndex, const detail::_xvecxGTX<N, T>& v)
|
|
{
|
|
m[ColIndex] = v;
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline void rowGTX(detail::_xmatxGTX<N, T>& m, int RowIndex, const detail::_xvecxGTX<N, T>& v)
|
|
{
|
|
for(int i = 0; i < N; ++i)
|
|
m[i][RowIndex] = v[i];
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline detail::_xvecxGTX<N, T> columnGTX(const detail::_xmatxGTX<N, T>& m, int ColIndex)
|
|
{
|
|
return m[ColIndex];
|
|
}
|
|
|
|
template <int N, typename T>
|
|
inline detail::_xvecxGTX<N, T> rowGTX(const detail::_xmatxGTX<N, T>& m, int RowIndex)
|
|
{
|
|
detail::_xvecxGTX<N, T> v;
|
|
for(int i = 0; i < N; ++i)
|
|
v[i] = m[i][RowIndex];
|
|
return v;
|
|
}
|
|
} //namespace glm
|