📄 wmlquaternion.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>
Quaternion<Real>::Quaternion ()
{
// the object is uninitialized
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::Quaternion (Real fW, Real fX, Real fY, Real fZ)
{
m_afTuple[0] = fW;
m_afTuple[1] = fX;
m_afTuple[2] = fY;
m_afTuple[3] = fZ;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::Quaternion (const Quaternion& rkQ)
{
memcpy(m_afTuple,rkQ.m_afTuple,4*sizeof(Real));
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::Quaternion (const Matrix3<Real>& rkRot)
{
FromRotationMatrix(rkRot);
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::Quaternion (const Vector3<Real>& rkAxis, Real fAngle)
{
FromAxisAngle(rkAxis,fAngle);
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::Quaternion (const Vector3<Real> akRotColumn[3])
{
FromRotationMatrix(akRotColumn);
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::operator const Real* () const
{
return m_afTuple;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>::operator Real* ()
{
return m_afTuple;
}
//----------------------------------------------------------------------------
template <class Real>
Real Quaternion<Real>::operator[] (int i) const
{
assert( 0 <= i && i < 4 );
return m_afTuple[i];
}
//----------------------------------------------------------------------------
template <class Real>
Real& Quaternion<Real>::operator[] (int i)
{
assert( 0 <= i && i < 4 );
return m_afTuple[i];
}
//----------------------------------------------------------------------------
template <class Real>
Real Quaternion<Real>::W () const
{
return m_afTuple[0];
}
//----------------------------------------------------------------------------
template <class Real>
Real& Quaternion<Real>::W ()
{
return m_afTuple[0];
}
//----------------------------------------------------------------------------
template <class Real>
Real Quaternion<Real>::X () const
{
return m_afTuple[1];
}
//----------------------------------------------------------------------------
template <class Real>
Real& Quaternion<Real>::X ()
{
return m_afTuple[1];
}
//----------------------------------------------------------------------------
template <class Real>
Real Quaternion<Real>::Y () const
{
return m_afTuple[2];
}
//----------------------------------------------------------------------------
template <class Real>
Real& Quaternion<Real>::Y ()
{
return m_afTuple[2];
}
//----------------------------------------------------------------------------
template <class Real>
Real Quaternion<Real>::Z () const
{
return m_afTuple[3];
}
//----------------------------------------------------------------------------
template <class Real>
Real& Quaternion<Real>::Z ()
{
return m_afTuple[3];
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>& Quaternion<Real>::operator= (const Quaternion& rkQ)
{
memcpy(m_afTuple,rkQ.m_afTuple,4*sizeof(Real));
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator== (const Quaternion& rkQ) const
{
for (int i = 0; i < 4; i++)
{
if ( m_afTuple[i] != rkQ.m_afTuple[i] )
return false;
}
return true;
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator!= (const Quaternion& rkQ) const
{
return !operator==(rkQ);
}
//----------------------------------------------------------------------------
template <class Real>
int Quaternion<Real>::CompareArrays (const Quaternion& rkQ) const
{
return memcmp(m_afTuple,rkQ.m_afTuple,4*sizeof(Real));
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator< (const Quaternion& rkQ) const
{
return CompareArrays(rkQ) < 0;
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator<= (const Quaternion& rkQ) const
{
return CompareArrays(rkQ) <= 0;
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator> (const Quaternion& rkQ) const
{
return CompareArrays(rkQ) > 0;
}
//----------------------------------------------------------------------------
template <class Real>
bool Quaternion<Real>::operator>= (const Quaternion& rkQ) const
{
return CompareArrays(rkQ) >= 0;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator+ (const Quaternion& rkQ) const
{
Quaternion<Real> kSum;
for (int i = 0; i < 4; i++)
kSum.m_afTuple[i] = m_afTuple[i] + rkQ.m_afTuple[i];
return kSum;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator- (const Quaternion& rkQ) const
{
Quaternion<Real> kDiff;
for (int i = 0; i < 4; i++)
kDiff.m_afTuple[i] = m_afTuple[i] - rkQ.m_afTuple[i];
return kDiff;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator* (const Quaternion& rkQ) const
{
// NOTE: Multiplication is not generally commutative, so in most
// cases p*q != q*p.
Quaternion kProd;
kProd.m_afTuple[0] =
m_afTuple[0]*rkQ.m_afTuple[0] -
m_afTuple[1]*rkQ.m_afTuple[1] -
m_afTuple[2]*rkQ.m_afTuple[2] -
m_afTuple[3]*rkQ.m_afTuple[3];
kProd.m_afTuple[1] =
m_afTuple[0]*rkQ.m_afTuple[1] +
m_afTuple[1]*rkQ.m_afTuple[0] +
m_afTuple[2]*rkQ.m_afTuple[3] -
m_afTuple[3]*rkQ.m_afTuple[2];
kProd.m_afTuple[2] =
m_afTuple[0]*rkQ.m_afTuple[2] +
m_afTuple[2]*rkQ.m_afTuple[0] +
m_afTuple[3]*rkQ.m_afTuple[1] -
m_afTuple[1]*rkQ.m_afTuple[3];
kProd.m_afTuple[3] =
m_afTuple[0]*rkQ.m_afTuple[3] +
m_afTuple[3]*rkQ.m_afTuple[0] +
m_afTuple[1]*rkQ.m_afTuple[2] -
m_afTuple[2]*rkQ.m_afTuple[1];
return kProd;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator* (Real fScalar) const
{
Quaternion<Real> kProd;
for (int i = 0; i < 4; i++)
kProd.m_afTuple[i] = fScalar*m_afTuple[i];
return kProd;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator/ (Real fScalar) const
{
Quaternion<Real> kQuot;
int i;
if ( fScalar != (Real)0.0 )
{
Real fInvScalar = ((Real)1.0)/fScalar;
for (i = 0; i < 4; i++)
kQuot.m_afTuple[i] = fInvScalar*m_afTuple[i];
}
else
{
for (i = 0; i < 4; i++)
kQuot.m_afTuple[i] = Math<Real>::MAX_REAL;
}
return kQuot;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> Quaternion<Real>::operator- () const
{
Quaternion<Real> kNeg;
for (int i = 0; i < 4; i++)
kNeg.m_afTuple[i] = -m_afTuple[i];
return kNeg;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real> operator* (Real fScalar, const Quaternion<Real>& rkQ)
{
Quaternion<Real> kProd;
for (int i = 0; i < 4; i++)
kProd[i] = fScalar*rkQ[i];
return kProd;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>& Quaternion<Real>::operator+= (const Quaternion& rkQ)
{
for (int i = 0; i < 4; i++)
m_afTuple[i] += rkQ.m_afTuple[i];
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>& Quaternion<Real>::operator-= (const Quaternion& rkQ)
{
for (int i = 0; i < 4; i++)
m_afTuple[i] -= rkQ.m_afTuple[i];
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>& Quaternion<Real>::operator*= (Real fScalar)
{
for (int i = 0; i < 4; i++)
m_afTuple[i] *= fScalar;
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
Quaternion<Real>& Quaternion<Real>::operator/= (Real fScalar)
{
int i;
if ( fScalar != (Real)0.0 )
{
Real fInvScalar = ((Real)1.0)/fScalar;
for (i = 0; i < 4; i++)
m_afTuple[i] *= fInvScalar;
}
else
{
for (i = 0; i < 4; i++)
m_afTuple[i] = Math<Real>::MAX_REAL;
}
return *this;
}
//----------------------------------------------------------------------------
template <class Real>
void Quaternion<Real>::FromRotationMatrix (const Matrix3<Real>& rkRot)
{
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
// article "Quaternion Calculus and Fast Animation".
Real fTrace = rkRot(0,0) + rkRot(1,1) + rkRot(2,2);
Real fRoot;
if ( fTrace > (Real)0.0 )
{
// |w| > 1/2, may as well choose w > 1/2
fRoot = Math<Real>::Sqrt(fTrace + (Real)1.0); // 2w
m_afTuple[0] = ((Real)0.5)*fRoot;
fRoot = ((Real)0.5)/fRoot; // 1/(4w)
m_afTuple[1] = (rkRot(2,1)-rkRot(1,2))*fRoot;
m_afTuple[2] = (rkRot(0,2)-rkRot(2,0))*fRoot;
m_afTuple[3] = (rkRot(1,0)-rkRot(0,1))*fRoot;
}
else
{
// |w| <= 1/2
int i = 0;
if ( rkRot(1,1) > rkRot(0,0) )
i = 1;
if ( rkRot(2,2) > rkRot(i,i) )
i = 2;
int j = ms_iNext[i];
int k = ms_iNext[j];
fRoot = Math<Real>::Sqrt(rkRot(i,i)-rkRot(j,j)-rkRot(k,k)+(Real)1.0);
Real* apfQuat[3] = { &m_afTuple[1], &m_afTuple[2], &m_afTuple[3] };
*apfQuat[i] = ((Real)0.5)*fRoot;
fRoot = ((Real)0.5)/fRoot;
m_afTuple[0] = (rkRot(k,j)-rkRot(j,k))*fRoot;
*apfQuat[j] = (rkRot(j,i)+rkRot(i,j))*fRoot;
*apfQuat[k] = (rkRot(k,i)+rkRot(i,k))*fRoot;
}
}
//----------------------------------------------------------------------------
template <class Real>
void Quaternion<Real>::ToRotationMatrix (Matrix3<Real>& rkRot) const
{
Real fTx = ((Real)2.0)*m_afTuple[1];
Real fTy = ((Real)2.0)*m_afTuple[2];
Real fTz = ((Real)2.0)*m_afTuple[3];
Real fTwx = fTx*m_afTuple[0];
Real fTwy = fTy*m_afTuple[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -