Simple Vector Library 1.5 http://www.cs.cmu.edu/~ajw/doc/svl.html
Mat4.cpp
- Committer:
- BartJanssens
- Date:
- 2016-01-05
- Revision:
- 1:e25ff4b06ed2
- Parent:
- 0:785cff1e5a7c
File content as of revision 1:e25ff4b06ed2:
/* File: Mat4.cpp Function: Implements Mat4.h Author(s): Andrew Willmott Copyright: (c) 1995-2001, Andrew Willmott */ #include "Mat4.h" //#include <cctype> //#include <iomanip> Mat4::Mat4(Real a, Real b, Real c, Real d, Real e, Real f, Real g, Real h, Real i, Real j, Real k, Real l, Real m, Real n, Real o, Real p) { row[0][0] = a; row[0][1] = b; row[0][2] = c; row[0][3] = d; row[1][0] = e; row[1][1] = f; row[1][2] = g; row[1][3] = h; row[2][0] = i; row[2][1] = j; row[2][2] = k; row[2][3] = l; row[3][0] = m; row[3][1] = n; row[3][2] = o; row[3][3] = p; } Mat4::Mat4(const Mat4 &m) { row[0] = m[0]; row[1] = m[1]; row[2] = m[2]; row[3] = m[3]; } Mat4 &Mat4::operator = (const Mat4 &m) { row[0] = m[0]; row[1] = m[1]; row[2] = m[2]; row[3] = m[3]; return(SELF); } Mat4 &Mat4::operator += (const Mat4 &m) { row[0] += m[0]; row[1] += m[1]; row[2] += m[2]; row[3] += m[3]; return(SELF); } Mat4 &Mat4::operator -= (const Mat4 &m) { row[0] -= m[0]; row[1] -= m[1]; row[2] -= m[2]; row[3] -= m[3]; return(SELF); } Mat4 &Mat4::operator *= (const Mat4 &m) { SELF = SELF * m; return(SELF); } Mat4 &Mat4::operator *= (Real s) { row[0] *= s; row[1] *= s; row[2] *= s; row[3] *= s; return(SELF); } Mat4 &Mat4::operator /= (Real s) { row[0] /= s; row[1] /= s; row[2] /= s; row[3] /= s; return(SELF); } Bool Mat4::operator == (const Mat4 &m) const { return(row[0] == m[0] && row[1] == m[1] && row[2] == m[2] && row[3] == m[3]); } Bool Mat4::operator != (const Mat4 &m) const { return(row[0] != m[0] || row[1] != m[1] || row[2] != m[2] || row[3] != m[3]); } Mat4 Mat4::operator + (const Mat4 &m) const { Mat4 result; result[0] = row[0] + m[0]; result[1] = row[1] + m[1]; result[2] = row[2] + m[2]; result[3] = row[3] + m[3]; return(result); } Mat4 Mat4::operator - (const Mat4 &m) const { Mat4 result; result[0] = row[0] - m[0]; result[1] = row[1] - m[1]; result[2] = row[2] - m[2]; result[3] = row[3] - m[3]; return(result); } Mat4 Mat4::operator - () const { Mat4 result; result[0] = -row[0]; result[1] = -row[1]; result[2] = -row[2]; result[3] = -row[3]; return(result); } Mat4 Mat4::operator * (const Mat4 &m) const { #define N(x,y) row[x][y] #define M(x,y) m[x][y] #define R(x,y) result[x][y] Mat4 result; R(0,0) = N(0,0) * M(0,0) + N(0,1) * M(1,0) + N(0,2) * M(2,0) + N(0,3) * M(3,0); R(0,1) = N(0,0) * M(0,1) + N(0,1) * M(1,1) + N(0,2) * M(2,1) + N(0,3) * M(3,1); R(0,2) = N(0,0) * M(0,2) + N(0,1) * M(1,2) + N(0,2) * M(2,2) + N(0,3) * M(3,2); R(0,3) = N(0,0) * M(0,3) + N(0,1) * M(1,3) + N(0,2) * M(2,3) + N(0,3) * M(3,3); R(1,0) = N(1,0) * M(0,0) + N(1,1) * M(1,0) + N(1,2) * M(2,0) + N(1,3) * M(3,0); R(1,1) = N(1,0) * M(0,1) + N(1,1) * M(1,1) + N(1,2) * M(2,1) + N(1,3) * M(3,1); R(1,2) = N(1,0) * M(0,2) + N(1,1) * M(1,2) + N(1,2) * M(2,2) + N(1,3) * M(3,2); R(1,3) = N(1,0) * M(0,3) + N(1,1) * M(1,3) + N(1,2) * M(2,3) + N(1,3) * M(3,3); R(2,0) = N(2,0) * M(0,0) + N(2,1) * M(1,0) + N(2,2) * M(2,0) + N(2,3) * M(3,0); R(2,1) = N(2,0) * M(0,1) + N(2,1) * M(1,1) + N(2,2) * M(2,1) + N(2,3) * M(3,1); R(2,2) = N(2,0) * M(0,2) + N(2,1) * M(1,2) + N(2,2) * M(2,2) + N(2,3) * M(3,2); R(2,3) = N(2,0) * M(0,3) + N(2,1) * M(1,3) + N(2,2) * M(2,3) + N(2,3) * M(3,3); R(3,0) = N(3,0) * M(0,0) + N(3,1) * M(1,0) + N(3,2) * M(2,0) + N(3,3) * M(3,0); R(3,1) = N(3,0) * M(0,1) + N(3,1) * M(1,1) + N(3,2) * M(2,1) + N(3,3) * M(3,1); R(3,2) = N(3,0) * M(0,2) + N(3,1) * M(1,2) + N(3,2) * M(2,2) + N(3,3) * M(3,2); R(3,3) = N(3,0) * M(0,3) + N(3,1) * M(1,3) + N(3,2) * M(2,3) + N(3,3) * M(3,3); return(result); #undef N #undef M #undef R } Mat4 Mat4::operator * (Real s) const { Mat4 result; result[0] = row[0] * s; result[1] = row[1] * s; result[2] = row[2] * s; result[3] = row[3] * s; return(result); } Mat4 Mat4::operator / (Real s) const { Mat4 result; result[0] = row[0] / s; result[1] = row[1] / s; result[2] = row[2] / s; result[3] = row[3] / s; return(result); } Vec4 operator * (const Mat4 &m, const Vec4 &v) // m * v { Vec4 result; result[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + v[3] * m[0][3]; result[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + v[3] * m[1][3]; result[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + v[3] * m[2][3]; result[3] = v[0] * m[3][0] + v[1] * m[3][1] + v[2] * m[3][2] + v[3] * m[3][3]; return(result); } Vec4 operator * (const Vec4 &v, const Mat4 &m) // v * m { Vec4 result; result[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0]; result[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1]; result[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2]; result[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3]; return(result); } Vec4 &operator *= (Vec4 &v, const Mat4 &m) // v *= m { Real t0, t1, t2; t0 = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0]; t1 = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1]; t2 = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2]; v[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3]; v[0] = t0; v[1] = t1; v[2] = t2; return(v); } Mat4 trans(const Mat4 &m) { #define M(x,y) m[x][y] #define R(x,y) result[x][y] Mat4 result; R(0,0) = M(0,0); R(0,1) = M(1,0); R(0,2) = M(2,0); R(0,3) = M(3,0); R(1,0) = M(0,1); R(1,1) = M(1,1); R(1,2) = M(2,1); R(1,3) = M(3,1); R(2,0) = M(0,2); R(2,1) = M(1,2); R(2,2) = M(2,2); R(2,3) = M(3,2); R(3,0) = M(0,3); R(3,1) = M(1,3); R(3,2) = M(2,3); R(3,3) = M(3,3); return(result); #undef M #undef R } Mat4 adj(const Mat4 &m) { Mat4 result; result[0] = cross(m[1], m[2], m[3]); result[1] = -cross(m[0], m[2], m[3]); result[2] = cross(m[0], m[1], m[3]); result[3] = -cross(m[0], m[1], m[2]); return(result); } Real trace(const Mat4 &m) { return(m[0][0] + m[1][1] + m[2][2] + m[3][3]); } Real det(const Mat4 &m) { return(dot(m[0], cross(m[1], m[2], m[3]))); } Mat4 inv(const Mat4 &m) { Real mDet; Mat4 adjoint; Mat4 result; adjoint = adj(m); // Find the adjoint mDet = dot(adjoint[0], m[0]); Assert(mDet != 0, "(Mat4::inv) matrix is non-singular"); result = trans(adjoint); result /= mDet; return(result); } Mat4 oprod(const Vec4 &a, const Vec4 &b) // returns outerproduct of a and b: a * trans(b) { Mat4 result; result[0] = a[0] * b; result[1] = a[1] * b; result[2] = a[2] * b; result[3] = a[3] * b; return(result); } Void Mat4::MakeZero() { Int i; for (i = 0; i < 16; i++) ((Real *) row)[i] = vl_zero; } Void Mat4::MakeDiag(Real k) // default argument is vl_one { Int i, j; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) if (i == j) row[i][j] = k; else row[i][j] = vl_zero; } Void Mat4::MakeBlock(Real k) { Int i; for (i = 0; i < 16; i++) { //printf("i = %d k = %f\r\n",i,k); ((Real *) row)[i] = k; } } void printMat4(const Mat4 &m) { printf("["); printVec4(m[0]); printf("\r\n"); printVec4(m[1]); printf("\r\n"); printVec4(m[2]); printf("\r\n"); printVec4(m[3]); printf("]\r\n"); } /* ostream &operator << (ostream &s, const Mat4 &m) { Int w = s.width(); return(s << '[' << m[0] << "\r\n" << setw(w) << m[1] << "\r\n" << setw(w) << m[2] << "\r\n" << setw(w) << m[3] << ']' << "\r\n"); } istream &operator >> (istream &s, Mat4 &m) { Mat4 result; Char c; // Expected format: [[1 2 3] [4 5 6] [7 8 9]] // Each vector is a column of the matrix. while (s >> c && isspace(c)) // ignore leading white space ; if (c == '[') { s >> result[0] >> result[1] >> result[2] >> result[3]; if (!s) { cerr << "Expected number while reading matrix\n"; return(s); } while (s >> c && isspace(c)) ; if (c != ']') { s.clear(ios::failbit); cerr << "Expected ']' while reading matrix\n"; return(s); } } else { s.clear(ios::failbit); cerr << "Expected '[' while reading matrix\n"; return(s); } m = result; return(s); } */ Mat4& Mat4::MakeHRot(const Vec4 &q) { Real i2 = 2 * q[1], j2 = 2 * q[2], k2 = 2 * q[3], ij = i2 * q[2], ik = i2 * q[3], jk = j2 * q[3], ri = i2 * q[0], rj = j2 * q[0], rk = k2 * q[0]; MakeDiag(); i2 *= q[1]; j2 *= q[2]; k2 *= q[3]; #if VL_ROW_ORIENT row[0][0] = 1 - j2 - k2; row[0][1] = ij + rk ; row[0][2] = ik - rj; row[1][0] = ij - rk ; row[1][1] = 1 - i2- k2; row[1][2] = jk + ri; row[2][0] = ik + rj ; row[2][1] = jk - ri ; row[2][2] = 1 - i2 - j2; #else row[0][0] = 1 - j2 - k2; row[0][1] = ij - rk ; row[0][2] = ik + rj; row[1][0] = ij + rk ; row[1][1] = 1 - i2- k2; row[1][2] = jk - ri; row[2][0] = ik - rj ; row[2][1] = jk + ri ; row[2][2] = 1 - i2 - j2; #endif return(SELF); } Mat4& Mat4::MakeHRot(const Vec3 &axis, Real theta) { Real s; Vec4 q; theta /= 2.0; s = sin(theta); q[1] = s * axis[0]; q[2] = s * axis[1]; q[3] = s * axis[2]; q[0] = cos(theta); MakeHRot(q); return(SELF); } Mat4& Mat4::MakeHScale(const Vec3 &s) { MakeDiag(); row[0][0] = s[0]; row[1][1] = s[1]; row[2][2] = s[2]; return(SELF); } Mat4& Mat4::MakeHTrans(const Vec3 &t) { MakeDiag(); #ifdef VL_ROW_ORIENT row[3][0] = t[0]; row[3][1] = t[1]; row[3][2] = t[2]; #else row[0][3] = t[0]; row[1][3] = t[1]; row[2][3] = t[2]; #endif return(SELF); } Mat4& Mat4::Transpose() { row[0][1] = row[1][0]; row[0][2] = row[2][0]; row[0][3] = row[3][0]; row[1][0] = row[0][1]; row[1][2] = row[2][1]; row[1][3] = row[3][1]; row[2][0] = row[0][2]; row[2][1] = row[1][2]; row[2][3] = row[3][2]; row[3][0] = row[0][3]; row[3][1] = row[1][3]; row[3][2] = row[2][3]; return(SELF); } Mat4& Mat4::AddShift(const Vec3 &t) { #ifdef VL_ROW_ORIENT row[3][0] += t[0]; row[3][1] += t[1]; row[3][2] += t[2]; #else row[0][3] += t[0]; row[1][3] += t[1]; row[2][3] += t[2]; #endif return(SELF); }