improve mat44 implementation

this will make it easier to create matrices of different sizes

Change-Id: I2c1771ba0823c42d737762e2dfc2cd47eb302767
This commit is contained in:
Mathias Agopian 2013-09-01 21:35:36 -07:00
parent 9b5534b0e5
commit 1d4d8f94e2
6 changed files with 210 additions and 157 deletions

View File

@ -26,6 +26,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <math.h>
#include <utils/Debug.h>
#include <utils/String8.h>
@ -171,6 +172,83 @@ String8 asString(const MATRIX& m) {
}; // namespace matrix
// -------------------------------------------------------------------------------------
/*
* TMatProductOperators implements basic arithmetic and basic compound assignments
* operators on a vector of type BASE<T>.
*
* BASE only needs to implement operator[] and size().
* By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
* get all the functionality here.
*/
template <template<typename T> class BASE, typename T>
class TMatProductOperators {
public:
// multiply by a scalar
BASE<T>& operator *= (T v) {
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
for (size_t r=0 ; r<lhs.row_size() ; r++) {
lhs[r] *= v;
}
return lhs;
}
// divide by a scalar
BASE<T>& operator /= (T v) {
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
for (size_t r=0 ; r<lhs.row_size() ; r++) {
lhs[r] /= v;
}
return lhs;
}
// matrix * matrix, result is a matrix of the same type than the lhs matrix
template<typename U>
friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
return matrix::multiply<BASE<T> >(lhs, rhs);
}
};
/*
* TMatSquareFunctions implements functions on a matrix of type BASE<T>.
*
* BASE only needs to implement:
* - operator[]
* - col_type
* - row_type
* - COL_SIZE
* - ROW_SIZE
*
* By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
* get all the functionality here.
*/
template<template<typename U> class BASE, typename T>
class TMatSquareFunctions {
public:
/*
* NOTE: the functions below ARE NOT member methods. They are friend functions
* with they definition inlined with their declaration. This makes these
* template functions available to the compiler when (and only when) this class
* is instantiated, at which point they're only templated on the 2nd parameter
* (the first one, BASE<T> being known).
*/
friend BASE<T> PURE inverse(const BASE<T>& m) { return matrix::inverse(m); }
friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
friend T PURE trace(const BASE<T>& m) { return matrix::trace(m); }
};
template <template<typename T> class BASE, typename T>
class TMatDebug {
public:
String8 asString() const {
return matrix::asString(*this);
}
};
// -------------------------------------------------------------------------------------
}; // namespace android

View File

@ -57,16 +57,16 @@ struct Impersonator {
};
/*
* TVecArithmeticOperators implements basic arithmetic and basic compound assignments
* TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments
* operators on a vector of type BASE<T>.
*
* BASE only needs to implement operator[] and size().
* By simply inheriting from TVecArithmeticOperators<BASE, T> BASE will automatically
* By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically
* get all the functionality here.
*/
template <template<typename T> class BASE, typename T>
class TVecArithmeticOperators {
class TVecAddOperators {
public:
/* compound assignment from a another vector of the same size but different
* element type.
@ -87,22 +87,6 @@ public:
}
return rhs;
}
template <typename OTHER>
BASE<T>& operator *= (const BASE<OTHER>& v) {
BASE<T>& rhs = static_cast<BASE<T>&>(*this);
for (size_t i=0 ; i<BASE<T>::size() ; i++) {
rhs[i] *= v[i];
}
return rhs;
}
template <typename OTHER>
BASE<T>& operator /= (const BASE<OTHER>& v) {
BASE<T>& rhs = static_cast<BASE<T>&>(*this);
for (size_t i=0 ; i<BASE<T>::size() ; i++) {
rhs[i] /= v[i];
}
return rhs;
}
/* compound assignment from a another vector of the same type.
* These operators can be used for implicit conversion and handle operations
@ -123,6 +107,73 @@ public:
}
return rhs;
}
/*
* NOTE: the functions below ARE NOT member methods. They are friend functions
* with they definition inlined with their declaration. This makes these
* template functions available to the compiler when (and only when) this class
* is instantiated, at which point they're only templated on the 2nd parameter
* (the first one, BASE<T> being known).
*/
/* The operators below handle operation between vectors of the same side
* but of a different element type.
*/
template<typename RT>
friend inline
BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) {
return BASE<T>(lv) += rv;
}
template<typename RT>
friend inline
BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) {
return BASE<T>(lv) -= rv;
}
/* The operators below (which are not templates once this class is instanced,
* i.e.: BASE<T> is known) can be used for implicit conversion on both sides.
* These handle operations like "vector * scalar" and "scalar * vector" by
* letting the compiler implicitly convert a scalar to a vector (assuming
* the BASE<T> allows it).
*/
friend inline
BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) {
return BASE<T>(lv) += rv;
}
friend inline
BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) {
return BASE<T>(lv) -= rv;
}
};
template <template<typename T> class BASE, typename T>
class TVecProductOperators {
public:
/* compound assignment from a another vector of the same size but different
* element type.
*/
template <typename OTHER>
BASE<T>& operator *= (const BASE<OTHER>& v) {
BASE<T>& rhs = static_cast<BASE<T>&>(*this);
for (size_t i=0 ; i<BASE<T>::size() ; i++) {
rhs[i] *= v[i];
}
return rhs;
}
template <typename OTHER>
BASE<T>& operator /= (const BASE<OTHER>& v) {
BASE<T>& rhs = static_cast<BASE<T>&>(*this);
for (size_t i=0 ; i<BASE<T>::size() ; i++) {
rhs[i] /= v[i];
}
return rhs;
}
/* compound assignment from a another vector of the same type.
* These operators can be used for implicit conversion and handle operations
* like "vector *= scalar" by letting the compiler implicitly convert a scalar
* to a vector (assuming the BASE<T> allows it).
*/
BASE<T>& operator *= (const BASE<T>& v) {
BASE<T>& rhs = static_cast<BASE<T>&>(*this);
for (size_t i=0 ; i<BASE<T>::size() ; i++) {
@ -151,16 +202,6 @@ public:
*/
template<typename RT>
friend inline
BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) {
return BASE<T>(lv) += rv;
}
template<typename RT>
friend inline
BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) {
return BASE<T>(lv) -= rv;
}
template<typename RT>
friend inline
BASE<T> PURE operator *(const BASE<T>& lv, const BASE<RT>& rv) {
return BASE<T>(lv) *= rv;
}
@ -177,14 +218,6 @@ public:
* the BASE<T> allows it).
*/
friend inline
BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) {
return BASE<T>(lv) += rv;
}
friend inline
BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) {
return BASE<T>(lv) -= rv;
}
friend inline
BASE<T> PURE operator *(const BASE<T>& lv, const BASE<T>& rv) {
return BASE<T>(lv) *= rv;
}

View File

@ -33,7 +33,11 @@ namespace android {
template <typename T>
class tmat44 : public TVecUnaryOperators<tmat44, T>,
public TVecComparisonOperators<tmat44, T>
public TVecComparisonOperators<tmat44, T>,
public TVecAddOperators<tmat44, T>,
public TMatProductOperators<tmat44, T>,
public TMatSquareFunctions<tmat44, T>,
public TMatDebug<tmat44, T>
{
public:
enum no_init { NO_INIT };
@ -108,6 +112,17 @@ public:
template <typename A, typename B, typename C, typename D>
tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3);
// construct from 16 scalars
template <
typename A, typename B, typename C, typename D,
typename E, typename F, typename G, typename H,
typename I, typename J, typename K, typename L,
typename M, typename N, typename O, typename P>
tmat44( A m00, B m01, C m02, D m03,
E m10, F m11, G m12, H m13,
I m20, J m21, K m22, L m23,
M m30, N m31, O m32, P m33);
// construct from a C array
template <typename U>
explicit tmat44(U const* rawArray);
@ -131,33 +146,6 @@ public:
template <typename A, typename B>
static tmat44 rotate(A radian, const tvec3<B>& about);
/*
* Compound assignment arithmetic operators
*/
// add another matrix of the same size
template <typename U>
tmat44& operator += (const tmat44<U>& v);
// subtract another matrix of the same size
template <typename U>
tmat44& operator -= (const tmat44<U>& v);
// multiply by a scalar
template <typename U>
tmat44& operator *= (U v);
// divide by a scalar
template <typename U>
tmat44& operator /= (U v);
/*
* debugging
*/
String8 asString() const;
};
// ----------------------------------------------------------------------------------------
@ -195,6 +183,23 @@ tmat44<T>::tmat44(const tvec4<U>& v) {
mValue[3] = col_type(0,0,0,v.w);
}
// construct from 16 scalars
template<typename T>
template <
typename A, typename B, typename C, typename D,
typename E, typename F, typename G, typename H,
typename I, typename J, typename K, typename L,
typename M, typename N, typename O, typename P>
tmat44<T>::tmat44( A m00, B m01, C m02, D m03,
E m10, F m11, G m12, H m13,
I m20, J m21, K m22, L m23,
M m30, N m31, O m32, P m33) {
mValue[0] = col_type(m00, m01, m02, m03);
mValue[1] = col_type(m10, m11, m12, m13);
mValue[2] = col_type(m20, m21, m22, m23);
mValue[3] = col_type(m30, m31, m32, m33);
}
template <typename T>
template <typename U>
tmat44<T>::tmat44(const tmat44<U>& rhs) {
@ -319,42 +324,6 @@ tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) {
}
}
// ----------------------------------------------------------------------------------------
// Compound assignment arithmetic operators
// ----------------------------------------------------------------------------------------
template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator += (const tmat44<U>& v) {
for (size_t r=0 ; r<row_size() ; r++)
mValue[r] += v[r];
return *this;
}
template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator -= (const tmat44<U>& v) {
for (size_t r=0 ; r<row_size() ; r++)
mValue[r] -= v[r];
return *this;
}
template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator *= (U v) {
for (size_t r=0 ; r<row_size() ; r++)
mValue[r] *= v;
return *this;
}
template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator /= (U v) {
for (size_t r=0 ; r<row_size() ; r++)
mValue[r] /= v;
return *this;
}
// ----------------------------------------------------------------------------------------
// Arithmetic operators outside of class
// ----------------------------------------------------------------------------------------
@ -367,24 +336,6 @@ tmat44<T>& tmat44<T>::operator /= (U v) {
* it determines the output type (only relevant when T != U).
*/
// matrix + matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator +(const tmat44<T>& lhs, const tmat44<U>& rhs) {
tmat44<T> result(tmat44<T>::NO_INIT);
for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
result[r] = lhs[r] + rhs[r];
return result;
}
// matrix - matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator -(const tmat44<T>& lhs, const tmat44<U>& rhs) {
tmat44<T> result(tmat44<T>::NO_INIT);
for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
result[r] = lhs[r] - rhs[r];
return result;
}
// matrix * vector, result is a vector of the same type than the input vector
template <typename T, typename U>
typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
@ -421,46 +372,16 @@ tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
return result;
}
// matrix * matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator *(const tmat44<T>& lhs, const tmat44<U>& rhs) {
return matrix::multiply< tmat44<T> >(lhs, rhs);
}
// ----------------------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------------------
// inverse a matrix
template <typename T>
tmat44<T> PURE inverse(const tmat44<T>& m) {
return matrix::inverse(m);
}
template <typename T>
tmat44<T> PURE transpose(const tmat44<T>& m) {
return matrix::transpose(m);
}
template <typename T>
T PURE trace(const tmat44<T>& m) {
return matrix::trace(m);
}
template <typename T>
tvec4<T> PURE diag(const tmat44<T>& m) {
/* FIXME: this should go into TMatSquareFunctions<> but for some reason
* BASE<T>::col_type is not accessible from there (???)
*/
template<typename T>
typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
return matrix::diag(m);
}
// ----------------------------------------------------------------------------------------
// Debugging
// ----------------------------------------------------------------------------------------
template <typename T>
String8 tmat44<T>::asString() const {
return matrix::asString(*this);
}
// ----------------------------------------------------------------------------------------
typedef tmat44<float> mat4;

View File

@ -27,7 +27,8 @@ namespace android {
// -------------------------------------------------------------------------------------
template <typename T>
class tvec2 : public TVecArithmeticOperators<tvec2, T>,
class tvec2 : public TVecProductOperators<tvec2, T>,
public TVecAddOperators<tvec2, T>,
public TVecUnaryOperators<tvec2, T>,
public TVecComparisonOperators<tvec2, T>,
public TVecFunctions<tvec2, T>
@ -73,6 +74,11 @@ public:
template<typename A>
explicit tvec2(const tvec2<A>& v) : x(v.x), y(v.y) { }
template<typename A>
tvec2(const Impersonator< tvec2<A> >& v)
: x(((const tvec2<A>&)v).x),
y(((const tvec2<A>&)v).y) { }
};
// ----------------------------------------------------------------------------------------

View File

@ -26,7 +26,8 @@ namespace android {
// -------------------------------------------------------------------------------------
template <typename T>
class tvec3 : public TVecArithmeticOperators<tvec3, T>,
class tvec3 : public TVecProductOperators<tvec3, T>,
public TVecAddOperators<tvec3, T>,
public TVecUnaryOperators<tvec3, T>,
public TVecComparisonOperators<tvec3, T>,
public TVecFunctions<tvec3, T>
@ -78,6 +79,12 @@ public:
template<typename A>
explicit tvec3(const tvec3<A>& v) : x(v.x), y(v.y), z(v.z) { }
template<typename A>
tvec3(const Impersonator< tvec3<A> >& v)
: x(((const tvec3<A>&)v).x),
y(((const tvec3<A>&)v).y),
z(((const tvec3<A>&)v).z) { }
template<typename A, typename B>
tvec3(const Impersonator< tvec2<A> >& v, B z)
: x(((const tvec2<A>&)v).x),

View File

@ -26,7 +26,8 @@ namespace android {
// -------------------------------------------------------------------------------------
template <typename T>
class tvec4 : public TVecArithmeticOperators<tvec4, T>,
class tvec4 : public TVecProductOperators<tvec4, T>,
public TVecAddOperators<tvec4, T>,
public TVecUnaryOperators<tvec4, T>,
public TVecComparisonOperators<tvec4, T>,
public TVecFunctions<tvec4, T>
@ -85,6 +86,13 @@ public:
template<typename A>
explicit tvec4(const tvec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
template<typename A>
tvec4(const Impersonator< tvec4<A> >& v)
: x(((const tvec4<A>&)v).x),
y(((const tvec4<A>&)v).y),
z(((const tvec4<A>&)v).z),
w(((const tvec4<A>&)v).w) { }
template<typename A, typename B>
tvec4(const Impersonator< tvec3<A> >& v, B w)
: x(((const tvec3<A>&)v).x),