BizHawk/ppsspp/native/math/lin/quat.h

93 lines
2.1 KiB
C++

#ifndef _MATH_LIN_QUAT_H
#define _MATH_LIN_QUAT_H
#include "math/lin/vec3.h"
class Matrix4x4;
class Quaternion
{
public:
float x,y,z,w;
Quaternion() { }
Quaternion(const float _x, const float _y, const float _z, const float _w) {
x=_x; y=_y; z=_z; w=_w;
}
void setIdentity()
{
x=y=z=0; w=1.0f;
}
void setXRotation(const float r) { w = cosf(r / 2); x = sinf(r / 2); y = z = 0; }
void setYRotation(const float r) { w = cosf(r / 2); y = sinf(r / 2); x = z = 0; }
void setZRotation(const float r) { w = cosf(r / 2); z = sinf(r / 2); x = y = 0; }
void toMatrix(Matrix4x4 *out) const;
static Quaternion fromMatrix(Matrix4x4 &m);
Quaternion operator *(Quaternion &q) const
{
return Quaternion(
(w * q.w) - (x * q.x) - (y * q.y) - (z * q.z),
(w * q.x) + (x * q.w) + (y * q.z) - (z * q.y),
(w * q.y) + (y * q.w) + (z * q.x) - (x * q.z),
(w * q.z) + (z * q.w) + (x * q.y) - (y * q.x)
);
}
Quaternion operator -()
{
return Quaternion(-x,-y,-z,-w);
}
void setRotation(Vec3 axis, float angle)
{
axis /= axis.length();
angle *= .5f;
float sine = sinf(angle);
w = cosf(angle);
x = sine * axis.x;
y = sine * axis.y;
z = sine * axis.z;
}
void toAxisAngle(Vec3 &v, float &angle)
{
normalize();
if (w==1.0f && x==0.0f && y==0.0f && z==0.0f)
{
v = Vec3(0,1,0);
angle = 0.0f;
return;
}
float cos_a = w;
angle = acosf(cos_a) * 2;
float sin_a = sqrtf( 1.0f - cos_a * cos_a );
if (fabsf(sin_a) < 0.00005f) sin_a = 1;
float inv_sin_a=1.0f/sin_a;
v.x = x * inv_sin_a;
v.y = y * inv_sin_a;
v.z = z * inv_sin_a;
}
enum {
QUAT_SHORT,
QUAT_LONG,
QUAT_CW,
QUAT_CCW
};
Quaternion slerp(const Quaternion &to, const float a) const;
Quaternion multiply(const Quaternion &q) const;
float &operator [] (int i) {
return *((&x) + i);
}
float operator [] (int i) const {
return *((&x) + i);
}
//not sure about this, maybe mag is supposed to sqrt
float magnitude() const {
return x*x + y*y + z*z + w*w;
}
void normalize() {
float f = 1.0f/sqrtf(magnitude());
x*=f; y*=f; z*=f; w*=f;
}
};
#endif // _MATH_LIN_QUAT_H