2015-04-19 20:39:16 +00:00
|
|
|
#ifndef CQUATERNION_HPP
|
|
|
|
#define CQUATERNION_HPP
|
|
|
|
|
|
|
|
#include "Global.hpp"
|
|
|
|
#include "CAxisAngle.hpp"
|
|
|
|
#include "CVector3f.hpp"
|
2015-08-12 01:41:28 +00:00
|
|
|
#include "CVector4f.hpp"
|
2015-04-19 20:39:16 +00:00
|
|
|
#include <math.h>
|
2015-11-01 12:04:29 +00:00
|
|
|
#if ZE_ATHENA_TYPES
|
2015-04-19 20:39:16 +00:00
|
|
|
#include <Athena/IStreamReader.hpp>
|
2015-11-01 12:04:29 +00:00
|
|
|
#endif
|
2015-04-19 20:39:16 +00:00
|
|
|
|
2015-10-08 00:21:38 +00:00
|
|
|
namespace Zeus
|
|
|
|
{
|
2015-10-25 19:31:41 +00:00
|
|
|
class alignas(16) CQuaternion
|
2015-04-19 20:39:16 +00:00
|
|
|
{
|
2016-01-17 22:40:48 +00:00
|
|
|
#if __atdna__ && ZE_ATHENA_TYPES
|
|
|
|
float clangVec __attribute__((__vector_size__(16)));
|
|
|
|
#endif
|
2015-04-19 20:39:16 +00:00
|
|
|
public:
|
|
|
|
ZE_DECLARE_ALIGNED_ALLOCATOR();
|
|
|
|
|
2015-08-12 01:41:28 +00:00
|
|
|
CQuaternion() : r(1.0f) {}
|
2016-01-17 15:56:45 +00:00
|
|
|
CQuaternion(float r, float x, float y, float z) : v(x, y, z){ this->r = r; }
|
2015-08-12 01:41:28 +00:00
|
|
|
CQuaternion(float x, float y, float z) { fromVector3f(CVector3f(x, y, z)); }
|
2016-01-17 15:55:45 +00:00
|
|
|
CQuaternion(float r, const CVector3f& vec) : v(vec){ this->r = r;}
|
2015-11-01 12:04:29 +00:00
|
|
|
#if ZE_ATHENA_TYPES
|
2015-08-12 01:41:28 +00:00
|
|
|
CQuaternion(Athena::io::IStreamReader& input) { r = input.readFloat(); v = CVector3f(input);}
|
2016-01-17 22:40:48 +00:00
|
|
|
CQuaternion(const atVec4f& vec)
|
|
|
|
{
|
|
|
|
#if __SSE__
|
|
|
|
v.mVec128 = vec.mVec128;
|
|
|
|
#else
|
|
|
|
x = vec.vec[0]; y = vec.vec[1]; z = vec.vec[2]; r = vec.vec[3];
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
operator atVec4f()
|
|
|
|
{
|
|
|
|
atVec4f ret;
|
|
|
|
#if __SSE__
|
|
|
|
ret.mVec128 = v.mVec128;
|
|
|
|
#else
|
|
|
|
ret.vec = v;
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
operator atVec4f() const
|
|
|
|
{
|
|
|
|
atVec4f ret;
|
|
|
|
#if __SSE__
|
|
|
|
ret.mVec128 = v.mVec128;
|
|
|
|
#else
|
|
|
|
ret.vec = v;
|
|
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-11-01 12:04:29 +00:00
|
|
|
#endif
|
2015-08-12 01:41:28 +00:00
|
|
|
CQuaternion(const CVector3f& vec) { fromVector3f(vec); }
|
|
|
|
CQuaternion(const CVector4f& vec)
|
|
|
|
{
|
|
|
|
#if __SSE__
|
2016-01-17 05:45:47 +00:00
|
|
|
v.mVec128 = vec.mVec128;
|
2015-08-12 01:41:28 +00:00
|
|
|
#else
|
2016-01-17 05:45:47 +00:00
|
|
|
v.x = vec.x; v.y = vec.y; v.z = vec.z; r = vec.w;
|
2015-08-12 01:41:28 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~CQuaternion() {}
|
2015-04-19 20:39:16 +00:00
|
|
|
|
|
|
|
void fromVector3f(const CVector3f& vec);
|
|
|
|
|
|
|
|
CQuaternion& operator=(const CQuaternion& q);
|
|
|
|
CQuaternion operator+(const CQuaternion& q) const;
|
|
|
|
CQuaternion operator-(const CQuaternion& q) const;
|
|
|
|
CQuaternion operator*(const CQuaternion& q) const;
|
|
|
|
CQuaternion operator/(const CQuaternion& q) const;
|
|
|
|
CQuaternion operator*(float scale) const;
|
|
|
|
CQuaternion operator/(float scale) const;
|
|
|
|
CQuaternion operator-() const;
|
|
|
|
const CQuaternion& operator+=(const CQuaternion& q);
|
|
|
|
const CQuaternion& operator-=(const CQuaternion& q);
|
|
|
|
const CQuaternion& operator*=(const CQuaternion& q);
|
|
|
|
const CQuaternion& operator*=(float scale);
|
|
|
|
const CQuaternion& operator/=(float scale);
|
2015-10-08 00:21:38 +00:00
|
|
|
float magnitude() const;
|
|
|
|
float magSquared() const;
|
2015-04-19 20:39:16 +00:00
|
|
|
void normalize();
|
|
|
|
CQuaternion normalized() const;
|
|
|
|
void invert();
|
|
|
|
CQuaternion inverse() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Set the rotation using axis angle notation
|
|
|
|
* @param axis The axis to rotate around
|
|
|
|
* @param angle The magnitude of the rotation in radians
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
static inline CQuaternion fromAxisAngle(const CVector3f& axis, float angle)
|
|
|
|
{
|
|
|
|
return CQuaternion(cosf(angle/2), axis*sinf(angle/2));
|
|
|
|
}
|
|
|
|
|
2016-02-02 08:29:16 +00:00
|
|
|
void rotateX(float angle) { *this *= fromAxisAngle({1.0f, 0.0f, 0.0f}, angle); }
|
|
|
|
void rotateY(float angle) { *this *= fromAxisAngle({0.0f, 1.0f, 0.0f}, angle); }
|
|
|
|
void rotateZ(float angle) { *this *= fromAxisAngle({0.0f, 0.0f, 1.0f}, angle); }
|
|
|
|
|
|
|
|
|
2015-04-19 20:39:16 +00:00
|
|
|
CAxisAngle toAxisAngle();
|
|
|
|
|
|
|
|
static inline CVector3f rotate(const CQuaternion& rotation, const CVector3f& v)
|
|
|
|
{
|
|
|
|
CQuaternion q = rotation * v;
|
|
|
|
q *= rotation.inverse();
|
|
|
|
|
|
|
|
return q.v;
|
|
|
|
}
|
|
|
|
|
|
|
|
CQuaternion log() const;
|
|
|
|
|
|
|
|
CQuaternion exp() const;
|
|
|
|
|
|
|
|
float dot(const CQuaternion& quat);
|
|
|
|
|
|
|
|
static CQuaternion lerp(CQuaternion& a, CQuaternion& b, double t);
|
|
|
|
static CQuaternion slerp(CQuaternion& a, CQuaternion& b, double t);
|
|
|
|
static CQuaternion nlerp(CQuaternion& a, CQuaternion& b, double t);
|
|
|
|
|
|
|
|
inline float roll() const
|
|
|
|
{
|
|
|
|
return atan2f(2.0 * (v.x * v.y + r * v.z), r * r + v.x * v.x - v.y * v.y - v.z * v.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline float pitch() const
|
|
|
|
{
|
|
|
|
return atan2f(2.0 * (v.y * v.z + r * v.x), r * r - v.x * v.x - v.y * v.y + v.z * v.z);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline float yaw() const
|
|
|
|
{
|
|
|
|
return asinf(-2.0 * (v.x * v.z - r * v.y));
|
|
|
|
}
|
|
|
|
|
2016-01-17 05:45:47 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
struct { float x, y, z, r; };
|
|
|
|
CVector3f v;
|
|
|
|
};
|
2015-04-19 20:39:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
CQuaternion operator+(float lhs, const CQuaternion& rhs);
|
|
|
|
CQuaternion operator-(float lhs, const CQuaternion& rhs);
|
|
|
|
CQuaternion operator*(float lhs, const CQuaternion& rhs);
|
2015-10-08 00:21:38 +00:00
|
|
|
}
|
2015-04-19 20:39:16 +00:00
|
|
|
#endif // CQUATERNION_HPP
|