#ifndef _MATRIX_H_
#define _MATRIX_H_
#include <vDEC/include/Vector.h>
#include <vDEC/include/Point.h>
class Mat4{
private:
real M[4][4];
public: inline Mat4(); inline Mat4(const real *data);
inline Mat4(const Mat4 &mat);
inline Mat4& operator = (const Mat4 &mat);
inline Mat4& operator+=(const Mat4& mat);
inline Mat4& operator-=(const Mat4& mat);
inline Mat4& operator*=(const real &s);
inline Mat4& operator*=(const Mat4 &mat);
inline Mat4& operator/=(const real &s); inline real& operator()(unsigned int i, unsigned int j); inline const real& operator()(unsigned int i, unsigned int j) const; inline static const Mat4 Identity(); inline static Mat4 Diagonal(const Vec4 &d); inline static Mat4 Scaling(const Vec3 &ScaleFactors); inline static Mat4 Scaling(const real &Scale); inline static Mat4 Translation(const Vec3 &displacement); inline static Mat4 Rotation(const Vec3 &Axis, real Angle); inline static Mat4 Rotation(const Vec3 &Axis, real Angle, const Vec3 &Center); inline static Mat4 LookAt(const Vec3 &Eye, const Vec3 &At, const Vec3 &Up); inline static Mat4 Orthogonal(real Width, real Height, real ZNear, real ZFar); inline static Mat4 Perspective(real Width, real Height, real ZNear, real ZFar); inline static Mat4 PerspectiveFov(real FOV, real Aspect, real ZNear, real ZFar); inline static Mat4 Face(const Vec3 &v1, const Vec3 &v2); inline static Mat4 Viewport(real Width, real Height); inline Mat4& Invert(); inline Mat4& Transpose(); inline real Determinant(); inline real* operator [] (unsigned int Row); inline const real* operator [] (unsigned int Row) const; inline const real* Data() const; inline real* MutableData(); inline Pt3 AffineTransform(const Pt3 &P) const; inline Vec3 LinearTransform(const Vec3 &V) const; inline Pt3 AffineProjectionTransform(const Pt3 &P) const;
};
inline Mat4 operator * (const Mat4 &Left, const Mat4 &Right);
inline Mat4 operator * (const Mat4 &Left, const real &Right);
inline Mat4 operator * (const real &Left, const Mat4 &Right);
inline Mat4 operator + (const Mat4 &Left, const Mat4 &Right);
inline Mat4 operator - (const Mat4 &Left, const Mat4 &Right);
inline Vec4 operator * (const Vec4 &Right, const Mat4 &Left);
class Mat3{
private:
real M[3][3];
public: inline Mat3(); inline Mat3(const real *data);
inline Mat3(const Mat3& mat);
inline Mat3(const Vec3 &row1,const Vec3 &row2, const Vec3 &row3); inline real& operator()(unsigned int i, unsigned int j); inline real operator()(unsigned int i, unsigned int j) const; inline Vec3 Col(unsigned int i) const; inline Vec3 Row(unsigned int i) const; inline real* operator [] (unsigned int Row); inline const real* operator [] (unsigned int Row) const;
inline Mat3& operator=(const Mat3& mat);
inline Mat3& operator+=(const Mat3& mat);
inline Mat3& operator-=(const Mat3& mat);
inline Mat3& operator*=(const real &s);
inline Mat3& operator/=(const real &s); inline real Determinant() const; inline real Trace() const; inline Mat3& Transpose(); inline Mat3& Invert(); inline static const Mat3 Identity(); inline static Mat3 Diagonal(const Vec3 &d); inline const real* Data() const; inline real* MutableData();
};
inline Mat3 operator+(const Mat3& Left, const Mat3& Right);
inline Mat3 operator-(const Mat3& Left, const Mat3& Right);
inline Mat3 operator-(const Mat3& M);inline Mat3 operator*(const real &s, const Mat3& M);
inline Mat3 operator*(const Mat3& M, const real &s);
inline Mat3 operator/(const Mat3& M, const real &s);
inline Vec3 operator*(const Mat3& M, const Vec3& V);
inline Mat3 operator*(const Mat3& Left, const Mat3& Right);
inline Mat3 OuterProduct(const Vec3& ColVec, const Vec3& RowVec);
class Mat2{
private:
real M[2][2];
public: inline Mat2(); inline Mat2(const real* data);
inline Mat2(const Mat2& mat);
inline Mat2(const Vec2 &row1, const Vec2 &row2); inline real& operator()(unsigned int i, unsigned int j); inline real operator()(unsigned int i, unsigned int j) const; inline Vec2 Col(unsigned int i) const; inline Vec2 Row(unsigned int i) const; inline real* operator [] (unsigned int Row); inline const real* operator [] (unsigned int Row) const;
inline Mat2& operator=(const Mat2& mat);
inline Mat2& operator+=(const Mat2& mat);
inline Mat2& operator-=(const Mat2& mat);
inline Mat2& operator*=(const real &s);
inline Mat2& operator/=(const real &s); inline real Determinant() const; inline real Trace() const; inline Mat2& Transpose(); inline Mat2& Invert(); inline static const Mat2 Identity(); inline static Mat2 Diagonal(const Vec2 &d); inline const real* Data() const; inline real* MutableData();
};
inline Mat2 operator+(const Mat2& Left, const Mat2& Right);
inline Mat2 operator-(const Mat2& Left, const Mat2& Right);
inline Mat2 operator-(const Mat2& M);inline Mat2 operator*(const real &s, const Mat2& M);
inline Mat2 operator*(const Mat2& M, const real &s);
inline Mat2 operator/(const Mat2& M, const real &s);
inline Vec2 operator*(const Mat2& M, const Vec2& V);
inline Mat2 operator*(const Mat2& Left, const Mat2& Right);
inline Mat2 OuterProduct(const Vec2& ColVec, const Vec2& RowVec);
template <unsigned int N>
class Mat{
private:
real M[N][N];
public:
Mat(){
for(unsigned int i = 0; i < N; ++i){
for(unsigned int j = 0; j < N; ++j){
M[i][j] = 0;
}
}
}
Mat(const real *d){ for(unsigned int i = 0; i < N; ++i){
for(unsigned int j = 0; j < N; ++j){
M[i][j] = d[i*N+j];
}
}
}
Mat(const Mat& mat){
for(unsigned int i = 0; i < N; ++i){
for(unsigned int j = 0; j < N; ++j){
M[i][j] = mat.M[i][j];
}
}
}
real& operator()(unsigned int i, unsigned int j){ return M[i][j]; }
real operator()(unsigned int i, unsigned int j) const{ return M[i][j]; } Mat<N>& operator=(const Mat<N>& mat){
if(this != &M){
for(unsigned int i = 0; i < N; ++i){
for(unsigned int j = 0; j < N; ++j){
M[i][j] = mat.M[i][j];
}
}
}
return *this;
}
Mat<N>& operator+=(const Mat<N>& Right){
for(unsigned int i = 0; i < 3; i++){
for(unsigned int j = 0; j < 3; j++){
M[i][j] += Right.M[i][j];
}
}
return *this;
}
Mat<N>& operator-=(const Mat<N>& Right){
for(unsigned int i = 0; i < 3; i++){
for(unsigned int j = 0; j < 3; j++){
M[i][j] -= Right.M[i][j];
}
}
return *this;
}
Mat<N>& operator*=(const real &s){
for(unsigned int i = 0; i < 3; i++){
for(unsigned int j = 0; j < 3; j++){
M[i][j] *= s;
}
}
return *this;
}
Mat<N>& operator/=(const real &s){
for(unsigned int i = 0; i < 3; i++){
for(unsigned int j = 0; j < 3; j++){
M[i][j] /= s;
}
}
return *this;
}
real Determinant() const{
for(unsigned int i = 1; i < N; ++i){
M[0][i] /= M[0][0];
} for(unsigned int i = 1; i < N; ++i){
for(unsigned int j = i; j < N; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[j][k] * M[k][i];
}
M[j][i] -= sum;
}
if(i == N-1) continue;
for(unsigned int j = i+1; j < N; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[i][k]*M[k][j];
}
M[i][j] = (M[i][j]-sum) / M[i][i];
}
}
real prod = (real)1.0;
for(unsigned int i = 0; i < N; ++i){
prod *= M[i][i];
}
return prod;
}
real Trace() const{
real sum = 0;
for(unsigned int i = 0; i < N; ++i){
sum += M[i][i];
}
return sum;
}
Mat<N>& Transpose(){
for(unsigned int i = 0; i < N; i++){
for(unsigned int j = i+1; j < N; j++){
std::swap(M[i][j], M[j][i]);
}
}
return *this;
}
Mat<N>& Invert(){
for(unsigned int i = 1; i < N; ++i){
M[0][i] /= M[0][0];
}
for(unsigned int i = 1; i < N; ++i){
for(unsigned int j = i; j < N; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[j][k] * M[k][i];
}
M[j][i] -= sum;
}
if(i == N-1) continue;
for(unsigned int j = i+1; j < N; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[i][k]*M[k][j];
}
M[i][j] = (M[i][j]-sum) / M[i][i];
}
}
for(unsigned int i = 0; i < N; ++i){ for(unsigned int j = i; j < N; ++j){
real x = 1.0;
if(i != j){
x = 0.0;
for(unsigned int k = i; k < j; ++k){
x -= M[j][k]*M[k][i];
}
}
M[j][i] = x / M[j][j];
}
}
for(unsigned int i = 0; i < N; ++i){ for(unsigned int j = i; j < N; ++j){
if(i == j){ continue; }
real sum = 0.0;
for(unsigned int k = i; k < j; ++k){
sum += M[k][j]*( (i==k) ? 1.0f : M[i][k] );
}
M[i][j] = -sum;
}
}
for(unsigned int i = 0; i < N; ++i){ for(unsigned int j = 0; j < N; ++j){
real sum = 0.0;
for(unsigned int k = ((i>j)?i:j); k < N; k++ ){
sum += ((j==k)?1.0f:M[j][k])*M[k][i];
}
M[j][i] = sum;
}
}
return *this;
}
static Mat<N> Diagonal(const Vec<N> &d){
Mat<N> ret;
for(unsigned int i = 0; i < N; ++i){
ret(i,i) = d[i];
}
return ret;
}
static Mat<N> Identity(){
Mat<N> ret;
for(unsigned int i = 0; i < N; ++i){
ret(i,i) = 1;
}
return ret;
}
const real* Data() const{ return (const real*)M; }
real* MutableData(){ return (real*)M; }
};
template <unsigned int N>
Mat<N> operator+(const Mat<N>& Left, const Mat<N>& Right){
Mat<N> ret(Left);
return (ret += Right);
}
template <unsigned int N>
Mat<N> operator-(const Mat<N>& Left, const Mat<N>& Right){
Mat<N> ret(Left);
return (ret -= Right);
}
template <unsigned int N>
Mat<N> operator-(const Mat<N>& M){ Mat<N> ret(M);
return (ret *= -1);
}
template <unsigned int N>
Mat<N> operator*(const real &s, const Mat<N>& M){
Mat<N> ret(M);
return (ret *= s);
}
template <unsigned int N>
Mat<N> operator*(const Mat<N>& M, const real &s){
Mat<N> ret(M);
return (ret *= s);
}
template <unsigned int N>
Mat<N> operator/(const Mat<N>& M, const real &s){
Mat<N> ret(M);
return (ret /= s);
}
template <unsigned int N>
Vec<N> operator*(const Mat<N>& M, const Vec<N>& V){
Vec<N> ret;
for(unsigned int i = 0; i < N; ++i){
ret[i] = 0;
for(unsigned int j = 0; j < N; ++j){
ret[i] += M(i,j) * V[j];
}
}
return ret;
}
template <unsigned int N>
Mat<N> operator*(const Mat<N> Left, const Mat<N>& Right){
Mat<N> ret;
for(unsigned int i = 0; i < N; ++i){
for(unsigned int j = 0; j < N; ++j){
ret(i,j) = 0;
for(unsigned int k = 0; k < N; ++k){
ret(i,j) += Left(i, k) * Right(k, j);
}
}
}
return ret;
}
Mat4::Mat4(){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] = 0;
}
}
}
Mat4::Mat4(const real *data){
unsigned int k = 0;
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] = data[k++];
}
}
}
Mat4::Mat4(const Mat4 &mat){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] = mat.M[i][j];
}
}
}
Mat4& Mat4::operator = (const Mat4 &mat){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] = mat.M[i][j];
}
}
return *this;
}
Mat4& Mat4::operator+=(const Mat4& mat){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] += mat.M[i][j];
}
}
return *this;
}
Mat4& Mat4::operator-=(const Mat4& mat){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] -= mat.M[i][j];
}
}
return *this;
}
Mat4& Mat4::operator*=(const real &s){
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] += s;
}
}
return *this;
}
Mat4& Mat4::operator*=(const Mat4 &mat){
Mat4 ret;
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
ret(i,j) = (real)0.0;
for(unsigned int k = 0; k < 4; ++k){
ret(i,j) += M[i][k] * mat(k, j);
}
}
}
*this = ret;
return *this;
}
Mat4& Mat4::operator/=(const real &s){
real f = (real)1/s;
for(unsigned int i = 0; i < 4; ++i){
for(unsigned int j = 0; j < 4; ++j){
M[i][j] *= f;
}
}
return *this;
}
real& Mat4::operator()(unsigned int i, unsigned int j){ return M[i][j]; }
const real& Mat4::operator()(unsigned int i, unsigned int j) const{ return M[i][j]; }
const Mat4 Mat4::Identity(){
static const real identity_data_mat4[16] = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1};
static const Mat4 I(identity_data_mat4);
return I;
}
Mat4 Mat4::Diagonal(const Vec4 &d){
Mat4 ret;
ret(0,0) = d.x;
ret(1,1) = d.y;
ret(2,2) = d.z;
ret(3,3) = d.w;
return ret;
}
Mat4 Mat4::Scaling(const Vec3 &ScaleFactors){
Mat4 ret;
ret(0,0) = ScaleFactors.x;
ret(1,0) = (real)0.0;
ret(2,0) = (real)0.0;
ret(3,0) = (real)0.0;
ret(0,1) = (real)0.0;
ret(1,1) = ScaleFactors.y;
ret(2,1) = (real)0.0;
ret(3,1) = (real)0.0;
ret(0,2) = (real)0.0;
ret(1,2) = (real)0.0;
ret(2,2) = ScaleFactors.z;
ret(3,2) = (real)0.0;
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)0.0;
ret(3,3) = (real)1.0;
return ret;
}
Mat4 Mat4::Scaling(const real &Scale){
return Scaling(Vec3(Scale, Scale, Scale));
}
Mat4 Mat4::Translation(const Vec3 &displacement){
Mat4 ret;
ret(0,0) = (real)1.0;
ret(1,0) = (real)0.0;
ret(2,0) = (real)0.0;
ret(3,0) = displacement.x;
ret(0,1) = (real)0.0;
ret(1,1) = (real)1.0;
ret(2,1) = (real)0.0;
ret(3,1) = displacement.y;
ret(0,2) = (real)0.0;
ret(1,2) = (real)0.0;
ret(2,2) = (real)1.0;
ret(3,2) = displacement.z;
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)0.0;
ret(3,3) = (real)1.0;
return ret;
}
Mat4 Mat4::Rotation(const Vec3 &Axis, real Angle){
Mat4 ret;
real c = VDEC_COS(Angle);
real s = VDEC_SIN(Angle);
real t = 1.0f - c;
Vec3 Axis2 = Axis;
Axis2.Normalize();
real x = Axis2.x;
real y = Axis2.y;
real z = Axis2.z;
ret(0,0) = (real)1.0 + t*(x*x -(real) 1.0);
ret(0,1) = z*s + t*x*y;
ret(0,2) = -y*s + t*x*z;
ret(0,3) = (real)0.0;
ret(1,0) = -z*s + t*x*y;
ret(1,1) = (real)1.0 + t*(y*y - (real)1.0);
ret(1,2) = x*s + t*y*z;
ret(1,3) = (real)0.0;
ret(2,0) = y*s + t*x*z;
ret(2,1) = -x*s + t*y*z;
ret(2,2) = (real)1.0 + t*(z*z - (real)1.0);
ret(2,3) = (real)0.0;
ret(3,0) = (real)0.0;
ret(3,1) = (real)0.0;
ret(3,2) = (real)0.0;
ret(3,3) = (real)1.0;
return ret;
}
Mat4 Mat4::Rotation(const Vec3 &Axis, real Angle, const Vec3 &Center){
return Mat4::Translation(-Center) * Mat4::Rotation(Axis, Angle) * Mat4::Translation(Center);
}
Mat4 Mat4::LookAt(const Vec3 &Eye, const Vec3 &At, const Vec3 &Up){
Mat4 ret;
Vec3 ZAxis(Eye - At);
Vec3 XAxis(Vec3::Cross(Up,ZAxis));
XAxis.Normalize();
Vec3 YAxis(Vec3::Cross(ZAxis,XAxis));
ret(0,0) = XAxis.x;
ret(1,0) = XAxis.y;
ret(2,0) = XAxis.z;
ret(3,0) = -Vec3::Dot(XAxis,Eye);
ret(0,1) = YAxis.x;
ret(1,1) = YAxis.y;
ret(2,1) = YAxis.z;
ret(3,1) = -Vec3::Dot(YAxis,Eye);
ret(0,2) = ZAxis.x;
ret(1,2) = ZAxis.y;
ret(2,2) = ZAxis.z;
ret(3,2) = -Vec3::Dot(ZAxis,Eye);
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)0.0;
ret(3,3) = (real)1.0;
return ret;
}
Mat4 Mat4::Orthogonal(real Width, real Height, real ZNear, real ZFar){
Mat4 ret;
ret(0,0) = (real)2.0 / Width;
ret(1,0) = (real)0.0;
ret(2,0) = (real)0.0;
ret(3,0) = (real)0.0;
ret(0,1) = (real)0.0;
ret(1,1) = (real)2.0 / Height;
ret(2,1) = (real)0.0;
ret(3,1) = (real)0.0;
ret(0,2) = (real)0.0;
ret(1,2) = (real)0.0;
ret(2,2) = (real)1.0 / (ZNear - ZFar);
ret(3,2) = ZNear / (ZNear - ZFar);
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)0.0;
ret(3,3) = (real)1.0;
return ret;
}
Mat4 Mat4::Perspective(real Width, real Height, real ZNear, real ZFar){
Mat4 ret;
ret(0,0) = (real)2.0 * ZNear / Width;
ret(1,0) = (real)0.0;
ret(2,0) = (real)0.0;
ret(3,0) = (real)0.0;
ret(0,1) = (real)0.0;
ret(1,1) = (real)2.0 * ZNear / Height;
ret(2,1) = (real)0.0;
ret(3,1) = (real)0.0;
ret(0,2) = (real)0.0;
ret(1,2) = (real)0.0;
ret(2,2) = ZFar / (ZNear - ZFar);
ret(3,2) = ZFar * ZNear / (ZNear - ZFar);
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)-1.0;
ret(3,3) = (real)0.0;
return ret;
}
Mat4 Mat4::PerspectiveFov(real FOV, real Aspect, real ZNear, real ZFar){
Mat4 ret;
real Width = (real)1.0/VDEC_TAN((real)0.5*FOV), Height = (real)Aspect/VDEC_TAN((real)0.5*FOV);
ret(0,0) = Width;
ret(1,0) = (real)0.0;
ret(2,0) = (real)0.0;
ret(3,0) = (real)0.0;
ret(0,1) = (real)0.0;
ret(1,1) = Height;
ret(2,1) = (real)0.0;
ret(3,1) = (real)0.0;
ret(0,2) = (real)0.0;
ret(1,2) = (real)0.0;
ret(2,2) = ZFar / (ZNear - ZFar);
ret(3,2) = ZFar * ZNear / (ZNear - ZFar);
ret(0,3) = (real)0.0;
ret(1,3) = (real)0.0;
ret(2,3) = (real)-1.0;
ret(3,3) = (real)0.0;
return ret;
}
Mat4 Mat4::Face(const Vec3 &_v1, const Vec3 &_v2){ Vec3 v1(_v1), v2(_v2);
real Angle;
v1.Normalize();
v2.Normalize();
Vec3 Axis(Vec3::Cross(v1, v2));
real DotProduct = Vec3::Dot(v1,v2);
if(DotProduct <= -1.0f){
return Mat4::Scaling(-1);
}
if(DotProduct >= 1.0f){
return Mat4::Identity();
}
Angle = VDEC_ACOS(DotProduct);
if(Angle == 0.0f || Axis.Length() == 0.0f)
return Mat4::Identity();
else
return Mat4::Rotation(Axis,Angle);
}
Mat4 Mat4::Viewport(real Width, real Height){
Mat4 ret;
ret(0,0) = Width;
ret(1,0) = 0.0f;
ret(2,0) = 0.0f;
ret(3,0) = 0.0f;
ret(0,1) = 0.0f;
ret(1,1) = Height;
ret(2,1) = 0.0f;
ret(3,1) = 0.0f;
ret(0,2) = 0.0f;
ret(1,2) = 0.0f;
ret(2,2) = 1.0f;
ret(3,2) = 0.0f;
ret(0,3) = 0.0f;
ret(1,3) = 0.0f;
ret(2,3) = 0.0f;
ret(3,3) = 1.0f;
return ret;
}
Mat4& Mat4::Invert(){ for(unsigned int i = 1; i < 4; ++i){
M[0][i] /= M[0][0];
}
for(unsigned int i = 1; i < 4; ++i){
for(unsigned int j = i; j < 4; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[j][k] * M[k][i];
}
M[j][i] -= sum;
}
if(i == 4-1) continue;
for(unsigned int j = i+1; j < 4; ++j){
real sum = 0.0;
for(unsigned int k = 0; k < i; ++k){
sum += M[i][k]*M[k][j];
}
M[i][j] = (M[i][j]-sum) / M[i][i];
}
}
for(unsigned int i = 0; i < 4; ++i){
for(