matrix: parameterise on element type
This commit is contained in:
parent
6e2a78fc3b
commit
c9e46f986e
111
matrix.cpp
111
matrix.cpp
@ -14,7 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Copyright 2011-2012 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2014 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
@ -26,8 +26,10 @@
|
|||||||
using namespace util;
|
using namespace util;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
void
|
void
|
||||||
matrix::scale (double x, double y, double z) {
|
matrix<T>::scale (T x, T y, T z) {
|
||||||
CHECK_HARD (is_affine ());
|
CHECK_HARD (is_affine ());
|
||||||
values[0][0] *= x;
|
values[0][0] *= x;
|
||||||
values[1][1] *= y;
|
values[1][1] *= y;
|
||||||
@ -35,8 +37,10 @@ matrix::scale (double x, double y, double z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
void
|
void
|
||||||
matrix::translate (double x, double y, double z) {
|
matrix<T>::translate (T x, T y, T z) {
|
||||||
CHECK_HARD (is_affine ());
|
CHECK_HARD (is_affine ());
|
||||||
values[0][3] += x;
|
values[0][3] += x;
|
||||||
values[1][3] += y;
|
values[1][3] += y;
|
||||||
@ -44,33 +48,37 @@ matrix::translate (double x, double y, double z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matrix
|
//-----------------------------------------------------------------------------
|
||||||
matrix::inverse (void) const {
|
template <typename T>
|
||||||
return matrix(*this).invert ();
|
matrix<T>
|
||||||
|
matrix<T>::inverse (void) const {
|
||||||
|
return matrix<T>(*this).invert ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matrix&
|
//-----------------------------------------------------------------------------
|
||||||
matrix::invert (void) {
|
template <typename T>
|
||||||
|
matrix<T>&
|
||||||
|
matrix<T>::invert (void) {
|
||||||
CHECK_HARD (is_affine ());
|
CHECK_HARD (is_affine ());
|
||||||
|
|
||||||
// inv ([ M b ] == [ inv(M) -inv(M).b ]
|
// inv ([ M b ] == [ inv(M) -inv(M).b ]
|
||||||
// [ 0 1 ]) [ 0 1
|
// [ 0 1 ]) [ 0 1
|
||||||
|
|
||||||
// Invert the 3x3 M
|
// Invert the 3x3 M
|
||||||
double A = (values[1][1] * values[2][2] - values[1][2] * values[2][1]);
|
T A = (values[1][1] * values[2][2] - values[1][2] * values[2][1]);
|
||||||
double B = (values[1][2] * values[2][0] - values[1][0] * values[2][2]);
|
T B = (values[1][2] * values[2][0] - values[1][0] * values[2][2]);
|
||||||
double C = (values[1][0] * values[2][1] - values[1][1] * values[2][0]);
|
T C = (values[1][0] * values[2][1] - values[1][1] * values[2][0]);
|
||||||
|
|
||||||
double D = (values[0][2] * values[2][1] - values[0][1] * values[2][2]);
|
T D = (values[0][2] * values[2][1] - values[0][1] * values[2][2]);
|
||||||
double E = (values[0][0] * values[2][2] - values[0][2] * values[2][0]);
|
T E = (values[0][0] * values[2][2] - values[0][2] * values[2][0]);
|
||||||
double F = (values[2][0] * values[0][1] - values[0][0] * values[2][1]);
|
T F = (values[2][0] * values[0][1] - values[0][0] * values[2][1]);
|
||||||
|
|
||||||
double G = (values[0][1] * values[1][2] - values[0][2] * values[1][1]);
|
T G = (values[0][1] * values[1][2] - values[0][2] * values[1][1]);
|
||||||
double H = (values[0][2] * values[1][0] - values[0][0] * values[1][2]);
|
T H = (values[0][2] * values[1][0] - values[0][0] * values[1][2]);
|
||||||
double K = (values[0][0] * values[1][1] - values[0][1] * values[1][0]);
|
T K = (values[0][0] * values[1][1] - values[0][1] * values[1][0]);
|
||||||
|
|
||||||
double det = values[0][0] * A + values[0][1] * B + values[0][2] * C;
|
T det = values[0][0] * A + values[0][1] * B + values[0][2] * C;
|
||||||
CHECK_NEQ (det, 0.0);
|
CHECK_NEQ (det, 0.0);
|
||||||
|
|
||||||
values[0][0] = A / det;
|
values[0][0] = A / det;
|
||||||
@ -84,9 +92,9 @@ matrix::invert (void) {
|
|||||||
values[2][2] = K / det;
|
values[2][2] = K / det;
|
||||||
|
|
||||||
// Multiply the b
|
// Multiply the b
|
||||||
double b0 = - values[0][0] * values[0][3] - values[0][1] * values[1][3] - values[0][2] * values[2][3];
|
T b0 = - values[0][0] * values[0][3] - values[0][1] * values[1][3] - values[0][2] * values[2][3];
|
||||||
double b1 = - values[1][0] * values[0][3] - values[1][1] * values[1][3] - values[1][2] * values[2][3];
|
T b1 = - values[1][0] * values[0][3] - values[1][1] * values[1][3] - values[1][2] * values[2][3];
|
||||||
double b2 = - values[2][0] * values[0][3] - values[2][1] * values[1][3] - values[2][2] * values[2][3];
|
T b2 = - values[2][0] * values[0][3] - values[2][1] * values[1][3] - values[2][2] * values[2][3];
|
||||||
|
|
||||||
values[0][3] = b0;
|
values[0][3] = b0;
|
||||||
values[1][3] = b1;
|
values[1][3] = b1;
|
||||||
@ -96,9 +104,11 @@ matrix::invert (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matrix
|
//-----------------------------------------------------------------------------
|
||||||
matrix::operator* (const matrix &rhs) const {
|
template <typename T>
|
||||||
matrix m;
|
matrix<T>
|
||||||
|
matrix<T>::operator* (const matrix<T> &rhs) const {
|
||||||
|
matrix<T> m;
|
||||||
memset (m.values, 0, sizeof (m.values));
|
memset (m.values, 0, sizeof (m.values));
|
||||||
|
|
||||||
for (unsigned i = 0; i < 4; ++i)
|
for (unsigned i = 0; i < 4; ++i)
|
||||||
@ -110,8 +120,10 @@ matrix::operator* (const matrix &rhs) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
util::point<3>
|
util::point<3>
|
||||||
matrix::to_local (const util::point<3> &p) const {
|
matrix<T>::to_local (const util::point<3> &p) const {
|
||||||
CHECK_SOFT (is_affine ());
|
CHECK_SOFT (is_affine ());
|
||||||
|
|
||||||
return { p.x * values[0][0] +
|
return { p.x * values[0][0] +
|
||||||
@ -126,38 +138,51 @@ matrix::to_local (const util::point<3> &p) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
util::point<3>
|
util::point<3>
|
||||||
matrix::to_global (const util::point<3> &p) const {
|
matrix<T>::to_global (const util::point<3> &p) const {
|
||||||
return inverse ().to_local (p);
|
return inverse ().to_local (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
bool
|
bool
|
||||||
matrix::is_affine (void) const {
|
matrix<T>::is_affine (void) const {
|
||||||
return exactly_equal (values[3][0], 0.0) &&
|
return exactly_equal (values[3][0], static_cast<T> (0)) &&
|
||||||
exactly_equal (values[3][1], 0.0) &&
|
exactly_equal (values[3][1], static_cast<T> (0)) &&
|
||||||
exactly_equal (values[3][2], 0.0) &&
|
exactly_equal (values[3][2], static_cast<T> (0)) &&
|
||||||
exactly_equal (values[3][3], 1.0);
|
exactly_equal (values[3][3], static_cast<T> (1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const matrix
|
//-----------------------------------------------------------------------------
|
||||||
matrix::IDENTITY = { { { 1.0, 0.0, 0.0, 0.0 },
|
template <typename T>
|
||||||
{ 0.0, 1.0, 0.0, 0.0 },
|
const matrix<T>
|
||||||
{ 0.0, 0.0, 1.0, 0.0 },
|
matrix<T>::IDENTITY = { { { 1, 0, 0, 0 },
|
||||||
{ 0.0, 0.0, 0.0, 1.0 } } };
|
{ 0, 1, 0, 0 },
|
||||||
|
{ 0, 0, 1, 0 },
|
||||||
|
{ 0, 0, 0, 1 } } };
|
||||||
|
|
||||||
|
|
||||||
const matrix
|
template <typename T>
|
||||||
matrix::ZEROES = { { { 0.0, 0.0, 0.0, 0.0 },
|
const matrix<T>
|
||||||
{ 0.0, 0.0, 0.0, 0.0 },
|
matrix<T>::ZEROES = { { { 0, 0, 0, 0 },
|
||||||
{ 0.0, 0.0, 0.0, 0.0 },
|
{ 0, 0, 0, 0 },
|
||||||
{ 0.0, 0.0, 0.0, 0.0 } } };
|
{ 0, 0, 0, 0 },
|
||||||
|
{ 0, 0, 0, 0 } } };
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template struct matrix<float>;
|
||||||
|
template struct matrix<double>;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream &os, const matrix &m) {
|
operator<< (std::ostream &os, const matrix<T> &m) {
|
||||||
os << "{ {" << m.values[0][0] << ", "
|
os << "{ {" << m.values[0][0] << ", "
|
||||||
<< m.values[0][1] << ", "
|
<< m.values[0][1] << ", "
|
||||||
<< m.values[0][2] << ", "
|
<< m.values[0][2] << ", "
|
||||||
|
22
matrix.hpp
22
matrix.hpp
@ -14,7 +14,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* Copyright 2011-2012 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2014 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_MATRIX_HPP
|
#ifndef __UTIL_MATRIX_HPP
|
||||||
@ -25,27 +25,29 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
template <typename T>
|
||||||
struct matrix {
|
struct matrix {
|
||||||
double values[4][4];
|
T values[4][4];
|
||||||
|
|
||||||
void scale (double x, double y, double z);
|
void scale (T x, T y, T z);
|
||||||
void translate (double x, double y, double z);
|
void translate (T x, T y, T z);
|
||||||
|
|
||||||
matrix inverse (void) const;
|
matrix<T> inverse (void) const;
|
||||||
matrix& invert (void);
|
matrix<T>& invert (void);
|
||||||
|
|
||||||
matrix operator* (const matrix&) const;
|
matrix<T> operator* (const matrix<T>&) const;
|
||||||
|
|
||||||
point<3> to_local (const point<3> &p) const;
|
point<3> to_local (const point<3> &p) const;
|
||||||
point<3> to_global (const point<3> &p) const;
|
point<3> to_global (const point<3> &p) const;
|
||||||
|
|
||||||
bool is_affine (void) const;
|
bool is_affine (void) const;
|
||||||
|
|
||||||
static const matrix IDENTITY;
|
static const matrix<T> IDENTITY;
|
||||||
static const matrix ZEROES;
|
static const matrix<T> ZEROES;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream&, const util::matrix&);
|
template <typename T>
|
||||||
|
std::ostream& operator<< (std::ostream&, const util::matrix<T>&);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user