home *** CD-ROM | disk | FTP | other *** search
- #ifndef _HMATRIX_H
- #define _HMATRIX_H
-
- #include "cmatrix.h"
- #include "hvector.h"
-
- #define HomogenousMatrixDeclare(T) \
- class HMat(T) { \
- protected: \
- T m[4][4]; \
- \
- public: \
- enum { columns, rows }; \
- \
- HMat(T)() {} \
- HMat(T)(int flag, \
- const HVec(T) &x, \
- const HVec(T) &y, \
- const HVec(T) &z, \
- const HVec(T) &w); \
- \
- const T *operator()(int i) const { \
- return m[i]; \
- } \
- T *operator[](int i) { return m[i]; } \
- HMat(T) &zero(); \
- HMat(T) &identity(); \
- \
- HMat(T) transpose() const; \
- \
- /* Dehomogenize a matrix */ \
- operator CMat(T)() const; \
- \
- /* Homogenize a matrix */ \
- HMat(T)(const CMat(T) &v); \
- }; \
- \
- HVec(T) operator*(const HMat(T) &m, const HVec(T) &v); \
- HVec(T) operator*(const HVec(T) &v, const HMat(T) &m); \
- HMat(T) operator*(const HMat(T) &a, const HMat(T) &b); \
- /* These are for transformation matrices */ \
- inline HMat(T) operator*( \
- const HMat(T) &a, \
- const CMat(T) &b) \
- { \
- return a * HMat(T)(b); \
- } \
- inline HMat(T) operator*( \
- const CMat(T) &a, \
- const HMat(T) &b) \
- { \
- return HMat(T)(a) * b; \
- } \
- \
- /* Only implemented for HMat(float) */ \
- HMat(T) adjoint(const HMat(T) &m, T *det = NULL); \
- \
- HMat(T) view_matrix( \
- const HVec(T) &eye, \
- const HVec(T) &lookat, \
- const HVec(T) &vup); \
- HMat(T) perspective_matrix(T fov, T znear, T zfar); \
- HMat(T) screen_matrix(T size, T offset); \
- \
- ostream &operator<<(ostream &o, const HMat(T) &m);
-
- #define HomogenousMatrixImplement(T) \
- \
- static const int \
- X = 0, \
- Y = 1, \
- Z = 2, \
- W = 3; \
- \
- /* Initialize a matrix by either columns or rows */ \
- HMat(T)::HMat(T)( \
- int flag, \
- const HVec(T) &x, \
- const HVec(T) &y, \
- const HVec(T) &z, \
- const HVec(T) &w) \
- { \
- for (int i = X; i <= W; i++) { \
- if (flag == HMat(T)::columns) { \
- m[i][X] = x(i); \
- m[i][Y] = y(i); \
- m[i][Z] = z(i); \
- m[i][W] = w(i); \
- } else if (flag == HMat(T)::rows) { \
- m[X][i] = x(i); \
- m[Y][i] = y(i); \
- m[Z][i] = z(i); \
- m[W][i] = w(i); \
- } else { \
- cerr << "HMat(T)::HMat(T): bad flag " \
- << "(not rows or columns)" << endl; \
- zero(); \
- } \
- } \
- } \
- \
- HMat(T) &HMat(T)::zero() { \
- for (int i = X; i <= W ; i++) \
- for (int j = X; j <= W; j++) \
- m[i][j] = 0; \
- return *this; \
- } \
- \
- HMat(T) &HMat(T)::identity() { \
- for (int i = X; i <= W ; i++) \
- for (int j = X; j <= W; j++) \
- m[i][j] = (i == j); \
- return *this; \
- } \
- \
- /* Return the transpose of a matrix */ \
- HMat(T) HMat(T)::transpose() const { \
- HMat(T) tran; \
- \
- for (int i = X; i <= W; i++) \
- for (int j = X; j <= W; j++) \
- tran[i][j] = m[j][i]; \
- \
- return tran; \
- } \
- \
- /* Dehomogenize a matrix */ \
- HMat(T)::operator CMat(T)() const { \
- CMat(T) res; \
- \
- for (int i = X; i <= Z; i++) \
- for (int j = X; j <= W; j++) \
- res[i][j] = m[i][j]; \
- \
- return res; \
- } \
- \
- HMat(T)::HMat(T)(const CMat(T) &v) { \
- for (int i = X; i <= Z; i++) \
- for (int j = X; j <= W; j++) \
- m[i][j] = v(i)[j]; \
- \
- /* No perspective component */ \
- m[W][X] = m[W][Y] = m[W][Z] = 0; \
- m[W][W] = 1; \
- } \
- \
- /* M = M * V */ \
- HVec(T) operator*(const HMat(T) &m, const HVec(T) &v) { \
- return HVec(T)( \
- m(X)[X]*v(X)+m(X)[Y]*v(Y)+m(X)[Z]*v(Z)+m(X)[W]*v(W), \
- m(Y)[X]*v(X)+m(Y)[Y]*v(Y)+m(Y)[Z]*v(Z)+m(Y)[W]*v(W), \
- m(Z)[X]*v(X)+m(Z)[Y]*v(Y)+m(Z)[Z]*v(Z)+m(Z)[W]*v(W), \
- m(W)[X]*v(X)+m(W)[Y]*v(Y)+m(W)[Z]*v(Z)+m(W)[W]*v(W)); \
- } \
- \
- /* M = V * M */ \
- HVec(T) operator*(const HVec(T) &v, const HMat(T) &m) { \
- return HVec(T)( \
- m(X)[X]*v(X)+m(Y)[X]*v(Y)+m(Z)[X]*v(Z)+m(W)[X]*v(W), \
- m(X)[Y]*v(X)+m(Y)[Y]*v(Y)+m(Z)[Y]*v(Z)+m(W)[Y]*v(W), \
- m(X)[Z]*v(X)+m(Y)[Z]*v(Y)+m(Z)[Z]*v(Z)+m(W)[Z]*v(W), \
- m(X)[W]*v(X)+m(Y)[W]*v(Y)+m(Z)[W]*v(Z)+m(W)[W]*v(W)); \
- } \
- \
- /* M = M * M */ \
- HMat(T) operator*(const HMat(T) &a, const HMat(T) &b) { \
- HMat(T) res; \
- \
- for (int i = X; i <= W; i++) { \
- for (int j = X; j <= W; j++) { \
- res[i][j] = 0; \
- for (int k = X; k <= W; k++) \
- res[i][j] += a(i)[k] * b(k)[j]; \
- } \
- } \
- \
- return res; \
- } \
- \
- /* Construct a viewing matrix which effects a translation \
- * of the eye to the origin, the lookat - eye vector to \
- * the -Z axis, and the vup vector to the +Y axis. \
- * This is drawn from PPHIGS but done in RHS. \
- */ \
- HMat(T) view_matrix( \
- const HVec(T) &eye, \
- const HVec(T) &lookat, \
- const HVec(T) &vup) \
- { \
- static HVec(T) zero(0,0,0,1); \
- HVec(T) w = eye - lookat; /* Look vector */ \
- \
- /* Translate eye to origin */ \
- HMat(T) trans; \
- trans.identity(); \
- trans = trans * translation_matrix(-eye); \
- \
- /* Construct an orthogonal basis whose up \
- * vector v is as close to vup as possible \
- */ \
- HVec(T) u = vup ^ w; \
- HVec(T) v = w ^ u; \
- \
- u.normalize(); u[W] = 0; \
- v.normalize(); v[W] = 0; \
- w.normalize(); w[W] = 0; \
- \
- HMat(T) frame(HMat(T)::rows, u, v, w, zero); \
- \
- return frame * trans; \
- } \
- \
- /* Construct a Blinn-style perspective matrix, with specified \
- * near and far clipping planes and field of view (in degrees): \
- * \
- * | cos theta 0 0 0 | \
- * | | \
- * | | \
- * | 0 cos theta 0 0 | \
- * | | \
- * | sin theta Zf sin theta Zf Zn | \
- * | 0 0 ------------ --------------- | \
- * | Zf - Zn Zf - Zn | \
- * | | \
- * | 0 0 sin theta 0 | \
- * \
- * This transforms into the canonical [-1..1]^2 window. Z \
- * *decreases* with increasing depth in world space, and \
- * *increases* with increasing depth in screen space \
- * x' = tan theta x/-z \
- * y' = tan theta y/-z \
- * Zf Zn \
- * z' = ------- (1 + --) -> z'(-Zn) = 0, z'(-Zf) = 1 \
- * Zf - Zn z \
- */ \
- HMat(T) perspective_matrix(float fov, float Zn, float Zf) { \
- fov = dtor(fov); \
- \
- float ct = cos(fov/2), st = sin(fov/2), \
- zs = st * Zf / (Zf - Zn); \
- HMat(T) p; \
- \
- p.zero(); \
- /* Note that the third column is all negated so Z \
- * increases away from the eye (in RHS, we look \
- * down -Z instead of +Z). \
- */ \
- p[X][X] = ct; \
- p[Y][Y] = ct; \
- p[Z][Z] =-zs; p[Z][W] =-zs * Zn; \
- p[W][Z] =-st; \
- \
- return p; \
- } \
- \
- /* Construct a matrix that transforms from the canonical \
- * [-1..1]^2 window to a window of specified size and offset. \
- */ \
- HMat(T) screen_matrix(float size, float offset) { \
- HMat(T) p; \
- \
- p.zero(); \
- p[X][X] = size/2; p[X][W] = offset; \
- p[Y][Y] = size/2; p[Y][W] = offset; \
- p[Z][Z] = 1; \
- p[W][W] = 1; \
- \
- return p; \
- } \
- \
- ostream &operator<<(ostream &o, const HMat(T) &m) { \
- for (int i = X; i <= W; i++) \
- o << '\t' << "( " \
- << setw(8) << m(i)[X] << ' ' \
- << setw(8) << m(i)[Y] << ' ' \
- << setw(8) << m(i)[Z] << ' ' \
- << setw(8) << m(i)[W] << " )\n"; \
- \
- return o; \
- }
-
- HomogenousMatrixDeclare(float);
-
- typedef HMat(float) HMatrix;
-
- #endif /*_HMATRIX_H*/
-