📄 wmlmatrix3.inl
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2004. All Rights Reserved
//
// The Wild Magic Library (WML) source code is supplied under the terms of
// the license agreement http://www.magic-software.com/License/WildMagic.pdf
// and may not be copied or disclosed except in accordance with the terms of
// that agreement.
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 ()
{
// the matrix is uninitialized
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Matrix3& rkM)
{
memcpy(m_afEntry,rkM.m_afEntry,9*sizeof(Real));
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Matrix<3,Real>& rkM)
{
memcpy(m_afEntry,(const Real*)rkM,9*sizeof(Real));
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>& Matrix3<Real>::operator= (const Matrix3& rkM)
{
memcpy(m_afEntry,rkM.m_afEntry,9*sizeof(Real));
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>& Matrix3<Real>::operator= (const Matrix<3,Real>& rkM)
{
memcpy(m_afEntry,(const Real*)rkM,9*sizeof(Real));
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (Real fM00, Real fM01, Real fM02, Real fM10,
Real fM11, Real fM12, Real fM20, Real fM21, Real fM22)
{
m_afEntry[0] = fM00;
m_afEntry[1] = fM01;
m_afEntry[2] = fM02;
m_afEntry[3] = fM10;
m_afEntry[4] = fM11;
m_afEntry[5] = fM12;
m_afEntry[6] = fM20;
m_afEntry[7] = fM21;
m_afEntry[8] = fM22;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Real afEntry[9], bool bRowMajor)
{
if ( bRowMajor )
{
memcpy(m_afEntry,afEntry,9*sizeof(Real));
}
else
{
m_afEntry[0] = afEntry[0];
m_afEntry[1] = afEntry[3];
m_afEntry[2] = afEntry[6];
m_afEntry[3] = afEntry[1];
m_afEntry[4] = afEntry[4];
m_afEntry[5] = afEntry[7];
m_afEntry[6] = afEntry[2];
m_afEntry[7] = afEntry[5];
m_afEntry[8] = afEntry[8];
}
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Vector3<Real>& rkU,
const Vector3<Real>& rkV, const Vector3<Real>& rkW, bool bColumns)
{
if ( bColumns )
{
m_afEntry[0] = rkU[0];
m_afEntry[1] = rkV[0];
m_afEntry[2] = rkW[0];
m_afEntry[3] = rkU[1];
m_afEntry[4] = rkV[1];
m_afEntry[5] = rkW[1];
m_afEntry[6] = rkU[2];
m_afEntry[7] = rkV[2];
m_afEntry[8] = rkW[2];
}
else
{
m_afEntry[0] = rkU[0];
m_afEntry[1] = rkU[1];
m_afEntry[2] = rkU[2];
m_afEntry[3] = rkV[0];
m_afEntry[4] = rkV[1];
m_afEntry[5] = rkV[2];
m_afEntry[6] = rkW[0];
m_afEntry[7] = rkW[1];
m_afEntry[8] = rkW[2];
}
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Vector3<Real>* akV, bool bColumns)
{
if ( bColumns )
{
m_afEntry[0] = akV[0][0];
m_afEntry[1] = akV[1][0];
m_afEntry[2] = akV[2][0];
m_afEntry[3] = akV[0][1];
m_afEntry[4] = akV[1][1];
m_afEntry[5] = akV[2][1];
m_afEntry[6] = akV[0][2];
m_afEntry[7] = akV[1][2];
m_afEntry[8] = akV[2][2];
}
else
{
m_afEntry[0] = akV[0][0];
m_afEntry[1] = akV[0][1];
m_afEntry[2] = akV[0][2];
m_afEntry[3] = akV[1][0];
m_afEntry[4] = akV[1][1];
m_afEntry[5] = akV[1][2];
m_afEntry[6] = akV[2][0];
m_afEntry[7] = akV[2][1];
m_afEntry[8] = akV[2][2];
}
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Vector3<Real>& rkU,
const Vector3<Real>& rkV)
{
MakeTensorProduct(rkU,rkV);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::MakeTensorProduct (const Vector3<Real>& rkU,
const Vector3<Real>& rkV)
{
m_afEntry[0] = rkU[0]*rkV[0];
m_afEntry[1] = rkU[0]*rkV[1];
m_afEntry[2] = rkU[0]*rkV[2];
m_afEntry[3] = rkU[1]*rkV[0];
m_afEntry[4] = rkU[1]*rkV[1];
m_afEntry[5] = rkU[1]*rkV[2];
m_afEntry[6] = rkU[2]*rkV[0];
m_afEntry[7] = rkU[2]*rkV[1];
m_afEntry[8] = rkU[2]*rkV[2];
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (Real fM00, Real fM11, Real fM22)
{
MakeDiagonal(fM00,fM11,fM22);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::MakeDiagonal (Real fM00, Real fM11, Real fM22)
{
m_afEntry[0] = fM00;
m_afEntry[1] = (Real)0.0;
m_afEntry[2] = (Real)0.0;
m_afEntry[3] = (Real)0.0;
m_afEntry[4] = fM11;
m_afEntry[5] = (Real)0.0;
m_afEntry[6] = (Real)0.0;
m_afEntry[7] = (Real)0.0;
m_afEntry[8] = fM22;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real>::Matrix3 (const Vector3<Real>& rkAxis, Real fAngle)
{
FromAxisAngle(rkAxis,fAngle);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::FromAxisAngle (const Vector3<Real>& rkAxis, Real fAngle)
{
Real fCos = Math<Real>::Cos(fAngle);
Real fSin = Math<Real>::Sin(fAngle);
Real fOneMinusCos = ((Real)1.0)-fCos;
Real fX2 = rkAxis[0]*rkAxis[0];
Real fY2 = rkAxis[1]*rkAxis[1];
Real fZ2 = rkAxis[2]*rkAxis[2];
Real fXYM = rkAxis[0]*rkAxis[1]*fOneMinusCos;
Real fXZM = rkAxis[0]*rkAxis[2]*fOneMinusCos;
Real fYZM = rkAxis[1]*rkAxis[2]*fOneMinusCos;
Real fXSin = rkAxis[0]*fSin;
Real fYSin = rkAxis[1]*fSin;
Real fZSin = rkAxis[2]*fSin;
m_afEntry[0] = fX2*fOneMinusCos+fCos;
m_afEntry[1] = fXYM-fZSin;
m_afEntry[2] = fXZM+fYSin;
m_afEntry[3] = fXYM+fZSin;
m_afEntry[4] = fY2*fOneMinusCos+fCos;
m_afEntry[5] = fYZM-fXSin;
m_afEntry[6] = fXZM-fYSin;
m_afEntry[7] = fYZM+fXSin;
m_afEntry[8] = fZ2*fOneMinusCos+fCos;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real> Matrix3<Real>::Inverse () const
{
// Invert a 3x3 using cofactors. This is faster than using a generic
// Gaussian elimination because of the loop overhead of such a method.
Matrix3<Real> kInverse;
kInverse[0][0] = m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
kInverse[0][1] = m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8];
kInverse[0][2] = m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4];
kInverse[1][0] = m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
kInverse[1][1] = m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6];
kInverse[1][2] = m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5];
kInverse[2][0] = m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
kInverse[2][1] = m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7];
kInverse[2][2] = m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3];
Real fDet = m_afEntry[0]*kInverse[0][0] + m_afEntry[1]*kInverse[1][0]+
m_afEntry[2]*kInverse[2][0];
if ( Math<Real>::FAbs(fDet) <= Math<Real>::EPSILON )
return Matrix3::ZERO;
kInverse /= fDet;
return kInverse;
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real> Matrix3<Real>::Adjoint () const
{
Matrix3<Real> kAdjoint;
kAdjoint[0][0] = m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
kAdjoint[0][1] = m_afEntry[2]*m_afEntry[7] - m_afEntry[1]*m_afEntry[8];
kAdjoint[0][2] = m_afEntry[1]*m_afEntry[5] - m_afEntry[2]*m_afEntry[4];
kAdjoint[1][0] = m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
kAdjoint[1][1] = m_afEntry[0]*m_afEntry[8] - m_afEntry[2]*m_afEntry[6];
kAdjoint[1][2] = m_afEntry[2]*m_afEntry[3] - m_afEntry[0]*m_afEntry[5];
kAdjoint[2][0] = m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
kAdjoint[2][1] = m_afEntry[1]*m_afEntry[6] - m_afEntry[0]*m_afEntry[7];
kAdjoint[2][2] = m_afEntry[0]*m_afEntry[4] - m_afEntry[1]*m_afEntry[3];
return kAdjoint;
}
//----------------------------------------------------------------------------
template <class Real>
Real Matrix3<Real>::Determinant () const
{
Real fCo00 = m_afEntry[4]*m_afEntry[8] - m_afEntry[5]*m_afEntry[7];
Real fCo10 = m_afEntry[5]*m_afEntry[6] - m_afEntry[3]*m_afEntry[8];
Real fCo20 = m_afEntry[3]*m_afEntry[7] - m_afEntry[4]*m_afEntry[6];
Real fDet = m_afEntry[0]*fCo00 + m_afEntry[1]*fCo10 + m_afEntry[2]*fCo20;
return fDet;
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::ToAxisAngle (Vector3<Real>& rkAxis, Real& rfAngle) const
{
// Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
// The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
// I is the identity and
//
// +- -+
// P = | 0 -z +y |
// | +z 0 -x |
// | -y +x 0 |
// +- -+
//
// If A > 0, R represents a counterclockwise rotation about the axis in
// the sense of looking from the tip of the axis vector towards the
// origin. Some algebra will show that
//
// cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P
//
// In the event that A = pi, R-R^t = 0 which prevents us from extracting
// the axis through P. Instead note that R = I+2*P^2 when A = pi, so
// P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and
// z^2-1. We can solve these for axis (x,y,z). Because the angle is pi,
// it does not matter which sign you choose on the square roots.
Real fTrace = m_afEntry[0] + m_afEntry[4] + m_afEntry[8];
Real fCos = ((Real)0.5)*(fTrace-((Real)1.0));
rfAngle = Math<Real>::ACos(fCos); // in [0,PI]
if ( rfAngle > (Real)0.0 )
{
if ( rfAngle < Math<Real>::PI )
{
rkAxis[0] = m_afEntry[7]-m_afEntry[5];
rkAxis[1] = m_afEntry[2]-m_afEntry[6];
rkAxis[2] = m_afEntry[3]-m_afEntry[1];
rkAxis.Normalize();
}
else
{
// angle is PI
Real fHalfInverse;
if ( m_afEntry[0] >= m_afEntry[4] )
{
// r00 >= r11
if ( m_afEntry[0] >= m_afEntry[8] )
{
// r00 is maximum diagonal term
rkAxis[0] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[0] -
m_afEntry[4] - m_afEntry[8] + (Real)1.0);
fHalfInverse = ((Real)0.5)/rkAxis[0];
rkAxis[1] = fHalfInverse*m_afEntry[1];
rkAxis[2] = fHalfInverse*m_afEntry[2];
}
else
{
// r22 is maximum diagonal term
rkAxis[2] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[8] -
m_afEntry[0] - m_afEntry[4] + (Real)1.0);
fHalfInverse = ((Real)0.5)/rkAxis[2];
rkAxis[0] = fHalfInverse*m_afEntry[2];
rkAxis[1] = fHalfInverse*m_afEntry[5];
}
}
else
{
// r11 > r00
if ( m_afEntry[4] >= m_afEntry[8] )
{
// r11 is maximum diagonal term
rkAxis[1] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[4] -
m_afEntry[0] - m_afEntry[8] + (Real)1.0);
fHalfInverse = ((Real)0.5)/rkAxis[1];
rkAxis[0] = fHalfInverse*m_afEntry[1];
rkAxis[2] = fHalfInverse*m_afEntry[5];
}
else
{
// r22 is maximum diagonal term
rkAxis[2] = ((Real)0.5)*Math<Real>::Sqrt(m_afEntry[8] -
m_afEntry[0] - m_afEntry[4] + (Real)1.0);
fHalfInverse = ((Real)0.5)/rkAxis[2];
rkAxis[0] = fHalfInverse*m_afEntry[2];
rkAxis[1] = fHalfInverse*m_afEntry[5];
}
}
}
}
else
{
// The angle is 0 and the matrix is the identity. Any axis will
// work, so just use the x-axis.
rkAxis[0] = (Real)1.0;
rkAxis[1] = (Real)0.0;
rkAxis[2] = (Real)0.0;
}
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::Orthonormalize ()
{
// Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is
// M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
//
// q0 = m0/|m0|
// q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
// q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
//
// where |V| indicates length of vector V and A*B indicates dot
// product of vectors A and B.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -