mirror of https://github.com/AxioDL/zeus.git
287 lines
5.5 KiB
C++
287 lines
5.5 KiB
C++
|
#include "CQuaternion.hpp"
|
||
|
#include <math.h>
|
||
|
|
||
|
CQuaternion::CQuaternion()
|
||
|
: r(1.0f)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CQuaternion::CQuaternion(float r, float x, float y, float z)
|
||
|
: r(r), v(x, y, z)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CQuaternion::CQuaternion(float x, float y, float z)
|
||
|
{
|
||
|
fromVector3f(CVector3f(x, y, z));
|
||
|
}
|
||
|
|
||
|
CQuaternion::CQuaternion(const CVector3f& vec)
|
||
|
{
|
||
|
fromVector3f(vec);
|
||
|
}
|
||
|
|
||
|
CQuaternion::CQuaternion(float r, const CVector3f& vec)
|
||
|
: r(r), v(vec)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CQuaternion::CQuaternion(Athena::io::IStreamReader& input)
|
||
|
{
|
||
|
r = input.readFloat();
|
||
|
v = CVector3f(input);
|
||
|
}
|
||
|
|
||
|
CQuaternion::~CQuaternion()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CQuaternion::fromVector3f(const CVector3f& vec)
|
||
|
{
|
||
|
float cosX = cosf(0.5 * vec.x);
|
||
|
float cosY = cosf(0.5 * vec.y);
|
||
|
float cosZ = cosf(0.5 * vec.z);
|
||
|
|
||
|
float sinX = sinf(0.5 * vec.x);
|
||
|
float sinY = sinf(0.5 * vec.y);
|
||
|
float sinZ = sinf(0.5 * vec.z);
|
||
|
|
||
|
r = cosZ * cosY * cosX + sinZ * sinY * sinX;
|
||
|
v.x = cosZ * cosY * sinX - sinZ * sinY * cosX;
|
||
|
v.y = cosZ * sinY * cosX + sinZ * cosY * sinX;
|
||
|
v.z = sinZ * cosY * cosX - cosZ * sinY * sinX;
|
||
|
}
|
||
|
|
||
|
CQuaternion& CQuaternion::operator=(const CQuaternion& q)
|
||
|
{
|
||
|
r = q.r;
|
||
|
v = q.v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator+(const CQuaternion& q) const
|
||
|
{
|
||
|
return CQuaternion(r + q.r, v+q.v);
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator-(const CQuaternion& q) const
|
||
|
{
|
||
|
return CQuaternion(r - q.r, v-q.v);
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator*(const CQuaternion& q) const
|
||
|
{
|
||
|
return CQuaternion(r*q.r - v.dot(q.v),
|
||
|
v.y * q.v.z - v.z * q.v.y + r * q.v.x + v.x*q.r,
|
||
|
v.z * q.v.x - v.x * q.v.z + r * q.v.y + v.y*q.r,
|
||
|
v.x * q.v.y - v.y * q.v.x + r * q.v.z + v.z*q.r);
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator/(const CQuaternion& q) const
|
||
|
{
|
||
|
CQuaternion p(q);
|
||
|
p.invert();
|
||
|
return *this * p;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator*(float scale) const
|
||
|
{
|
||
|
return CQuaternion(r*scale, v*scale);
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator/(float scale) const
|
||
|
{
|
||
|
return CQuaternion(r/scale, v/scale);
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::operator-() const
|
||
|
{
|
||
|
return CQuaternion(-r, -v);
|
||
|
}
|
||
|
|
||
|
const CQuaternion& CQuaternion::operator+=(const CQuaternion& q)
|
||
|
{
|
||
|
r += q.r;
|
||
|
v += q.v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
const CQuaternion& CQuaternion::operator-=(const CQuaternion& q)
|
||
|
{
|
||
|
r -= q.r;
|
||
|
v -= q.v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
const CQuaternion& CQuaternion::operator *=(const CQuaternion& q)
|
||
|
{
|
||
|
r = r*q.r - v.dot(q.v);
|
||
|
v.x = v.y * q.v.z - v.z * q.v.y + r * q.v.x + v.x*q.r;
|
||
|
v.y = v.z * q.v.x - v.x * q.v.z + r * q.v.y + v.y*q.r;
|
||
|
v.z = v.x * q.v.y - v.y * q.v.x + r * q.v.z + v.z*q.r;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
const CQuaternion& CQuaternion::operator *=(float scale)
|
||
|
{
|
||
|
r *= scale;
|
||
|
v *= scale;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
const CQuaternion& CQuaternion::operator/=(float scale)
|
||
|
{
|
||
|
r /= scale;
|
||
|
v /= scale;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
float CQuaternion::length() const
|
||
|
{
|
||
|
return sqrt(lengthSquared());
|
||
|
}
|
||
|
|
||
|
float CQuaternion::lengthSquared() const
|
||
|
{
|
||
|
return (r*r + (v.dot(v)));
|
||
|
}
|
||
|
|
||
|
void CQuaternion::normalize()
|
||
|
{
|
||
|
*this /= length();
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::normalized() const
|
||
|
{
|
||
|
return *this/length();
|
||
|
}
|
||
|
|
||
|
void CQuaternion::invert()
|
||
|
{
|
||
|
v = -v;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::inverse() const
|
||
|
{
|
||
|
return CQuaternion(r, -v);
|
||
|
}
|
||
|
|
||
|
CAxisAngle CQuaternion::toAxisAngle()
|
||
|
{
|
||
|
CAxisAngle ret;
|
||
|
ret.angle = acosf(r);
|
||
|
|
||
|
float thetaInv = 1.0f/sinf(ret.angle);
|
||
|
|
||
|
ret.axis.x = v.x * thetaInv;
|
||
|
ret.axis.y = v.y * thetaInv;
|
||
|
ret.axis.z = v.z * thetaInv;
|
||
|
|
||
|
ret.angle *= 2;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::log() const
|
||
|
{
|
||
|
float a = acosf(r);
|
||
|
float sina = sinf(a);
|
||
|
CQuaternion ret;
|
||
|
|
||
|
ret.r = 0;
|
||
|
|
||
|
if (sina > 0)
|
||
|
{
|
||
|
ret.v.x = a * v.x / sina;
|
||
|
ret.v.y = a * v.y / sina;
|
||
|
ret.v.z = a * v.z / sina;
|
||
|
}
|
||
|
else
|
||
|
ret.v = CVector3f(0);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::exp() const
|
||
|
{
|
||
|
float a = (v.length());
|
||
|
float sina = sinf(a);
|
||
|
float cosa = cos(a);
|
||
|
CQuaternion ret;
|
||
|
|
||
|
ret.r = cosa;
|
||
|
if (a > 0)
|
||
|
{
|
||
|
ret.v.x = sina * v.x / a;
|
||
|
ret.v.y = sina * v.y / a;
|
||
|
ret.v.z = sina * v.z / a;
|
||
|
}
|
||
|
else
|
||
|
ret.v = CVector3f(0);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
float CQuaternion::dot(const CQuaternion& b)
|
||
|
{
|
||
|
return v.x * b.v.x + v.y * b.v.y + v.z * b.v.z + r * b.r;
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::lerp(CQuaternion& a, CQuaternion& b, double t)
|
||
|
{
|
||
|
return (a + t * (b - a));
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::nlerp(CQuaternion& a, CQuaternion& b, double t)
|
||
|
{
|
||
|
return lerp(a, b, t).normalized();
|
||
|
}
|
||
|
|
||
|
CQuaternion CQuaternion::slerp(CQuaternion& a, CQuaternion& b, double t)
|
||
|
{
|
||
|
if (t <= 0.0f)
|
||
|
return a;
|
||
|
if (t >= 1.0f)
|
||
|
return b;
|
||
|
|
||
|
CQuaternion ret;
|
||
|
|
||
|
float mag = sqrtf(a.dot(a) * b.dot(b));
|
||
|
|
||
|
float prod = a.dot(b) / mag;
|
||
|
|
||
|
if (fabsf(prod) < 1.0)
|
||
|
{
|
||
|
const double sign = (prod < 0.0) ? -1.0 : 1.0;
|
||
|
|
||
|
const double theta = acos(sign * prod);
|
||
|
const double s1 = sin (sign * t * theta);
|
||
|
const double d = 1.0 / sin(theta);
|
||
|
const double s0 = sin((1.0 - t) * theta);
|
||
|
|
||
|
ret.v.x = (float)(a.v.x * s0 + b.v.x * s1) * d;
|
||
|
ret.v.y = (float)(a.v.y * s0 + b.v.y * s1) * d;
|
||
|
ret.v.z = (float)(a.v.z * s0 + b.v.z * s1) * d;
|
||
|
ret.r = (float)(a.r * s0 + b.r * s1) * d;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
CQuaternion operator+(float lhs, const CQuaternion& rhs)
|
||
|
{
|
||
|
return CQuaternion(lhs + rhs.r, lhs * rhs.v);
|
||
|
}
|
||
|
|
||
|
CQuaternion operator-(float lhs, const CQuaternion& rhs)
|
||
|
{
|
||
|
return CQuaternion(lhs - rhs.r, lhs * rhs.v);
|
||
|
}
|
||
|
|
||
|
CQuaternion operator*(float lhs, const CQuaternion& rhs)
|
||
|
{
|
||
|
return CQuaternion(lhs * rhs.r, lhs * rhs.v);
|
||
|
}
|