00001 #ifndef MATRIX4D_H_
00002 #define MATRIX4D_H_
00003
00004 #include <cmath>
00005 #include <iostream>
00006 #include "Vec3D.h"
00007 #include "Vec4D.h"
00008 #include "HCoord4D.h"
00009
00010 namespace rcrt
00011 {
00012
00013 class Matrix4D
00014 {
00015 friend std::ostream& operator<<(std::ostream& out, const Matrix4D& m);
00016
00017 private:
00018 float values[4][4];
00019 void assign(const Matrix4D& mat);
00020 inline static void swap(float mat[4][4], int& i, int& ci);
00021 inline static void div(float mat[4][4], int& i, float& factor);
00022 inline static void res(float mat[4][4], int& i, int& b, float& factor);
00023
00024 public:
00025 Matrix4D();
00026 Matrix4D(float x);
00027 Matrix4D(const Matrix4D& mat);
00028 virtual ~Matrix4D();
00029
00030 const Matrix4D& operator= (const Matrix4D& mat);
00031 const Matrix4D& operator= (float mat[4][4]);
00032 Matrix4D operator+ (const Matrix4D& mat) const;
00033 Matrix4D operator- (const Matrix4D& mat) const;
00034 Matrix4D operator* (const Matrix4D& mat) const;
00035 HCoord4D operator* (const HCoord4D& coords) const;
00036 Point3D operator* (const Point3D& p) const;
00037 Vec3D operator* (const Vec3D& p) const;
00038 Matrix4D operator* (const float f) const;
00039 Matrix4D operator/ (const float f) const;
00040
00045 Vec4D operator[] (const int& i) const;
00046
00047 Matrix4D transpose() const;
00048 Matrix4D inverse() const;
00049
00050 static Matrix4D identity()
00051 {
00052 Matrix4D m;
00053 for (int i = 0; i < 4; ++i)
00054 for (int j = 0; j < 4; ++j)
00055 m.values[i][j] = i == j ? 1 : 0;
00056
00057 return m;
00058 }
00059
00060 static Matrix4D rotation(float angle, const Vec3D& axis)
00061 {
00062 Matrix4D m;
00063 float c = cos(angle);
00064 float s = sin(angle);
00065 float cm = 1-c;
00066 float xycm = axis.x()*axis.y()*cm;
00067 float xzcm = axis.x()*axis.z()*cm;
00068 float yzcm = axis.z()*axis.y()*cm;
00069 float zs = axis.z() * s;
00070 float ys = axis.y() * s;
00071 float xs = axis.x() * s;
00072 m.values[0][0] = axis.x()*axis.x()*cm + c;
00073 m.values[0][1] = xycm - zs;
00074 m.values[0][2] = xzcm + ys;
00075 m.values[0][3] = 0;
00076
00077 m.values[1][0] = xycm + zs;
00078 m.values[1][1] = axis.y()*axis.y()*cm + c;
00079 m.values[1][2] = yzcm - xs;
00080 m.values[1][3] = 0;
00081
00082 m.values[2][0] = xzcm - ys;
00083 m.values[2][1] = yzcm + xs;
00084 m.values[2][2] = axis.z()*axis.z()*cm + c;
00085 m.values[2][3] = 0;
00086
00087 for(int i = 0; i < 3; i++)
00088 m.values[3][i] = 0;
00089
00090 m.values[3][3] = 1;
00091
00092 return m;
00093 }
00094
00095 static Matrix4D translation(const Vec3D& vec)
00096 {
00097 Matrix4D m;
00098 for (int i = 0; i < 3; ++i)
00099 for (int j = 0; j < 3; ++j)
00100 m.values[i][j] = i == j ? 1 : 0;
00101 m.values[0][3] = vec.x();
00102 m.values[1][3] = vec.y();
00103 m.values[2][3] = vec.z();
00104 m.values[3][3] = 1;
00105
00106 return m;
00107 }
00108
00109 static Matrix4D getOrthoNormalBasis(const Vec3D& n, const Vec3D& v) {
00110 Matrix4D onb;
00111
00112 onb.values[0][2] = n.x();
00113 onb.values[1][2] = n.y();
00114 onb.values[2][2] = n.z();
00115
00116 Vec3D vp = v*(v*n)/(n*n);
00117 Vec3D t = (v-vp).normalize();
00118
00119 Vec3D b = (t.crossP(n)).normalize();
00120
00121
00122 onb.values[0][1] = t.x();
00123 onb.values[1][1] = t.y();
00124 onb.values[2][1] = t.z();
00125
00126 onb.values[0][0] = b.x();
00127 onb.values[1][0] = b.y();
00128 onb.values[2][0] = b.z();
00129 onb.values[3][3] = 1;
00130
00131 return onb;
00132 }
00133
00134 };
00135
00136 inline std::ostream& operator<<(std::ostream& out, const Matrix4D& m)
00137 {
00138 out<<"Matrix4D:"<<std::endl;
00139 out<<"/ "<<m.values[0][0]<<" "<<m.values[0][1]<<" "<<m.values[0][2]<<" "<<m.values[0][3]<<" \\"<<std::endl;;
00140 out<<"| "<<m.values[1][0]<<" "<<m.values[1][1]<<" "<<m.values[1][2]<<" "<<m.values[1][3]<<" |"<<std::endl;;
00141 out<<"| "<<m.values[2][0]<<" "<<m.values[2][1]<<" "<<m.values[2][2]<<" "<<m.values[2][3]<<" |"<<std::endl;;
00142 out<<"\\ "<<m.values[3][0]<<" "<<m.values[3][1]<<" "<<m.values[3][2]<<" "<<m.values[3][3]<<" /"<<std::endl;;
00143 return out;
00144 }
00145
00146 }
00147
00148 #endif