OpenGL Mathematics (GLM)
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
 
 
 

479 lines
12 KiB

///////////////////////////////////////////////////////////////////////////////////////////////////
// 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