// Geometric Tools, LLC // Copyright (c) 1998-2012 // Distributed under the Boost Software License, Version 1.0. // http://www.boost.org/LICENSE_1_0.txt // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt // // File Version: 5.0.0 (2010/01/01) //---------------------------------------------------------------------------- template Matrix4::Matrix4 (bool makeZero) { if (makeZero) { MakeZero(); } else { MakeIdentity(); } } //---------------------------------------------------------------------------- template Matrix4::Matrix4 (const Matrix4& mat) { mEntry[ 0] = mat.mEntry[ 0]; mEntry[ 1] = mat.mEntry[ 1]; mEntry[ 2] = mat.mEntry[ 2]; mEntry[ 3] = mat.mEntry[ 3]; mEntry[ 4] = mat.mEntry[ 4]; mEntry[ 5] = mat.mEntry[ 5]; mEntry[ 6] = mat.mEntry[ 6]; mEntry[ 7] = mat.mEntry[ 7]; mEntry[ 8] = mat.mEntry[ 8]; mEntry[ 9] = mat.mEntry[ 9]; mEntry[10] = mat.mEntry[10]; mEntry[11] = mat.mEntry[11]; mEntry[12] = mat.mEntry[12]; mEntry[13] = mat.mEntry[13]; mEntry[14] = mat.mEntry[14]; mEntry[15] = mat.mEntry[15]; } //---------------------------------------------------------------------------- template Matrix4::Matrix4 (Real m00, Real m01, Real m02, Real m03, Real m10, Real m11, Real m12, Real m13, Real m20, Real m21, Real m22, Real m23, Real m30, Real m31, Real m32, Real m33) { mEntry[ 0] = m00; mEntry[ 1] = m01; mEntry[ 2] = m02; mEntry[ 3] = m03; mEntry[ 4] = m10; mEntry[ 5] = m11; mEntry[ 6] = m12; mEntry[ 7] = m13; mEntry[ 8] = m20; mEntry[ 9] = m21; mEntry[10] = m22; mEntry[11] = m23; mEntry[12] = m30; mEntry[13] = m31; mEntry[14] = m32; mEntry[15] = m33; } //---------------------------------------------------------------------------- template Matrix4::Matrix4 (const Real entry[16], bool rowMajor) { if (rowMajor) { mEntry[ 0] = entry[ 0]; mEntry[ 1] = entry[ 1]; mEntry[ 2] = entry[ 2]; mEntry[ 3] = entry[ 3]; mEntry[ 4] = entry[ 4]; mEntry[ 5] = entry[ 5]; mEntry[ 6] = entry[ 6]; mEntry[ 7] = entry[ 7]; mEntry[ 8] = entry[ 8]; mEntry[ 9] = entry[ 9]; mEntry[10] = entry[10]; mEntry[11] = entry[11]; mEntry[12] = entry[12]; mEntry[13] = entry[13]; mEntry[14] = entry[14]; mEntry[15] = entry[15]; } else { mEntry[ 0] = entry[ 0]; mEntry[ 1] = entry[ 4]; mEntry[ 2] = entry[ 8]; mEntry[ 3] = entry[12]; mEntry[ 4] = entry[ 1]; mEntry[ 5] = entry[ 5]; mEntry[ 6] = entry[ 9]; mEntry[ 7] = entry[13]; mEntry[ 8] = entry[ 2]; mEntry[ 9] = entry[ 6]; mEntry[10] = entry[10]; mEntry[11] = entry[14]; mEntry[12] = entry[ 3]; mEntry[13] = entry[ 7]; mEntry[14] = entry[11]; mEntry[15] = entry[15]; } } //---------------------------------------------------------------------------- template Matrix4& Matrix4::operator= (const Matrix4& mat) { mEntry[ 0] = mat.mEntry[ 0]; mEntry[ 1] = mat.mEntry[ 1]; mEntry[ 2] = mat.mEntry[ 2]; mEntry[ 3] = mat.mEntry[ 3]; mEntry[ 4] = mat.mEntry[ 4]; mEntry[ 5] = mat.mEntry[ 5]; mEntry[ 6] = mat.mEntry[ 6]; mEntry[ 7] = mat.mEntry[ 7]; mEntry[ 8] = mat.mEntry[ 8]; mEntry[ 9] = mat.mEntry[ 9]; mEntry[10] = mat.mEntry[10]; mEntry[11] = mat.mEntry[11]; mEntry[12] = mat.mEntry[12]; mEntry[13] = mat.mEntry[13]; mEntry[14] = mat.mEntry[14]; mEntry[15] = mat.mEntry[15]; return *this; } //---------------------------------------------------------------------------- template void Matrix4::MakeZero () { mEntry[ 0] = (Real)0; mEntry[ 1] = (Real)0; mEntry[ 2] = (Real)0; mEntry[ 3] = (Real)0; mEntry[ 4] = (Real)0; mEntry[ 5] = (Real)0; mEntry[ 6] = (Real)0; mEntry[ 7] = (Real)0; mEntry[ 8] = (Real)0; mEntry[ 9] = (Real)0; mEntry[10] = (Real)0; mEntry[11] = (Real)0; mEntry[12] = (Real)0; mEntry[13] = (Real)0; mEntry[14] = (Real)0; mEntry[15] = (Real)0; } //---------------------------------------------------------------------------- template void Matrix4::MakeIdentity () { mEntry[ 0] = (Real)1; mEntry[ 1] = (Real)0; mEntry[ 2] = (Real)0; mEntry[ 3] = (Real)0; mEntry[ 4] = (Real)0; mEntry[ 5] = (Real)1; mEntry[ 6] = (Real)0; mEntry[ 7] = (Real)0; mEntry[ 8] = (Real)0; mEntry[ 9] = (Real)0; mEntry[10] = (Real)1; mEntry[11] = (Real)0; mEntry[12] = (Real)0; mEntry[13] = (Real)0; mEntry[14] = (Real)0; mEntry[15] = (Real)1; } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator+ (const Matrix4& mat) const { return Matrix4 ( mEntry[ 0] + mat.mEntry[ 0], mEntry[ 1] + mat.mEntry[ 1], mEntry[ 2] + mat.mEntry[ 2], mEntry[ 3] + mat.mEntry[ 3], mEntry[ 4] + mat.mEntry[ 4], mEntry[ 5] + mat.mEntry[ 5], mEntry[ 6] + mat.mEntry[ 6], mEntry[ 7] + mat.mEntry[ 7], mEntry[ 8] + mat.mEntry[ 8], mEntry[ 9] + mat.mEntry[ 9], mEntry[10] + mat.mEntry[10], mEntry[11] + mat.mEntry[11], mEntry[12] + mat.mEntry[12], mEntry[13] + mat.mEntry[13], mEntry[14] + mat.mEntry[14], mEntry[15] + mat.mEntry[15] ); } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator- (const Matrix4& mat) const { return Matrix4 ( mEntry[ 0] - mat.mEntry[ 0], mEntry[ 1] - mat.mEntry[ 1], mEntry[ 2] - mat.mEntry[ 2], mEntry[ 3] - mat.mEntry[ 3], mEntry[ 4] - mat.mEntry[ 4], mEntry[ 5] - mat.mEntry[ 5], mEntry[ 6] - mat.mEntry[ 6], mEntry[ 7] - mat.mEntry[ 7], mEntry[ 8] - mat.mEntry[ 8], mEntry[ 9] - mat.mEntry[ 9], mEntry[10] - mat.mEntry[10], mEntry[11] - mat.mEntry[11], mEntry[12] - mat.mEntry[12], mEntry[13] - mat.mEntry[13], mEntry[14] - mat.mEntry[14], mEntry[15] - mat.mEntry[15] ); } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator* (Real scalar) const { return Matrix4 ( scalar*mEntry[ 0], scalar*mEntry[ 1], scalar*mEntry[ 2], scalar*mEntry[ 3], scalar*mEntry[ 4], scalar*mEntry[ 5], scalar*mEntry[ 6], scalar*mEntry[ 7], scalar*mEntry[ 8], scalar*mEntry[ 9], scalar*mEntry[10], scalar*mEntry[11], scalar*mEntry[12], scalar*mEntry[13], scalar*mEntry[14], scalar*mEntry[15] ); } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator/ (Real scalar) const { if (scalar != (Real)0) { Real invScalar = ((Real)1)/scalar; return Matrix4 ( invScalar*mEntry[ 0], invScalar*mEntry[ 1], invScalar*mEntry[ 2], invScalar*mEntry[ 3], invScalar*mEntry[ 4], invScalar*mEntry[ 5], invScalar*mEntry[ 6], invScalar*mEntry[ 7], invScalar*mEntry[ 8], invScalar*mEntry[ 9], invScalar*mEntry[10], invScalar*mEntry[11], invScalar*mEntry[12], invScalar*mEntry[13], invScalar*mEntry[14], invScalar*mEntry[15] ); } else { return Matrix4 ( Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL, Math::MAX_REAL ); } } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator- () const { return Matrix4 ( -mEntry[ 0], -mEntry[ 1], -mEntry[ 2], -mEntry[ 3], -mEntry[ 4], -mEntry[ 5], -mEntry[ 6], -mEntry[ 7], -mEntry[ 8], -mEntry[ 9], -mEntry[10], -mEntry[11], -mEntry[12], -mEntry[13], -mEntry[14], -mEntry[15] ); } //---------------------------------------------------------------------------- template inline Matrix4& Matrix4::operator+= (const Matrix4& mat) { mEntry[ 0] += mat.mEntry[ 0]; mEntry[ 1] += mat.mEntry[ 1]; mEntry[ 2] += mat.mEntry[ 2]; mEntry[ 3] += mat.mEntry[ 3]; mEntry[ 4] += mat.mEntry[ 4]; mEntry[ 5] += mat.mEntry[ 5]; mEntry[ 6] += mat.mEntry[ 6]; mEntry[ 7] += mat.mEntry[ 7]; mEntry[ 8] += mat.mEntry[ 8]; mEntry[ 9] += mat.mEntry[ 9]; mEntry[10] += mat.mEntry[10]; mEntry[11] += mat.mEntry[11]; mEntry[12] += mat.mEntry[12]; mEntry[13] += mat.mEntry[13]; mEntry[14] += mat.mEntry[14]; mEntry[15] += mat.mEntry[15]; return *this; } //---------------------------------------------------------------------------- template inline Matrix4& Matrix4::operator-= (const Matrix4& mat) { mEntry[ 0] -= mat.mEntry[ 0]; mEntry[ 1] -= mat.mEntry[ 1]; mEntry[ 2] -= mat.mEntry[ 2]; mEntry[ 3] -= mat.mEntry[ 3]; mEntry[ 4] -= mat.mEntry[ 4]; mEntry[ 5] -= mat.mEntry[ 5]; mEntry[ 6] -= mat.mEntry[ 6]; mEntry[ 7] -= mat.mEntry[ 7]; mEntry[ 8] -= mat.mEntry[ 8]; mEntry[ 9] -= mat.mEntry[ 9]; mEntry[10] -= mat.mEntry[10]; mEntry[11] -= mat.mEntry[11]; mEntry[12] -= mat.mEntry[12]; mEntry[13] -= mat.mEntry[13]; mEntry[14] -= mat.mEntry[14]; mEntry[15] -= mat.mEntry[15]; return *this; } //---------------------------------------------------------------------------- template inline Matrix4& Matrix4::operator*= (Real scalar) { mEntry[ 0] *= scalar; mEntry[ 1] *= scalar; mEntry[ 2] *= scalar; mEntry[ 3] *= scalar; mEntry[ 4] *= scalar; mEntry[ 5] *= scalar; mEntry[ 6] *= scalar; mEntry[ 7] *= scalar; mEntry[ 8] *= scalar; mEntry[ 9] *= scalar; mEntry[10] *= scalar; mEntry[11] *= scalar; mEntry[12] *= scalar; mEntry[13] *= scalar; mEntry[14] *= scalar; mEntry[15] *= scalar; return *this; } //---------------------------------------------------------------------------- template inline Matrix4& Matrix4::operator/= (Real scalar) { if (scalar != (Real)0) { Real invScalar = ((Real)1)/scalar; mEntry[ 0] *= invScalar; mEntry[ 1] *= invScalar; mEntry[ 2] *= invScalar; mEntry[ 3] *= invScalar; mEntry[ 4] *= invScalar; mEntry[ 5] *= invScalar; mEntry[ 6] *= invScalar; mEntry[ 7] *= invScalar; mEntry[ 8] *= invScalar; mEntry[ 9] *= invScalar; mEntry[10] *= invScalar; mEntry[11] *= invScalar; mEntry[12] *= invScalar; mEntry[13] *= invScalar; mEntry[14] *= invScalar; mEntry[15] *= invScalar; } else { mEntry[ 0] = Math::MAX_REAL; mEntry[ 1] = Math::MAX_REAL; mEntry[ 2] = Math::MAX_REAL; mEntry[ 3] = Math::MAX_REAL; mEntry[ 4] = Math::MAX_REAL; mEntry[ 5] = Math::MAX_REAL; mEntry[ 6] = Math::MAX_REAL; mEntry[ 7] = Math::MAX_REAL; mEntry[ 8] = Math::MAX_REAL; mEntry[ 9] = Math::MAX_REAL; mEntry[10] = Math::MAX_REAL; mEntry[11] = Math::MAX_REAL; mEntry[12] = Math::MAX_REAL; mEntry[13] = Math::MAX_REAL; mEntry[14] = Math::MAX_REAL; mEntry[15] = Math::MAX_REAL; } return *this; } //---------------------------------------------------------------------------- template inline Vector4 Matrix4::operator* (const Vector4& vec) const { return Vector4 ( mEntry[ 0]*vec[0] + mEntry[ 1]*vec[1] + mEntry[ 2]*vec[2] + mEntry[ 3]*vec[3], mEntry[ 4]*vec[0] + mEntry[ 5]*vec[1] + mEntry[ 6]*vec[2] + mEntry[ 7]*vec[3], mEntry[ 8]*vec[0] + mEntry[ 9]*vec[1] + mEntry[10]*vec[2] + mEntry[11]*vec[3], mEntry[12]*vec[0] + mEntry[13]*vec[1] + mEntry[14]*vec[2] + mEntry[15]*vec[3] ); } //---------------------------------------------------------------------------- template Matrix4 Matrix4::Transpose () const { return Matrix4 ( mEntry[ 0], mEntry[ 4], mEntry[ 8], mEntry[12], mEntry[ 1], mEntry[ 5], mEntry[ 9], mEntry[13], mEntry[ 2], mEntry[ 6], mEntry[10], mEntry[14], mEntry[ 3], mEntry[ 7], mEntry[11], mEntry[15] ); } //---------------------------------------------------------------------------- template inline Matrix4 Matrix4::operator* (const Matrix4& mat) const { // A*B return Matrix4 ( mEntry[ 0]*mat.mEntry[ 0] + mEntry[ 1]*mat.mEntry[ 4] + mEntry[ 2]*mat.mEntry[ 8] + mEntry[ 3]*mat.mEntry[12], mEntry[ 0]*mat.mEntry[ 1] + mEntry[ 1]*mat.mEntry[ 5] + mEntry[ 2]*mat.mEntry[ 9] + mEntry[ 3]*mat.mEntry[13], mEntry[ 0]*mat.mEntry[ 2] + mEntry[ 1]*mat.mEntry[ 6] + mEntry[ 2]*mat.mEntry[10] + mEntry[ 3]*mat.mEntry[14], mEntry[ 0]*mat.mEntry[ 3] + mEntry[ 1]*mat.mEntry[ 7] + mEntry[ 2]*mat.mEntry[11] + mEntry[ 3]*mat.mEntry[15], mEntry[ 4]*mat.mEntry[ 0] + mEntry[ 5]*mat.mEntry[ 4] + mEntry[ 6]*mat.mEntry[ 8] + mEntry[ 7]*mat.mEntry[12], mEntry[ 4]*mat.mEntry[ 1] + mEntry[ 5]*mat.mEntry[ 5] + mEntry[ 6]*mat.mEntry[ 9] + mEntry[ 7]*mat.mEntry[13], mEntry[ 4]*mat.mEntry[ 2] + mEntry[ 5]*mat.mEntry[ 6] + mEntry[ 6]*mat.mEntry[10] + mEntry[ 7]*mat.mEntry[14], mEntry[ 4]*mat.mEntry[ 3] + mEntry[ 5]*mat.mEntry[ 7] + mEntry[ 6]*mat.mEntry[11] + mEntry[ 7]*mat.mEntry[15], mEntry[ 8]*mat.mEntry[ 0] + mEntry[ 9]*mat.mEntry[ 4] + mEntry[10]*mat.mEntry[ 8] + mEntry[11]*mat.mEntry[12], mEntry[ 8]*mat.mEntry[ 1] + mEntry[ 9]*mat.mEntry[ 5] + mEntry[10]*mat.mEntry[ 9] + mEntry[11]*mat.mEntry[13], mEntry[ 8]*mat.mEntry[ 2] + mEntry[ 9]*mat.mEntry[ 6] + mEntry[10]*mat.mEntry[10] + mEntry[11]*mat.mEntry[14], mEntry[ 8]*mat.mEntry[ 3] + mEntry[ 9]*mat.mEntry[ 7] + mEntry[10]*mat.mEntry[11] + mEntry[11]*mat.mEntry[15], mEntry[12]*mat.mEntry[ 0] + mEntry[13]*mat.mEntry[ 4] + mEntry[14]*mat.mEntry[ 8] + mEntry[15]*mat.mEntry[12], mEntry[12]*mat.mEntry[ 1] + mEntry[13]*mat.mEntry[ 5] + mEntry[14]*mat.mEntry[ 9] + mEntry[15]*mat.mEntry[13], mEntry[12]*mat.mEntry[ 2] + mEntry[13]*mat.mEntry[ 6] + mEntry[14]*mat.mEntry[10] + mEntry[15]*mat.mEntry[14], mEntry[12]*mat.mEntry[ 3] + mEntry[13]*mat.mEntry[ 7] + mEntry[14]*mat.mEntry[11] + mEntry[15]*mat.mEntry[15] ); } //---------------------------------------------------------------------------- template Matrix4 Matrix4::TransposeTimes (const Matrix4& mat) const { // A^T*B return Matrix4 ( mEntry[ 0]*mat.mEntry[ 0] + mEntry[ 4]*mat.mEntry[ 4] + mEntry[ 8]*mat.mEntry[ 8] + mEntry[12]*mat.mEntry[12], mEntry[ 0]*mat.mEntry[ 1] + mEntry[ 4]*mat.mEntry[ 5] + mEntry[ 8]*mat.mEntry[ 9] + mEntry[12]*mat.mEntry[13], mEntry[ 0]*mat.mEntry[ 2] + mEntry[ 4]*mat.mEntry[ 6] + mEntry[ 8]*mat.mEntry[10] + mEntry[12]*mat.mEntry[14], mEntry[ 0]*mat.mEntry[ 3] + mEntry[ 4]*mat.mEntry[ 7] + mEntry[ 8]*mat.mEntry[11] + mEntry[12]*mat.mEntry[15], mEntry[ 1]*mat.mEntry[ 0] + mEntry[ 5]*mat.mEntry[ 4] + mEntry[ 9]*mat.mEntry[ 8] + mEntry[13]*mat.mEntry[12], mEntry[ 1]*mat.mEntry[ 1] + mEntry[ 5]*mat.mEntry[ 5] + mEntry[ 9]*mat.mEntry[ 9] + mEntry[13]*mat.mEntry[13], mEntry[ 1]*mat.mEntry[ 2] + mEntry[ 5]*mat.mEntry[ 6] + mEntry[ 9]*mat.mEntry[10] + mEntry[13]*mat.mEntry[14], mEntry[ 1]*mat.mEntry[ 3] + mEntry[ 5]*mat.mEntry[ 7] + mEntry[ 9]*mat.mEntry[11] + mEntry[13]*mat.mEntry[15], mEntry[ 2]*mat.mEntry[ 0] + mEntry[ 6]*mat.mEntry[ 4] + mEntry[10]*mat.mEntry[ 8] + mEntry[14]*mat.mEntry[12], mEntry[ 2]*mat.mEntry[ 1] + mEntry[ 6]*mat.mEntry[ 5] + mEntry[10]*mat.mEntry[ 9] + mEntry[14]*mat.mEntry[13], mEntry[ 2]*mat.mEntry[ 2] + mEntry[ 6]*mat.mEntry[ 6] + mEntry[10]*mat.mEntry[10] + mEntry[14]*mat.mEntry[14], mEntry[ 2]*mat.mEntry[ 3] + mEntry[ 6]*mat.mEntry[ 7] + mEntry[10]*mat.mEntry[11] + mEntry[14]*mat.mEntry[15], mEntry[ 3]*mat.mEntry[ 0] + mEntry[ 7]*mat.mEntry[ 4] + mEntry[11]*mat.mEntry[ 8] + mEntry[15]*mat.mEntry[12], mEntry[ 3]*mat.mEntry[ 1] + mEntry[ 7]*mat.mEntry[ 5] + mEntry[11]*mat.mEntry[ 9] + mEntry[15]*mat.mEntry[13], mEntry[ 3]*mat.mEntry[ 2] + mEntry[ 7]*mat.mEntry[ 6] + mEntry[11]*mat.mEntry[10] + mEntry[15]*mat.mEntry[14], mEntry[ 3]*mat.mEntry[ 3] + mEntry[ 7]*mat.mEntry[ 7] + mEntry[11]*mat.mEntry[11] + mEntry[15]*mat.mEntry[15] ); } //---------------------------------------------------------------------------- template Matrix4 Matrix4::TimesTranspose (const Matrix4& mat) const { // A*B^T return Matrix4 ( mEntry[ 0]*mat.mEntry[ 0] + mEntry[ 1]*mat.mEntry[ 1] + mEntry[ 2]*mat.mEntry[ 2] + mEntry[ 3]*mat.mEntry[ 3], mEntry[ 0]*mat.mEntry[ 4] + mEntry[ 1]*mat.mEntry[ 5] + mEntry[ 2]*mat.mEntry[ 6] + mEntry[ 3]*mat.mEntry[ 7], mEntry[ 0]*mat.mEntry[ 8] + mEntry[ 1]*mat.mEntry[ 9] + mEntry[ 2]*mat.mEntry[10] + mEntry[ 3]*mat.mEntry[11], mEntry[ 0]*mat.mEntry[12] + mEntry[ 1]*mat.mEntry[13] + mEntry[ 2]*mat.mEntry[14] + mEntry[ 3]*mat.mEntry[15], mEntry[ 4]*mat.mEntry[ 0] + mEntry[ 5]*mat.mEntry[ 1] + mEntry[ 6]*mat.mEntry[ 2] + mEntry[ 7]*mat.mEntry[ 3], mEntry[ 4]*mat.mEntry[ 4] + mEntry[ 5]*mat.mEntry[ 5] + mEntry[ 6]*mat.mEntry[ 6] + mEntry[ 7]*mat.mEntry[ 7], mEntry[ 4]*mat.mEntry[ 8] + mEntry[ 5]*mat.mEntry[ 9] + mEntry[ 6]*mat.mEntry[10] + mEntry[ 7]*mat.mEntry[11], mEntry[ 4]*mat.mEntry[12] + mEntry[ 5]*mat.mEntry[13] + mEntry[ 6]*mat.mEntry[14] + mEntry[ 7]*mat.mEntry[15], mEntry[ 8]*mat.mEntry[ 0] + mEntry[ 9]*mat.mEntry[ 1] + mEntry[10]*mat.mEntry[ 2] + mEntry[11]*mat.mEntry[ 3], mEntry[ 8]*mat.mEntry[ 4] + mEntry[ 9]*mat.mEntry[ 5] + mEntry[10]*mat.mEntry[ 6] + mEntry[11]*mat.mEntry[ 7], mEntry[ 8]*mat.mEntry[ 8] + mEntry[ 9]*mat.mEntry[ 9] + mEntry[10]*mat.mEntry[10] + mEntry[11]*mat.mEntry[11], mEntry[ 8]*mat.mEntry[12] + mEntry[ 9]*mat.mEntry[13] + mEntry[10]*mat.mEntry[14] + mEntry[11]*mat.mEntry[15], mEntry[12]*mat.mEntry[ 0] + mEntry[13]*mat.mEntry[ 1] + mEntry[14]*mat.mEntry[ 2] + mEntry[15]*mat.mEntry[ 3], mEntry[12]*mat.mEntry[ 4] + mEntry[13]*mat.mEntry[ 5] + mEntry[14]*mat.mEntry[ 6] + mEntry[15]*mat.mEntry[ 7], mEntry[12]*mat.mEntry[ 8] + mEntry[13]*mat.mEntry[ 9] + mEntry[14]*mat.mEntry[10] + mEntry[15]*mat.mEntry[11], mEntry[12]*mat.mEntry[12] + mEntry[13]*mat.mEntry[13] + mEntry[14]*mat.mEntry[14] + mEntry[15]*mat.mEntry[15] ); } //---------------------------------------------------------------------------- template Matrix4 Matrix4::TransposeTimesTranspose (const Matrix4& mat) const { // A^T*B^T return Matrix4 ( mEntry[ 0]*mat.mEntry[ 0] + mEntry[ 4]*mat.mEntry[ 1] + mEntry[ 8]*mat.mEntry[ 2] + mEntry[12]*mat.mEntry[ 3], mEntry[ 0]*mat.mEntry[ 4] + mEntry[ 4]*mat.mEntry[ 5] + mEntry[ 8]*mat.mEntry[ 6] + mEntry[12]*mat.mEntry[ 7], mEntry[ 0]*mat.mEntry[ 8] + mEntry[ 4]*mat.mEntry[ 9] + mEntry[ 8]*mat.mEntry[10] + mEntry[12]*mat.mEntry[11], mEntry[ 0]*mat.mEntry[12] + mEntry[ 4]*mat.mEntry[13] + mEntry[ 8]*mat.mEntry[14] + mEntry[12]*mat.mEntry[15], mEntry[ 1]*mat.mEntry[ 0] + mEntry[ 5]*mat.mEntry[ 1] + mEntry[ 9]*mat.mEntry[ 2] + mEntry[13]*mat.mEntry[ 3], mEntry[ 1]*mat.mEntry[ 4] + mEntry[ 5]*mat.mEntry[ 5] + mEntry[ 9]*mat.mEntry[ 6] + mEntry[13]*mat.mEntry[ 7], mEntry[ 1]*mat.mEntry[ 8] + mEntry[ 5]*mat.mEntry[ 9] + mEntry[ 9]*mat.mEntry[10] + mEntry[13]*mat.mEntry[11], mEntry[ 1]*mat.mEntry[12] + mEntry[ 5]*mat.mEntry[13] + mEntry[ 9]*mat.mEntry[14] + mEntry[13]*mat.mEntry[15], mEntry[ 2]*mat.mEntry[ 0] + mEntry[ 6]*mat.mEntry[ 1] + mEntry[10]*mat.mEntry[ 2] + mEntry[14]*mat.mEntry[ 3], mEntry[ 2]*mat.mEntry[ 4] + mEntry[ 6]*mat.mEntry[ 5] + mEntry[10]*mat.mEntry[ 6] + mEntry[14]*mat.mEntry[ 7], mEntry[ 2]*mat.mEntry[ 8] + mEntry[ 6]*mat.mEntry[ 9] + mEntry[10]*mat.mEntry[10] + mEntry[14]*mat.mEntry[11], mEntry[ 2]*mat.mEntry[12] + mEntry[ 6]*mat.mEntry[13] + mEntry[10]*mat.mEntry[14] + mEntry[14]*mat.mEntry[15], mEntry[ 3]*mat.mEntry[ 0] + mEntry[ 7]*mat.mEntry[ 1] + mEntry[11]*mat.mEntry[ 2] + mEntry[15]*mat.mEntry[ 3], mEntry[ 3]*mat.mEntry[ 4] + mEntry[ 7]*mat.mEntry[ 5] + mEntry[11]*mat.mEntry[ 6] + mEntry[15]*mat.mEntry[ 7], mEntry[ 3]*mat.mEntry[ 8] + mEntry[ 7]*mat.mEntry[ 9] + mEntry[11]*mat.mEntry[10] + mEntry[15]*mat.mEntry[11], mEntry[ 3]*mat.mEntry[12] + mEntry[ 7]*mat.mEntry[13] + mEntry[11]*mat.mEntry[14] + mEntry[15]*mat.mEntry[15] ); } //---------------------------------------------------------------------------- template Matrix4 Matrix4::Inverse (const Real epsilon) const { Real a0 = mEntry[ 0]*mEntry[ 5] - mEntry[ 1]*mEntry[ 4]; Real a1 = mEntry[ 0]*mEntry[ 6] - mEntry[ 2]*mEntry[ 4]; Real a2 = mEntry[ 0]*mEntry[ 7] - mEntry[ 3]*mEntry[ 4]; Real a3 = mEntry[ 1]*mEntry[ 6] - mEntry[ 2]*mEntry[ 5]; Real a4 = mEntry[ 1]*mEntry[ 7] - mEntry[ 3]*mEntry[ 5]; Real a5 = mEntry[ 2]*mEntry[ 7] - mEntry[ 3]*mEntry[ 6]; Real b0 = mEntry[ 8]*mEntry[13] - mEntry[ 9]*mEntry[12]; Real b1 = mEntry[ 8]*mEntry[14] - mEntry[10]*mEntry[12]; Real b2 = mEntry[ 8]*mEntry[15] - mEntry[11]*mEntry[12]; Real b3 = mEntry[ 9]*mEntry[14] - mEntry[10]*mEntry[13]; Real b4 = mEntry[ 9]*mEntry[15] - mEntry[11]*mEntry[13]; Real b5 = mEntry[10]*mEntry[15] - mEntry[11]*mEntry[14]; Real det = a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0; if (Math::FAbs(det) > epsilon) { Matrix4 inverse; inverse.mEntry[ 0] = + mEntry[ 5]*b5 - mEntry[ 6]*b4 + mEntry[ 7]*b3; inverse.mEntry[ 4] = - mEntry[ 4]*b5 + mEntry[ 6]*b2 - mEntry[ 7]*b1; inverse.mEntry[ 8] = + mEntry[ 4]*b4 - mEntry[ 5]*b2 + mEntry[ 7]*b0; inverse.mEntry[12] = - mEntry[ 4]*b3 + mEntry[ 5]*b1 - mEntry[ 6]*b0; inverse.mEntry[ 1] = - mEntry[ 1]*b5 + mEntry[ 2]*b4 - mEntry[ 3]*b3; inverse.mEntry[ 5] = + mEntry[ 0]*b5 - mEntry[ 2]*b2 + mEntry[ 3]*b1; inverse.mEntry[ 9] = - mEntry[ 0]*b4 + mEntry[ 1]*b2 - mEntry[ 3]*b0; inverse.mEntry[13] = + mEntry[ 0]*b3 - mEntry[ 1]*b1 + mEntry[ 2]*b0; inverse.mEntry[ 2] = + mEntry[13]*a5 - mEntry[14]*a4 + mEntry[15]*a3; inverse.mEntry[ 6] = - mEntry[12]*a5 + mEntry[14]*a2 - mEntry[15]*a1; inverse.mEntry[10] = + mEntry[12]*a4 - mEntry[13]*a2 + mEntry[15]*a0; inverse.mEntry[14] = - mEntry[12]*a3 + mEntry[13]*a1 - mEntry[14]*a0; inverse.mEntry[ 3] = - mEntry[ 9]*a5 + mEntry[10]*a4 - mEntry[11]*a3; inverse.mEntry[ 7] = + mEntry[ 8]*a5 - mEntry[10]*a2 + mEntry[11]*a1; inverse.mEntry[11] = - mEntry[ 8]*a4 + mEntry[ 9]*a2 - mEntry[11]*a0; inverse.mEntry[15] = + mEntry[ 8]*a3 - mEntry[ 9]*a1 + mEntry[10]*a0; Real invDet = ((Real)1)/det; inverse.mEntry[ 0] *= invDet; inverse.mEntry[ 1] *= invDet; inverse.mEntry[ 2] *= invDet; inverse.mEntry[ 3] *= invDet; inverse.mEntry[ 4] *= invDet; inverse.mEntry[ 5] *= invDet; inverse.mEntry[ 6] *= invDet; inverse.mEntry[ 7] *= invDet; inverse.mEntry[ 8] *= invDet; inverse.mEntry[ 9] *= invDet; inverse.mEntry[10] *= invDet; inverse.mEntry[11] *= invDet; inverse.mEntry[12] *= invDet; inverse.mEntry[13] *= invDet; inverse.mEntry[14] *= invDet; inverse.mEntry[15] *= invDet; return inverse; } return ZERO; } //---------------------------------------------------------------------------- template Matrix4 Matrix4::Adjoint () const { Real a0 = mEntry[ 0]*mEntry[ 5] - mEntry[ 1]*mEntry[ 4]; Real a1 = mEntry[ 0]*mEntry[ 6] - mEntry[ 2]*mEntry[ 4]; Real a2 = mEntry[ 0]*mEntry[ 7] - mEntry[ 3]*mEntry[ 4]; Real a3 = mEntry[ 1]*mEntry[ 6] - mEntry[ 2]*mEntry[ 5]; Real a4 = mEntry[ 1]*mEntry[ 7] - mEntry[ 3]*mEntry[ 5]; Real a5 = mEntry[ 2]*mEntry[ 7] - mEntry[ 3]*mEntry[ 6]; Real b0 = mEntry[ 8]*mEntry[13] - mEntry[ 9]*mEntry[12]; Real b1 = mEntry[ 8]*mEntry[14] - mEntry[10]*mEntry[12]; Real b2 = mEntry[ 8]*mEntry[15] - mEntry[11]*mEntry[12]; Real b3 = mEntry[ 9]*mEntry[14] - mEntry[10]*mEntry[13]; Real b4 = mEntry[ 9]*mEntry[15] - mEntry[11]*mEntry[13]; Real b5 = mEntry[10]*mEntry[15] - mEntry[11]*mEntry[14]; return Matrix4 ( + mEntry[ 5]*b5 - mEntry[ 6]*b4 + mEntry[ 7]*b3, - mEntry[ 1]*b5 + mEntry[ 2]*b4 - mEntry[ 3]*b3, + mEntry[13]*a5 - mEntry[14]*a4 + mEntry[15]*a3, - mEntry[ 9]*a5 + mEntry[10]*a4 - mEntry[11]*a3, - mEntry[ 4]*b5 + mEntry[ 6]*b2 - mEntry[ 7]*b1, + mEntry[ 0]*b5 - mEntry[ 2]*b2 + mEntry[ 3]*b1, - mEntry[12]*a5 + mEntry[14]*a2 - mEntry[15]*a1, + mEntry[ 8]*a5 - mEntry[10]*a2 + mEntry[11]*a1, + mEntry[ 4]*b4 - mEntry[ 5]*b2 + mEntry[ 7]*b0, - mEntry[ 0]*b4 + mEntry[ 1]*b2 - mEntry[ 3]*b0, + mEntry[12]*a4 - mEntry[13]*a2 + mEntry[15]*a0, - mEntry[ 8]*a4 + mEntry[ 9]*a2 - mEntry[11]*a0, - mEntry[ 4]*b3 + mEntry[ 5]*b1 - mEntry[ 6]*b0, + mEntry[ 0]*b3 - mEntry[ 1]*b1 + mEntry[ 2]*b0, - mEntry[12]*a3 + mEntry[13]*a1 - mEntry[14]*a0, + mEntry[ 8]*a3 - mEntry[ 9]*a1 + mEntry[10]*a0 ); } //---------------------------------------------------------------------------- template Real Matrix4::Determinant () const { Real a0 = mEntry[ 0]*mEntry[ 5] - mEntry[ 1]*mEntry[ 4]; Real a1 = mEntry[ 0]*mEntry[ 6] - mEntry[ 2]*mEntry[ 4]; Real a2 = mEntry[ 0]*mEntry[ 7] - mEntry[ 3]*mEntry[ 4]; Real a3 = mEntry[ 1]*mEntry[ 6] - mEntry[ 2]*mEntry[ 5]; Real a4 = mEntry[ 1]*mEntry[ 7] - mEntry[ 3]*mEntry[ 5]; Real a5 = mEntry[ 2]*mEntry[ 7] - mEntry[ 3]*mEntry[ 6]; Real b0 = mEntry[ 8]*mEntry[13] - mEntry[ 9]*mEntry[12]; Real b1 = mEntry[ 8]*mEntry[14] - mEntry[10]*mEntry[12]; Real b2 = mEntry[ 8]*mEntry[15] - mEntry[11]*mEntry[12]; Real b3 = mEntry[ 9]*mEntry[14] - mEntry[10]*mEntry[13]; Real b4 = mEntry[ 9]*mEntry[15] - mEntry[11]*mEntry[13]; Real b5 = mEntry[10]*mEntry[15] - mEntry[11]*mEntry[14]; Real det = a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0; return det; } //---------------------------------------------------------------------------- template void Matrix4::MakeObliqueProjection (const Vector3& normal, const Vector3& origin, const Vector3& direction) { // The projection plane is Dot(N,X-P) = 0 where N is a 3-by-1 unit-length // normal vector and P is a 3-by-1 point on the plane. The projection // is oblique to the plane, in the direction of the 3-by-1 vector D. // Necessarily Dot(N,D) is not zero for this projection to make sense. // Given a 3-by-1 point U, compute the intersection of the line U+t*D // with the plane to obtain t = -Dot(N,U-P)/Dot(N,D). Then // // projection(U) = P + [I - D*N^T/Dot(N,D)]*(U-P) // // A 4-by-4 homogeneous transformation representing the projection is // // +- -+ // M = | D*N^T - Dot(N,D)*I -Dot(N,P)D | // | 0^T -Dot(N,D) | // +- -+ // // where M applies to [U^T 1]^T by M*[U^T 1]^T. The matrix is chosen so // that M[3][3] > 0 whenever Dot(N,D) < 0 (projection is onto the // "positive side" of the plane). Real dotND = normal.Dot(direction); Real dotNO = normal.Dot(origin); mEntry[ 0] = direction[0]*normal[0] - dotND; mEntry[ 1] = direction[0]*normal[1]; mEntry[ 2] = direction[0]*normal[2]; mEntry[ 3] = -dotNO*direction[0]; mEntry[ 4] = direction[1]*normal[0]; mEntry[ 5] = direction[1]*normal[1] - dotND; mEntry[ 6] = direction[1]*normal[2]; mEntry[ 7] = -dotNO*direction[1]; mEntry[ 8] = direction[2]*normal[0]; mEntry[ 9] = direction[2]*normal[1]; mEntry[10] = direction[2]*normal[2] - dotND; mEntry[11] = -dotNO*direction[2]; mEntry[12] = 0.0f; mEntry[13] = 0.0f; mEntry[14] = 0.0f; mEntry[15] = -dotND; } //---------------------------------------------------------------------------- template void Matrix4::MakePerspectiveProjection ( const Vector3& normal, const Vector3& origin, const Vector3& eye) { // +- -+ // M = | Dot(N,E-P)*I - E*N^T -(Dot(N,E-P)*I - E*N^T)*E | // | -N^t Dot(N,E) | // +- -+ // // where E is the eye point, P is a point on the plane, and N is a // unit-length plane normal. Real dotND = normal.Dot(eye - origin); mEntry[ 0] = dotND - eye[0]*normal[0]; mEntry[ 1] = -eye[0]*normal[1]; mEntry[ 2] = -eye[0]*normal[2]; mEntry[ 3] = -(mEntry[0]*eye[0] + mEntry[1]*eye[1] + mEntry[2]*eye[2]); mEntry[ 4] = -eye[1]*normal[0]; mEntry[ 5] = dotND - eye[1]*normal[1]; mEntry[ 6] = -eye[1]*normal[2]; mEntry[ 7] = -(mEntry[4]*eye[0] + mEntry[5]*eye[1] + mEntry[6]*eye[2]); mEntry[ 8] = -eye[2]*normal[0]; mEntry[ 9] = -eye[2]*normal[1]; mEntry[10] = dotND- eye[2]*normal[2]; mEntry[11] = -(mEntry[8]*eye[0] + mEntry[9]*eye[1] + mEntry[10]*eye[2]); mEntry[12] = -normal[0]; mEntry[13] = -normal[1]; mEntry[14] = -normal[2]; mEntry[15] = normal.Dot(eye); } //---------------------------------------------------------------------------- template void Matrix4::MakeReflection (const Vector3& normal, const Vector3& origin) { // +- -+ // M = | I-2*N*N^T 2*Dot(N,P)*N | // | 0^T 1 | // +- -+ // // where P is a point on the plane and N is a unit-length plane normal. Real twoDotNO = ((Real)2)*(normal.Dot(origin)); mEntry[ 0] = (Real)1 - ((Real)2)*normal[0]*normal[0]; mEntry[ 1] = -((Real)2)*normal[0]*normal[1]; mEntry[ 2] = -((Real)2)*normal[0]*normal[2]; mEntry[ 3] = twoDotNO*normal[0]; mEntry[ 4] = -((Real)2)*normal[1]*normal[0]; mEntry[ 5] = (Real)1 - ((Real)2)*normal[1]*normal[1]; mEntry[ 6] = -((Real)2)*normal[1]*normal[2]; mEntry[ 7] = twoDotNO*normal[1]; mEntry[ 8] = -((Real)2)*normal[2]*normal[0]; mEntry[ 9] = -((Real)2)*normal[2]*normal[1]; mEntry[10] = (Real)1 - ((Real)2)*normal[2]*normal[2]; mEntry[11] = twoDotNO*normal[2]; mEntry[12] = (Real)0; mEntry[13] = (Real)0; mEntry[14] = (Real)0; mEntry[15] = (Real)1; } //---------------------------------------------------------------------------- template inline Matrix4 operator* (Real scalar, const Matrix4& mat) { return mat*scalar; } //---------------------------------------------------------------------------- template inline Vector4 operator* (const Vector4& vec, const Matrix4& mat) { return Vector4( vec[0]*mat[0][0]+vec[1]*mat[1][0]+vec[2]*mat[2][0]+vec[3]*mat[3][0], vec[0]*mat[0][1]+vec[1]*mat[1][1]+vec[2]*mat[2][1]+vec[3]*mat[3][1], vec[0]*mat[0][2]+vec[1]*mat[1][2]+vec[2]*mat[2][2]+vec[3]*mat[3][2], vec[0]*mat[0][3]+vec[1]*mat[1][3]+vec[2]*mat[2][3]+vec[3]*mat[3][3]); } //----------------------------------------------------------------------------