/* (c) 1999-2000 Tino Schwarze, see COPYING for details */
/**@pkg math */
/*
* matrix math class plus implementation
*
* contains:
* - class cMatrix - 4x4 matrix class interfacing nicely with cVertex
*/
#ifndef cMatrix_hh
#define cMatrix_hh
#include "common.hh"
#include "cVertex.hh" // aquire class cVertex
/**
* A class for representing a 4x4 matrix. It supports matrix math too.
*
* this really simplifies matrix math! :-)
* oh, not to forget: my matrix is built as follows:
* (due to OpenGL's convention to store matrices column-major - argh!)
*
* _ _
* | |
* | x y z 0 |
* | x x x |
* | |
* | x y z 0 |
* | y y y |
* | |
* | x y z 0 |
* | z z z |
* | |
* | p p p 1 |
* | x y z |
* |_ _|
*
*
* (x
x, x
y, x
z) is the x-axis
*
* (y
x, y
y, y
z) is the y-axis
*
* (z
x, z
y, z
z) is the z-axis
*
* (p
x, p
y, p
z) is the translation
*/
class cMatrix
{
public:
/**
* Matrix data made public to allow direct access
*
* (operator[] doesnt work with 2-dimensional fields... :-( )
* has anyone a better idea? */
GLfloat mMatrix[4][4];
/**
* default constructor (initializes to identity)
*/
cMatrix ()
{
ENTER_METHOD("cMatrix::cMatrix()");
Identity ();
}
#if DEBUG
/**
* destructor (for debugging purposes only)
*/
~cMatrix ()
{
ENTER_METHOD("cMatrix::~cMatrix()");
}
#endif
#if DEBUG
/**
* copy constructor for debugging purposes only
* @param m cMatrix to copy
*/
cMatrix (const cMatrix &m)
{
ENTER_METHOD("cMatrix::cMatrix(const cMatrix &)");
memcpy ((void *)&mMatrix, (void *)&m.mMatrix, sizeof (mMatrix));
}
#endif
// OPERATORS
/**
* an operator for matrix multiplication
* @param m matrix to multiply with
* @return reference to self
*/
/**@#-*/
inline class cMatrix &operator*= (const class cMatrix &m)
{
GLfloat temp[4][4]; // temporary mMatrix for storing result
int i, j; // row and column counters
for (j = 0; j < 4; j++) // transform by columns first
for (i = 0; i < 4; i++) // then by rows
temp[i][j] = mMatrix[i][0] * m.mMatrix[0][j] + mMatrix[i][1] * m.mMatrix[1][j] +
mMatrix[i][2] * m.mMatrix[2][j] + mMatrix[i][3] * m.mMatrix[3][j];
// copy temp into mMatrix (ANSI does not allow array
// assignment)
memcpy ((void *)&mMatrix, (void *)&temp, sizeof (temp));
return *this;
};
/**@#+*/
/**
* an operator to multiply a vector with an matrix
* (which means transforming the vector by the matrix)
*/
inline cVertex operator* (const cVertex &v)
{
cVertex tmp;
tmp[0] = mMatrix[0][0]*v.GetX() + mMatrix[1][0]*v.GetY() + mMatrix[2][0]*v.GetZ() + mMatrix[3][0];
tmp[1] = mMatrix[0][1]*v.GetX() + mMatrix[1][1]*v.GetY() + mMatrix[2][1]*v.GetZ() + mMatrix[3][1];
tmp[2] = mMatrix[0][2]*v.GetX() + mMatrix[1][2]*v.GetY() + mMatrix[2][2]*v.GetZ() + mMatrix[3][2];
return tmp;
};
/**
* an operator to inversely multiply a vector with an matrix
* (which means transforming the vector by the matrix's inverse)
*/
inline cVertex operator/ (const cVertex &v)
{
cVertex tmp;
tmp[0] = mMatrix[0][0]*v.GetX() + mMatrix[0][1]*v.GetY() + mMatrix[0][2]*v.GetZ();// + mMatrix[3][0];
tmp[1] = mMatrix[1][0]*v.GetX() + mMatrix[1][1]*v.GetY() + mMatrix[1][2]*v.GetZ();// + mMatrix[3][1];
tmp[2] = mMatrix[2][0]*v.GetX() + mMatrix[2][1]*v.GetY() + mMatrix[2][2]*v.GetZ();// + mMatrix[3][2];
return tmp;
};
// assignment operator not neccessary (generated by compiler)
/**
* operator to "convert" matrix to an pointer to GLfloat
*/
inline operator GLfloat *()
{
return (GLfloat *)mMatrix;
}
// OPERATIONS
/**
* Initialize matrix to identity
* @return reference to cMatrix object (for convenience)
*/
inline cMatrix &Identity ()
{
memset ((void *)&mMatrix, 0, sizeof (mMatrix));
for (int i = 0; i < 4; i++) mMatrix[i][i] = 1;
return *this;
};
/**
* "normalize" the matrix by normalizing the axis components
*
* This is a very special operation which is only sometimes
* useful to get orthonormal bases.
*
* @return reference to cMatrix object
*/
inline cMatrix &Normalize () // normalize the axis components
{
for (int c = 0; c < 3; c++) // process each column
{
const GLfloat nl = 1/sqrt (mMatrix[0][c]*mMatrix[0][c] + mMatrix[1][c]*mMatrix[1][c] + mMatrix[2][c]*mMatrix[2][c]);
mMatrix[0][c] *= nl;
mMatrix[1][c] *= nl;
mMatrix[2][c] *= nl;
}
return *this;
};
/**
* translate/move origin of matrix
* @param v amount to translate
*/
inline void Translate (const cVertex &v)
{
mMatrix[3][0] += v.GetX();
mMatrix[3][1] += v.GetY();
mMatrix[3][2] += v.GetZ();
};
/**
* translate/move origin of matrix
* @param x distance to translate
* @param y distance to translate
* @param z distance to translate
*/
inline void Translate (
const GLfloat x,
const GLfloat y,
const GLfloat z)
{
mMatrix[3][0] += x;
mMatrix[3][1] += y;
mMatrix[3][2] += z;
};
};
#endif // ifndef cMatrix_hh
/* vim:ts=4:smartindent:
*/