src/Matrix.h

Go to the documentation of this file.
00001 #ifndef MATRIX_H
00002 #define MATRIX_H
00003 
00004 #include <cassert>
00005 #include <iosfwd>
00006 
00007 #include "Vec3f.h"
00008 #include "Ray.h"
00009 
00010 
00015 class Matrix
00016 {
00017     // friends
00018     friend Matrix operator*(const Matrix &  m,  const float     f);
00019     friend Matrix operator*(const float     f,  const Matrix &  m);
00020     friend Vec3f  operator*(const Matrix &  m,  const Vec3f &   v);
00021     friend Vec3f  operator*(const Vec3f &   v,  const Matrix &  m);
00022     friend Ray    operator*(const Matrix &  m,  const Ray &     r);
00023     friend Ray    operator*(const Ray &     r,  const Matrix &  m);
00024     friend Matrix operator*(const Matrix &  m1, const Matrix &  m2);
00025     friend std::ostream & operator<<(std::ostream & o, const Matrix & m);
00026 
00027 public:     
00035     Matrix()
00036     {
00037         // initialize by identity matrix
00038         for (int i = 0; i < 4; i++)
00039         {
00040             for (int j = 0; j < 4; j++)
00041             {
00042                 if (i != j)
00043                     mValues[i][j] = 0.0f;
00044                 else
00045                     mValues[i][j] = 1.0f;
00046             }
00047         }
00048     }
00049 
00057     Matrix(const float f)
00058     {
00059         for(int i=0; i<4; i++)
00060         {
00061             for(int j=0; j<4; j++)
00062             {
00063                 mValues[i][j] = f;
00064             }
00065         }
00066     }
00067 
00079     Matrix(const float x, const float y, const float z)
00080     {
00081         for (int i = 0; i < 4; i++)
00082         {
00083             for (int j = 0; j < 4; j++)
00084             {
00085                 if (i != j)
00086                     mValues[i][j] = 0.0f;
00087             }
00088         }
00089         mValues[0][0] = x;
00090         mValues[1][1] = y;
00091         mValues[2][2] = z;
00092         mValues[3][3] = 1.0f;
00093     }
00094 
00104     Matrix(const Vec3f & t)
00105     {
00106         for (int i = 0; i < 4; i++)
00107         {
00108             for (int j = 0; j < 3; j++)
00109             {
00110                 if (i != j)
00111                     mValues[i][j] = 0.0f;
00112                 else
00113                     mValues[i][j] = 1.0f;
00114             }
00115         }
00116         mValues[0][3] = t.x();
00117         mValues[1][3] = t.y();
00118         mValues[2][3] = t.z();
00119         mValues[3][3] = 1.0f;
00120     }
00121 
00137     Matrix(const float angle, const Vec3f & axis)
00138     {
00139         const Vec3f a(axis.normal());
00140         const float c = cosf(angle);
00141         const float s = sinf(angle);
00142 
00143         mValues[0][0] = a.x()*a.x()*(1.0f - c) + c;
00144         mValues[0][1] = a.x()*a.y()*(1.0f - c) - a.z()*s;
00145         mValues[0][2] = a.x()*a.z()*(1.0f - c) + a.y()*s;
00146         mValues[0][3] = 0.0f;
00147 
00148         mValues[1][0] = a.y()*a.x()*(1.0f - c) + a.z()*s;
00149         mValues[1][1] = a.y()*a.y()*(1.0f - c) + c;
00150         mValues[1][2] = a.y()*a.z()*(1.0f - c) - a.x()*s;
00151         mValues[1][3] = 0.0f;
00152 
00153         mValues[2][0] = a.x()*a.z()*(1.0f - c) - a.y()*s;
00154         mValues[2][1] = a.y()*a.z()*(1.0f - c) + a.x()*s;
00155         mValues[2][2] = a.z()*a.z()*(1.0f - c) + c;
00156         mValues[2][3] = 0.0f;
00157 
00158         mValues[3][0] = 0.0f;
00159         mValues[3][1] = 0.0f;
00160         mValues[3][2] = 0.0f;
00161         mValues[3][3] = 1.0f;
00162     }
00163 
00170     void set(int x, int y, float value)
00171     {
00172         assert(x>=0 && x<4);
00173         assert(y>=0 && y<4);
00174         
00175         mValues[x][y] = value;
00176     }
00177 
00189     float get(int x, int y) const
00190     {
00191         assert(x>=0 && x<4);
00192         assert(y>=0 && y<4);
00193 
00194         return mValues[x][y];
00195     }
00196 
00199     inline Matrix & operator*=(const Matrix & m)
00200     {
00201         *this = (*this) * m;
00202         return *this;
00203     }
00204 
00208     inline Vec3f transformVector(const Vec3f & vector) const
00209     {
00210         float result[3];
00211         for(int i=0; i<3; i++)
00212         {
00213             result[i] = 0.0f;
00214             for(int j=0; j<3; j++)
00215             {
00216                 result[i] += (mValues[i][j] * vector[j]);
00217             }
00218             // 4-th dimension is set to 0
00219         }
00220         return Vec3f( result[0], result[1], result[2] );
00221     }
00222 
00223 private:
00224     float mValues[4][4];  
00225 };
00226 
00227 
00230 inline Matrix operator*(const Matrix & m, const float f)
00231 {
00232     Matrix result;
00233     for(int x=0; x<4; x++)
00234     {
00235         for(int y=0; y<4; y++)
00236         {
00237             result.mValues[x][y] = m.mValues[x][y] * f;
00238         }
00239     }
00240     return result;
00241 }
00242 
00243 
00246 inline Matrix operator*(const float f, const Matrix & m)
00247 {
00248     Matrix result;
00249     for(int x=0; x<4; x++)
00250     {
00251         for(int y=0; y<4; y++)
00252         {
00253             result.mValues[x][y] = m.mValues[x][y] * f;
00254         }
00255     }
00256     return result;
00257 }
00258 
00259 
00262 inline Vec3f operator*(const Matrix & m, const Vec3f & point)
00263 {
00264     float result[4];
00265     for(int i=0; i<4; i++)
00266     {
00267         result[i] = 0.0f;
00268         for(int j=0; j<3; j++)
00269         {
00270             result[i] += (m.mValues[i][j] * point[j]);
00271         }
00272         result[i] += (m.mValues[i][3]);  //emulating v has 4 dimensions with v[3]=1;
00273     }
00274 
00275     return Vec3f( result[0]/result[3], result[1]/result[3], result[2]/result[3] ); 
00276 }
00277 
00278 
00281 inline Vec3f operator*(const Vec3f & point, const Matrix & m)
00282 {
00283     LOG("Multiplying a 3D-point with the matrix should not be used unless you really know what you're doing");
00284     assert(false);
00285     float result[4];
00286     for(int i=0; i<4; i++)
00287     {
00288         result[i] = 0.0f;
00289         for(int j=0; j<3; j++)
00290         {
00291             result[i] += (point[i] * m.mValues[i][j]);
00292         }
00293         result[i] += m.mValues[i][3];
00294     }
00295     return Vec3f( result[0]/result[3], result[1]/result[3], result[2]/result[3] );
00296 }
00297 
00298 
00306 inline Ray operator*(const Matrix & m, const Ray & r)
00307 {
00308     Vec3f   org = m * r.org();
00309     Vec3f   dir = m.transformVector(r.dir());
00310 
00311     // transform t accordingly
00312     float   t = dir.length() * r.t();
00313 
00314     Ray result;
00315     result.init(org, dir);
00316     result.setHit(r.hit(), t);
00317     result.setObj(r.obj());
00318     result.setUV(r.u(), r.v()); // barycentric coordinates are invariant under affine transformations
00319     result.setInfluence(r.influence(), r.recDeep());
00320     return result;
00321 }
00322 
00323 
00326 inline Ray operator*(const Ray & /*r*/, const Matrix & /*m*/)
00327 {
00328     LOG("Left-sided multiplication of Ray and Matrix does not make any sense");
00329     assert(false);
00330     return Ray();
00331 }
00332 
00333 
00336 inline Matrix operator*(const Matrix & m1, const Matrix & m2)
00337 {
00338     Matrix result;
00339     for(int i=0; i<4; i++)
00340     {
00341         for(int j=0; j<4; j++)
00342         {
00343             float f = 0.0f;
00344             for(int k = 0; k<4; k++)
00345             {
00346                 f += m1.mValues[i][k] * m2.mValues[k][j];
00347             }
00348             result.mValues[i][j] = f;
00349         }
00350     }
00351     return result;
00352 }
00353 
00354 
00357 std::ostream & operator<<(std::ostream & o, const Matrix & m);
00358 
00359 
00360 #endif
00361 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1