//===========================================================================// // File: matrix.cc // // Project: MUNGA Brick: Math Library // // Contents: Implementation details for the matrix class // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 11/21/94 JMA Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include #pragma hdrstop #if !defined(MATRIX_HPP) # include #endif #if !defined(AFFNMTRX_HPP) # include #endif #if !defined(ORIGIN_HPP) # include #endif #if defined(USE_SIGNATURE) int Is_Signature_Bad(const volatile AbstractMatrix4x4 *) { return False; } #endif // //########################################################################### //########################################################################### // AbstractMatrix4x4& AbstractMatrix4x4::operator=(const AbstractMatrix4x4 &m) { #if sizeof(entries) > sizeof(m.entries) # error memcpy size mismatch! #endif memcpy(entries, m.entries, sizeof(m.entries)); return *this; } // //########################################################################### //########################################################################### // AbstractMatrix4x4& AbstractMatrix4x4::Transpose(const AbstractMatrix4x4 &m) { entries[0] = m.entries[0]; entries[1] = m.entries[4]; entries[2] = m.entries[8]; entries[3] = m.entries[12]; entries[4] = m.entries[1]; entries[5] = m.entries[5]; entries[6] = m.entries[9]; entries[7] = m.entries[13]; entries[8] = m.entries[2]; entries[9] = m.entries[6]; entries[10] = m.entries[10]; entries[11] = m.entries[14]; entries[12] = m.entries[3]; entries[13] = m.entries[7]; entries[14] = m.entries[11]; entries[15] = m.entries[15]; return *this; } // //########################################################################### //########################################################################### // Logical AbstractMatrix4x4::TestInstance() const { return True; } const Matrix4x4 Matrix4x4::Identity(True); // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::BuildIdentity() { (*this)(0,0) = 1.0f; (*this)(1,0) = 0.0f; (*this)(2,0) = 0.0f; (*this)(3,0) = 0.0f; (*this)(0,1) = 0.0f; (*this)(1,1) = 1.0f; (*this)(2,1) = 0.0f; (*this)(3,1) = 0.0f; (*this)(0,2) = 0.0f; (*this)(1,2) = 0.0f; (*this)(2,2) = 1.0f; (*this)(3,2) = 0.0f; (*this)(0,3) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,3) = 0.0f; (*this)(3,3) = 1.0f; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::operator=(const AffineMatrix &m) { (*this)(0,0) = m(0,0); (*this)(0,1) = m(0,1); (*this)(0,2) = m(0,2); (*this)(0,3) = 0.0f; (*this)(1,0) = m(1,0); (*this)(1,1) = m(1,1); (*this)(1,2) = m(1,2); (*this)(1,3) = 0.0f; (*this)(2,0) = m(2,0); (*this)(2,1) = m(2,1); (*this)(2,2) = m(2,2); (*this)(2,3) = 0.0f; (*this)(3,0) = m(3,0); (*this)(3,1) = m(3,1); (*this)(3,2) = m(3,2); (*this)(3,3) = 1.0f; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::operator=(const Origin& p) { Check_Pointer(this); Check(&p); BuildRotation(p.angularPosition); BuildTranslation(p.linearPosition); (*this)(0,3) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,3) = 0.0f; (*this)(3,3) = 1.0f; return *this; } // //############################################################################# //############################################################################# // Matrix4x4& Matrix4x4::operator=(const EulerAngles &angles) { Check_Pointer(this); Check(&angles); SinCosPair x, y, z; x = angles.pitch; y = angles.yaw; z = angles.roll; (*this)(0,0) = y.cosine*z.cosine; (*this)(0,1) = y.cosine*z.sine; (*this)(0,2) = -y.sine; (*this)(0,3) = 0.0f; (*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine; (*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine; (*this)(1,2) = x.sine*y.cosine; (*this)(1,3) = 0.0f; (*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine; (*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine; (*this)(2,2) = x.cosine*y.cosine; (*this)(2,3) = 0.0f; (*this)(3,0) = 0.0f; (*this)(3,1) = 0.0f; (*this)(3,2) = 0.0f; (*this)(3,3) = 1.0f; Check(this); return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::BuildRotation(const Quaternion &q) { Check_Pointer(this); Check(&q); Scalar a = q.x*q.y, b = q.y*q.z, c = q.z*q.x, d = q.w*q.x, e = q.w*q.y, f = q.w*q.z, g = q.w*q.w, h = q.x*q.x, i = q.y*q.y, j = q.z*q.z; (*this)(0,0) = g + h - i - j; (*this)(1,0) = 2.0f*(a - f); (*this)(2,0) = 2.0f*(c + e); (*this)(0,1) = 2.0f*(f + a); (*this)(1,1) = g - h + i - j; (*this)(2,1) = 2.0f*(b - d); (*this)(0,2) = 2.0f*(c - e); (*this)(1,2) = 2.0f*(b + d); (*this)(2,2) = g - h - i + j; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::operator=(const Quaternion &q) { Check_Pointer(this); Check(&q); BuildRotation(q); (*this)(0,3) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,3) = 0.0f; (*this)(3,0) = 0.0f; (*this)(3,1) = 0.0f; (*this)(3,2) = 0.0f; (*this)(3,3) = 1.0f; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::BuildTranslation(const Point3D& p) { Check_Pointer(this); Check(&p); (*this)(3,0) = p.x; (*this)(3,1) = p.y; (*this)(3,2) = p.z; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::operator=(const Point3D& p) { Check_Pointer(this); Check(&p); BuildTranslation(p); (*this)(0,0) = 1.0f; (*this)(0,1) = 0.0f; (*this)(0,2) = 0.0f; (*this)(0,3) = 0.0f; (*this)(1,0) = 0.0f; (*this)(1,1) = 1.0f; (*this)(1,2) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,0) = 0.0f; (*this)(2,1) = 0.0f; (*this)(2,2) = 1.0f; (*this)(2,3) = 0.0f; (*this)(3,3) = 1.0f; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::Multiply( const Matrix4x4 &Source1, const Matrix4x4 &Source2 ) { (*this)(0,0) = Source1(0,0)*Source2(0,0) + Source1(0,1)*Source2(1,0) + Source1(0,2)*Source2(2,0) + Source1(0,3)*Source2(3,0); (*this)(1,0) = Source1(1,0)*Source2(0,0) + Source1(1,1)*Source2(1,0) + Source1(1,2)*Source2(2,0) + Source1(1,3)*Source2(3,0); (*this)(2,0) = Source1(2,0)*Source2(0,0) + Source1(2,1)*Source2(1,0) + Source1(2,2)*Source2(2,0) + Source1(2,3)*Source2(3,0); (*this)(3,0) = Source1(3,0)*Source2(0,0) + Source1(3,1)*Source2(1,0) + Source1(3,2)*Source2(2,0) + Source1(3,3)*Source2(3,0); (*this)(0,1) = Source1(0,0)*Source2(0,1) + Source1(0,1)*Source2(1,1) + Source1(0,2)*Source2(2,1) + Source1(0,3)*Source2(3,1); (*this)(1,1) = Source1(1,0)*Source2(0,1) + Source1(1,1)*Source2(1,1) + Source1(1,2)*Source2(2,1) + Source1(1,3)*Source2(3,1); (*this)(2,1) = Source1(2,0)*Source2(0,1) + Source1(2,1)*Source2(1,1) + Source1(2,2)*Source2(2,1) + Source1(2,3)*Source2(3,1); (*this)(3,1) = Source1(3,0)*Source2(0,1) + Source1(3,1)*Source2(1,1) + Source1(3,2)*Source2(2,1) + Source1(3,3)*Source2(3,1); (*this)(0,2) = Source1(0,0)*Source2(0,2) + Source1(0,1)*Source2(1,2) + Source1(0,2)*Source2(2,2) + Source1(0,3)*Source2(3,2); (*this)(1,2) = Source1(1,0)*Source2(0,2) + Source1(1,1)*Source2(1,2) + Source1(1,2)*Source2(2,2) + Source1(1,3)*Source2(3,2); (*this)(2,2) = Source1(2,0)*Source2(0,2) + Source1(2,1)*Source2(1,2) + Source1(2,2)*Source2(2,2) + Source1(2,3)*Source2(3,2); (*this)(3,2) = Source1(3,0)*Source2(0,2) + Source1(3,1)*Source2(1,2) + Source1(3,2)*Source2(2,2) + Source1(3,3)*Source2(3,2); (*this)(0,3) = Source1(0,0)*Source2(0,3) + Source1(0,1)*Source2(1,3) + Source1(0,2)*Source2(2,3) + Source1(0,3)*Source2(3,3); (*this)(1,3) = Source1(1,0)*Source2(0,3) + Source1(1,1)*Source2(1,3) + Source1(1,2)*Source2(2,3) + Source1(1,3)*Source2(3,3); (*this)(2,3) = Source1(2,0)*Source2(0,3) + Source1(2,1)*Source2(1,3) + Source1(2,2)*Source2(2,3) + Source1(2,3)*Source2(3,3); (*this)(3,3) = Source1(3,0)*Source2(0,3) + Source1(3,1)*Source2(1,3) + Source1(3,2)*Source2(2,3) + Source1(3,3)*Source2(3,3); return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::Multiply( const Matrix4x4 &Source1, const AffineMatrix &Source2 ) { (*this)(0,0) = Source1(0,0)*Source2(0,0) + Source1(0,1)*Source2(1,0) + Source1(0,2)*Source2(2,0) + Source1(0,3)*Source2(3,0); (*this)(1,0) = Source1(1,0)*Source2(0,0) + Source1(1,1)*Source2(1,0) + Source1(1,2)*Source2(2,0) + Source1(1,3)*Source2(3,0); (*this)(2,0) = Source1(2,0)*Source2(0,0) + Source1(2,1)*Source2(1,0) + Source1(2,2)*Source2(2,0) + Source1(2,3)*Source2(3,0); (*this)(3,0) = Source1(3,0)*Source2(0,0) + Source1(3,1)*Source2(1,0) + Source1(3,2)*Source2(2,0) + Source1(3,3)*Source2(3,0); (*this)(0,1) = Source1(0,0)*Source2(0,1) + Source1(0,1)*Source2(1,1) + Source1(0,2)*Source2(2,1) + Source1(0,3)*Source2(3,1); (*this)(1,1) = Source1(1,0)*Source2(0,1) + Source1(1,1)*Source2(1,1) + Source1(1,2)*Source2(2,1) + Source1(1,3)*Source2(3,1); (*this)(2,1) = Source1(2,0)*Source2(0,1) + Source1(2,1)*Source2(1,1) + Source1(2,2)*Source2(2,1) + Source1(2,3)*Source2(3,1); (*this)(3,1) = Source1(3,0)*Source2(0,1) + Source1(3,1)*Source2(1,1) + Source1(3,2)*Source2(2,1) + Source1(3,3)*Source2(3,1); (*this)(0,2) = Source1(0,0)*Source2(0,2) + Source1(0,1)*Source2(1,2) + Source1(0,2)*Source2(2,2) + Source1(0,3)*Source2(3,2); (*this)(1,2) = Source1(1,0)*Source2(0,2) + Source1(1,1)*Source2(1,2) + Source1(1,2)*Source2(2,2) + Source1(1,3)*Source2(3,2); (*this)(2,2) = Source1(2,0)*Source2(0,2) + Source1(2,1)*Source2(1,2) + Source1(2,2)*Source2(2,2) + Source1(2,3)*Source2(3,2); (*this)(3,2) = Source1(3,0)*Source2(0,2) + Source1(3,1)*Source2(1,2) + Source1(3,2)*Source2(2,2) + Source1(3,3)*Source2(3,2); (*this)(0,3) = Source1(0,3); (*this)(1,3) = Source1(1,3); (*this)(2,3) = Source1(2,3); (*this)(3,3) = Source1(3,3); return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::Multiply( const AffineMatrix &Source1, const Matrix4x4 &Source2 ) { (*this)(0,0) = Source1(0,0)*Source2(0,0) + Source1(0,1)*Source2(1,0) + Source1(0,2)*Source2(2,0); (*this)(1,0) = Source1(1,0)*Source2(0,0) + Source1(1,1)*Source2(1,0) + Source1(1,2)*Source2(2,0); (*this)(2,0) = Source1(2,0)*Source2(0,0) + Source1(2,1)*Source2(1,0) + Source1(2,2)*Source2(2,0); (*this)(3,0) = Source1(3,0)*Source2(0,0) + Source1(3,1)*Source2(1,0) + Source1(3,2)*Source2(2,0) + Source2(3,0); (*this)(0,1) = Source1(0,0)*Source2(0,1) + Source1(0,1)*Source2(1,1) + Source1(0,2)*Source2(2,1); (*this)(1,1) = Source1(1,0)*Source2(0,1) + Source1(1,1)*Source2(1,1) + Source1(1,2)*Source2(2,1); (*this)(2,1) = Source1(2,0)*Source2(0,1) + Source1(2,1)*Source2(1,1) + Source1(2,2)*Source2(2,1); (*this)(3,1) = Source1(3,0)*Source2(0,1) + Source1(3,1)*Source2(1,1) + Source1(3,2)*Source2(2,1) + Source2(3,1); (*this)(0,2) = Source1(0,0)*Source2(0,2) + Source1(0,1)*Source2(1,2) + Source1(0,2)*Source2(2,2); (*this)(1,2) = Source1(1,0)*Source2(0,2) + Source1(1,1)*Source2(1,2) + Source1(1,2)*Source2(2,2); (*this)(2,2) = Source1(2,0)*Source2(0,2) + Source1(2,1)*Source2(1,2) + Source1(2,2)*Source2(2,2); (*this)(3,2) = Source1(3,0)*Source2(0,2) + Source1(3,1)*Source2(1,2) + Source1(3,2)*Source2(2,2) + Source2(3,2); (*this)(0,3) = Source1(0,0)*Source2(0,3) + Source1(0,1)*Source2(1,3) + Source1(0,2)*Source2(2,3); (*this)(1,3) = Source1(1,0)*Source2(0,3) + Source1(1,1)*Source2(1,3) + Source1(1,2)*Source2(2,3); (*this)(2,3) = Source1(2,0)*Source2(0,3) + Source1(2,1)*Source2(1,3) + Source1(2,2)*Source2(2,3); (*this)(3,3) = Source1(3,0)*Source2(0,3) + Source1(3,1)*Source2(1,3) + Source1(3,2)*Source2(2,3) + Source2(3,3); return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::Multiply( const AffineMatrix &m1, const AffineMatrix &m2 ) { Cast_Object(AffineMatrix*,this)->Multiply(m1,m2); (*this)(0,3) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,3) = 0.0f; (*this)(3,3) = 1.0f; return *this; } // //########################################################################### //########################################################################### // Matrix4x4& Matrix4x4::SetToProjection( Scalar Z_Plane, Scalar Inv_Q, Scalar Dx, Scalar Dy, Scalar Inv_Dz ) { Scalar temp; // // This may need to be transposed!!!! // (*this)(0,0) = 1.0; (*this)(0,1) = 0.0; (*this)(0,2) = 0.0; (*this)(0,3) = 0.0; (*this)(1,0) = 0.0; (*this)(1,1) = 1.0; (*this)(1,2) = 0.0; (*this)(1,3) = 0.0; temp = Dx * Inv_Dz; (*this)(3,0) = temp * Z_Plane; (*this)(2,0) = -temp; temp = Dy * Inv_Dz; (*this)(3,1) = temp * Z_Plane; (*this)(2,1) = -temp; Inv_Dz *= -Inv_Q; (*this)(2,2) = Z_Plane * Inv_Dz; (*this)(2,3) = Z_Plane * (1.0 - (*this)(2,2)); (*this)(3,2) = Inv_Dz; (*this)(3,3) = 1.0 - (*this)(2,2); return *this; } // //########################################################################### //########################################################################### // ostream& operator <<(ostream& Stream, const Matrix4x4 &A_Matrix) { Stream << setprecision(4); Stream << "\n\t| " << setw(9) << A_Matrix(0,0) << ", " << setw(9); Stream << A_Matrix(0,1) << ", " << setw(9) << A_Matrix(0,2) << ", "; Stream << setw(9) << A_Matrix(0,3) << " |\n\t| " << setw(9); Stream << A_Matrix(1,0) << ", " << setw(9) << A_Matrix(1,1) << ", "; Stream << setw(9) << A_Matrix(1,2) << ", " << setw(9) << A_Matrix(1,3); Stream << " |\n\t| " << setw(9) << A_Matrix(2,0) << ", " << setw(9); Stream << A_Matrix(2,1) << ", " << setw(9) << A_Matrix(2,2) << ", "; Stream << setw(9) << A_Matrix(2,3) << " |\n\t| " << setw(9); Stream << A_Matrix(3,0) << ", " << setw(9) << A_Matrix(3,1) << ", "; Stream << setw(9) << A_Matrix(3,2) << ", " << setw(9) << A_Matrix(3,3); return Stream << " |"; } // //########################################################################### //########################################################################### // TransposedMatrix& TransposedMatrix::operator=(const AffineMatrix &m) { #if sizeof(m.entries) > sizeof(entries) # error memcpy size mismatch! #endif memcpy(entries, m.entries, sizeof(m.entries)); (*this)(0,3) = 0.0f; (*this)(1,3) = 0.0f; (*this)(2,3) = 0.0f; (*this)(3,3) = 1.0f; return *this; } #if defined(TEST_CLASS) # include "matrix.tcp" #endif