reflex2q3/ReflexToQ3/ckmath/ckmath_quaternion.cpp

236 lines
6.9 KiB
C++
Raw Normal View History

2015-02-02 08:11:03 +05:30
//
// Author: Michael Cameron
// Email: chronokun@hotmail.com
//
// Local Includes
#include "ckmath_quaternion.h"
#include "ckmath_scalar.h"
#include "ckmath_vector.h"
//
// Quaternion
//
const TVector4d& IdentityQuaternion(TVector4d& _rResult)
{
_rResult.m_dW = 1.0;
_rResult.m_dX = 0.0;
_rResult.m_dY = 0.0;
_rResult.m_dZ = 0.0;
return(_rResult);
}
const TVector4f& IdentityQuaternion(TVector4f& _rResult)
{
_rResult.m_fW = 1.0f;
_rResult.m_fX = 0.0f;
_rResult.m_fY = 0.0f;
_rResult.m_fZ = 0.0f;
return(_rResult);
}
const TVector4d& ConjugateQuaternion(TVector4d& _rResult, const TVector4d& _krQuaternion)
{
_rResult.m_dW = _krQuaternion.m_dW;
_rResult.m_dX = -_krQuaternion.m_dX;
_rResult.m_dY = -_krQuaternion.m_dY;
_rResult.m_dZ = -_krQuaternion.m_dZ;
return(_rResult);
}
const TVector4f& ConjugateQuaternion(TVector4f& _rResult, const TVector4f& _krQuaternion)
{
_rResult.m_fW = _krQuaternion.m_fW;
_rResult.m_fX = -_krQuaternion.m_fX;
_rResult.m_fY = -_krQuaternion.m_fY;
_rResult.m_fZ = -_krQuaternion.m_fZ;
return(_rResult);
}
const TVector4d& InverseQuaternion(TVector4d& _rResult, const TVector4d& _krQuaternion)
{
_rResult = ScalarMultiply(_rResult,
ConjugateQuaternion(TVector4d(), _krQuaternion),
(1.0 / Square(QuaternionMagnitude(_krQuaternion))));
return(_rResult);
}
const TVector4f& InverseQuaternion(TVector4f& _rResult, const TVector4f& _krQuaternion)
{
_rResult = ScalarMultiply(_rResult,
ConjugateQuaternion(TVector4f(), _krQuaternion),
(1.0f / Square(QuaternionMagnitude(_krQuaternion))));
return(_rResult);
}
const TVector4d& UnitQuaternion(TVector4d& _rResult, const TVector4d& _krQuaternion)
{
_rResult = ScalarMultiply( _rResult,
_krQuaternion,
(1.0 / QuaternionMagnitude(_krQuaternion)));
return(_rResult);
}
const TVector4f& UnitQuaternion(TVector4f& _rResult, const TVector4f& _krQuaternion)
{
_rResult = ScalarMultiply( _rResult,
_krQuaternion,
(1.0f / QuaternionMagnitude(_krQuaternion)));
return(_rResult);
}
const TVector4d& AxisAngleQuaternion(TVector4d& _rResult, const TVector3d& _krAxis, const double _kdAngle)
{
_rResult.m_dW = Cosine(_kdAngle / 2.0);
_rResult.m_dX = _krAxis.m_dX * Sine(_kdAngle / 2.0);
_rResult.m_dY = _krAxis.m_dY * Sine(_kdAngle / 2.0);
_rResult.m_dZ = _krAxis.m_dZ * Sine(_kdAngle / 2.0);
return(_rResult);
}
const TVector4f& AxisAngleQuaternion(TVector4f& _rResult, const TVector3f& _krAxis, const float _kfAngle)
{
_rResult.m_fW = Cosine(_kfAngle / 2.0f);
_rResult.m_fX = _krAxis.m_fX * Sine(_kfAngle / 2.0f);
_rResult.m_fY = _krAxis.m_fY * Sine(_kfAngle / 2.0f);
_rResult.m_fZ = _krAxis.m_fZ * Sine(_kfAngle / 2.0f);
return(_rResult);
}
const double QuaternionMagnitude(const TVector4d& _krQuaternion)
{
return(SquareRoot(QuaternionProduct(TVector4d(),
ConjugateQuaternion( TVector4d(),
_krQuaternion),
_krQuaternion).m_dW));
}
const float QuaternionMagnitude(const TVector4f& _krQuaternion)
{
return(SquareRoot(QuaternionProduct(TVector4f(),
ConjugateQuaternion( TVector4f(),
_krQuaternion),
_krQuaternion).m_fW));
}
const TVector4d& QuaternionProduct(TVector4d& _rResult, const TVector4d& _krA, const TVector4d& _krB)
{
_rResult.m_dW = (_krA.m_dW * _krB.m_dW) - (_krA.m_dX * _krB.m_dX) - (_krA.m_dY * _krB.m_dY) - (_krA.m_dZ * _krB.m_dZ);
_rResult.m_dX = (_krA.m_dW * _krB.m_dX) + (_krA.m_dX * _krB.m_dW) + (_krA.m_dY * _krB.m_dZ) - (_krA.m_dZ * _krB.m_dY);
_rResult.m_dY = (_krA.m_dW * _krB.m_dY) - (_krA.m_dX * _krB.m_dZ) + (_krA.m_dY * _krB.m_dW) + (_krA.m_dZ * _krB.m_dX);
_rResult.m_dZ = (_krA.m_dW * _krB.m_dZ) + (_krA.m_dX * _krB.m_dY) - (_krA.m_dY * _krB.m_dX) + (_krA.m_dZ * _krB.m_dW);
return(_rResult);
}
const TVector4f& QuaternionProduct(TVector4f& _rResult, const TVector4f& _krA, const TVector4f& _krB)
{
_rResult.m_fW = (_krA.m_fW * _krB.m_fW) - (_krA.m_fX * _krB.m_fX) - (_krA.m_fY * _krB.m_fY) - (_krA.m_fZ * _krB.m_fZ);
_rResult.m_fX = (_krA.m_fW * _krB.m_fX) + (_krA.m_fX * _krB.m_fW) + (_krA.m_fY * _krB.m_fZ) - (_krA.m_fZ * _krB.m_fY);
_rResult.m_fY = (_krA.m_fW * _krB.m_fY) - (_krA.m_fX * _krB.m_fZ) + (_krA.m_fY * _krB.m_fW) + (_krA.m_fZ * _krB.m_fX);
_rResult.m_fZ = (_krA.m_fW * _krB.m_fZ) + (_krA.m_fX * _krB.m_fY) - (_krA.m_fY * _krB.m_fX) + (_krA.m_fZ * _krB.m_fW);
return(_rResult);
}
const TVector3d& QuaternionRotate(TVector3d& _rResult, const TVector3d& _krVector, const TVector4d& _krQuaternion)
{
const TVector4d kVecAsQuat{_krVector.m_dX, _krVector.m_dY, _krVector.m_dZ, 0.0};
const TVector4d kResultAsQuat = QuaternionProduct(TVector4d(),
QuaternionProduct(TVector4d(), _krQuaternion, kVecAsQuat),
ConjugateQuaternion(TVector4d(), _krQuaternion));
_rResult.m_dX = kResultAsQuat.m_dX;
_rResult.m_dY = kResultAsQuat.m_dY;
_rResult.m_dZ = kResultAsQuat.m_dZ;
return(_rResult);
}
const TVector3f& QuaternionRotate(TVector3f& _rResult, const TVector3f& _krVector, const TVector4f& _krQuaternion)
{
const TVector4f kVecAsQuat{_krVector.m_fX, _krVector.m_fY, _krVector.m_fZ, 0.0f};
const TVector4f kResultAsQuat = QuaternionProduct(TVector4f(),
QuaternionProduct(TVector4f(), _krQuaternion, kVecAsQuat),
ConjugateQuaternion(TVector4f(), _krQuaternion));
_rResult.m_fX = kResultAsQuat.m_fX;
_rResult.m_fY = kResultAsQuat.m_fY;
_rResult.m_fZ = kResultAsQuat.m_fZ;
return(_rResult);
}
const TVector4d& Slerp(TVector4d& _rResult, const TVector4d& _krA, const TVector4d& _krB, const double _kdT)
{
const double kdCosOmega = DotProduct(_krA, _krB);
double dK0, dK1;
if(Magnitude(kdCosOmega) == 1.0) // Avoid divide by zero using lerp
{
dK0 = 1.0 - _kdT;
dK1 = _kdT;
}
else
{
const double kdSinOmega = SquareRoot(1.0 - Square(kdCosOmega));
const double kdOmega = ArcTan2(kdSinOmega, kdCosOmega);
dK0 = Sine((1.0 - _kdT) * kdOmega) * (1.0 / kdSinOmega);
dK1 = Sine(_kdT * kdOmega) * (1.0 / kdSinOmega);
}
_rResult.m_dW = (_krA.m_dW * dK0) + (_krB.m_dW * dK1);
_rResult.m_dX = (_krA.m_dX * dK0) + (_krB.m_dX * dK1);
_rResult.m_dY = (_krA.m_dY * dK0) + (_krB.m_dY * dK1);
_rResult.m_dZ = (_krA.m_dZ * dK0) + (_krB.m_dZ * dK1);
return(_rResult);
}
const TVector4f& Slerp(TVector4f& _rResult, const TVector4f& _krA, const TVector4f& _krB, const float _kfT)
{
const float kfCosOmega = DotProduct(_krA, _krB);
float fK0, fK1;
if(Magnitude(kfCosOmega) == 1.0f) // Avoid divide by zero using lerp
{
fK0 = 1.0f - _kfT;
fK1 = _kfT;
}
else
{
const float kfSinOmega = SquareRoot(1.0f - Square(kfCosOmega));
const float kfOmega = ArcTan2(kfSinOmega, kfCosOmega);
fK0 = Sine((1.0f - _kfT) * kfOmega) * (1.0f / kfSinOmega);
fK1 = Sine(_kfT * kfOmega) * (1.0f / kfSinOmega);
}
_rResult.m_fW = (_krA.m_fW * fK0) + (_krB.m_fW * fK1);
_rResult.m_fX = (_krA.m_fX * fK0) + (_krB.m_fX * fK1);
_rResult.m_fY = (_krA.m_fY * fK0) + (_krB.m_fY * fK1);
_rResult.m_fZ = (_krA.m_fZ * fK0) + (_krB.m_fZ * fK1);
return(_rResult);
}