www.pudn.com > zfxcengine-0.1.0.zip > ceQuaternion.cpp
// $Id: ceQuaternion.cpp,v 1.12 2005/09/13 00:47:15 andreaskohn Exp $ #include#include #include "Core/ceDebug.h" #include "Math/ceMath.h" namespace ZFXCE { using namespace std; //////////////////////////////////////////////////////////////////////////////// void ceQuaternion::MakeFromEuler(FLOAT fPitch, FLOAT fYaw, FLOAT fRoll) { fPitch *= 0.5f; fYaw *= 0.5f; fRoll *= 0.5f; const FLOAT cX = cosf(fPitch * 0.5f); const FLOAT cY = cosf(fYaw * 0.5f); const FLOAT cZ = cosf(fRoll * 0.5f); const FLOAT sX = sinf(fPitch * 0.5f); const FLOAT sY = sinf(fYaw * 0.5f); const FLOAT sZ = sinf(fRoll * 0.5f); const FLOAT cYcZ = cY * cZ; const FLOAT sYsZ = sY * sZ; const FLOAT cYsZ = cY * sZ; const FLOAT sYcZ = sY * cZ; w = cX * cYcZ + sX * sYsZ; x = sX * cYcZ - cX * sYsZ; y = cX * sYcZ + sX * cYsZ; z = cX * cYsZ - sX * sYcZ; } //////////////////////////////////////////////////////////////////////////////// void ceQuaternion::Conjugate(ceQuaternion q) { x = -q.x; y = -q.y; z = -q.z; w = q.w; } //////////////////////////////////////////////////////////////////////////////// void ceQuaternion::GetEulers(FLOAT* pfPitch, FLOAT* pfYaw, FLOAT* pfRoll) const { const FLOAT q00 = w * w; const FLOAT q11 = x * x; const FLOAT q22 = y * y; const FLOAT q33 = z * z; const FLOAT r11 = q00 + q11 - q22 - q33; const FLOAT r21 = 2 * (x*y + w*z); const FLOAT r31 = 2 * (x*z - w*y); const FLOAT r32 = 2 * (y*z + w*x); const FLOAT r33 = q00 - q11 - q22 + q33; const FLOAT tmp = _fabs(r31); if (tmp > 0.999999) { const FLOAT r12 = 2 * (x*y - w*z); const FLOAT r13 = 2 * (x*z + w*y); if(pfPitch) *pfPitch = 0.0f; if(pfYaw) *pfYaw = (FLOAT)-((cePI * 0.5f) * r31/tmp); if(pfRoll) *pfRoll = (FLOAT)atan2(-r12, -r31*r13); } else { if (pfPitch) *pfPitch = (FLOAT) atan2(r32, r33); if (pfYaw) *pfYaw = (FLOAT) asin(-r31); if (pfRoll) *pfRoll = (FLOAT) atan2(r21, r11); } } //////////////////////////////////////////////////////////////////////////////// void ceQuaternion::GetMatrix(ceMatrix* pM) const { ce_assert (NULL != pM); pM->Identity(); const FLOAT x2 = x + x; const FLOAT y2 = y + y; const FLOAT z2 = z + z; const FLOAT xx = x * x2; const FLOAT xy = x * y2; const FLOAT xz = x * z2; const FLOAT yy = y * y2; const FLOAT yz = y * z2; const FLOAT zz = z * z2; const FLOAT wx = w * x2; const FLOAT wy = w * y2; const FLOAT wz = w * z2; pM->_ms._11 = 1.0f - (yy + zz); pM->_ms._12 = xy - wz; pM->_ms._13 = xz + wy; pM->_ms._21 = xy + wz; pM->_ms._22 = 1.0f - (xx + zz); pM->_ms._23 = yz - wx; pM->_ms._31 = xz - wy; pM->_ms._32 = yz + wx; pM->_ms._33 = 1.0f - (xx + yy); } //////////////////////////////////////////////////////////////////////////////// FLOAT ceQuaternion::GetMagnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } //////////////////////////////////////////////////////////////////////////////// ceQuaternion &ceQuaternion::Normalize() { const FLOAT n = x*x + y*y + z*z + w*w; if (1.0f != n) { operator/=(sqrtf(n)); } return *this; } //////////////////////////////////////////////////////////////////////////////// ceQuaternion &ceQuaternion::operator /=(const FLOAT f) { if (f != 0.0f) { operator*=(1.0f / f); } return *this; } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator /(const FLOAT f) const { // XXX: avoiding div-by-zero violates general / contract! if (f != 0.0f) { const FLOAT fVal = 1 / f; return ceQuaternion(x*fVal, y*fVal, z*fVal, w*fVal); } else { return *this; } } //////////////////////////////////////////////////////////////////////////////// ceQuaternion &ceQuaternion::operator *=(const FLOAT f) { x *= f; y *= f; z *= f; w *= f; return *this; } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator *(const FLOAT f) const { return ceQuaternion(x*f, y*f, z*f, w*f); } //////////////////////////////////////////////////////////////////////////////// ceQuaternion &ceQuaternion::operator +=(const ceQuaternion& q) { x += q.x; y += q.y; z += q.z; w += q.w; return *this; } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator +(const ceQuaternion& q) const { return ceQuaternion(x+q.x, y+q.y, z+q.z, w+q.w); } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator *(const ceVec4f& v) const { return ceQuaternion( w*v.x + y*v.z - z*v.y, w*v.y + z*v.x - x*v.z, w*v.z + x*v.y - y*v.x, -(x*v.x + y*v.y + z*v.z) ); } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator *(const ceVec3f& v) const { return ceQuaternion(w*v.x + y*v.z - z*v.y, w*v.y + z*v.x - x*v.z, w*v.z + x*v.y - y*v.x, -(x*v.x + y*v.y + z*v.z) ); } //////////////////////////////////////////////////////////////////////////////// ceQuaternion ceQuaternion::operator *(const ceQuaternion& q) const { ceQuaternion Result; Result.x = w*q.x + x*q.w + y*q.z - z*q.y; Result.y = w*q.y + y*q.w + z*q.x - x*q.z; Result.z = w*q.z + z*q.w + x*q.y - y*q.x; Result.w = w*q.w - x*q.x - y*q.y - z*q.z; return Result; } //////////////////////////////////////////////////////////////////////////////// ceQuaternion &ceQuaternion::operator *= (const ceQuaternion& q) { const FLOAT _x = w*q.x + x*q.w + y*q.z - z*q.y; const FLOAT _y = w*q.y + y*q.w + z*q.x - x*q.z; const FLOAT _z = w*q.z + z*q.w + x*q.y - y*q.x; const FLOAT _w = w*q.w - x*q.x - y*q.y - z*q.z; x = _x; y = _y; z = _z; w = _w; return *this; } //////////////////////////////////////////////////////////////////////////////// void ceQuaternion::Rotate(const ceQuaternion& q1, const ceQuaternion& q2) { const ceQuaternion q = q1 * q2 * (~q1); x = q.x; y = q.y; z = q.z; w = q.w; } //////////////////////////////////////////////////////////////////////////////// ceVec4f ceQuaternion::Rotate(const ceVec4f& v) { const ceQuaternion q(x,y,z,w); const ceQuaternion r = q * v * (~q); x = r.x; y = r.y; z = r.z; w = r.w; // XXX: check if we should return r.w in w. return ceVec4f(r.x, r.y, r.z); } //////////////////////////////////////////////////////////////////////////////// } // Namespace ZFXCE