134 lines
3.7 KiB
C++
134 lines
3.7 KiB
C++
/* ================================================================
|
|
Quat
|
|
````````````````
|
|
This file defines the Quaternion class
|
|
================================================================ */
|
|
#include "Quat.hpp"
|
|
#include <math.h>
|
|
#define PIOVER180 0.01745329252
|
|
Quat::Quat() {
|
|
x = y = z = w = 0.0f;
|
|
};
|
|
Quat::Quat(float x_, float y_, float z_, float w_) {
|
|
x = x_;
|
|
y = y_;
|
|
z = z_;
|
|
w = w_;
|
|
}
|
|
// Tait-bryan angles to Quat constructor
|
|
Quat::Quat(float pitch, float yaw, float roll) {
|
|
float cp = (float)cos(pitch * PIOVER180 / 2.0f);
|
|
float cy = (float)cos(-yaw * PIOVER180 / 2.0f);
|
|
float cr = (float)cos(-roll * PIOVER180 / 2.0f);
|
|
float cycr = cy * cr;
|
|
float sp = (float)sin(pitch * PIOVER180 / 2.0f);
|
|
float sy = (float)sin(-yaw * PIOVER180 / 2.0f);
|
|
float sr = (float)sin(-roll * PIOVER180 / 2.0f);
|
|
float srsy = sr * sy;
|
|
|
|
x = cycr * sp + srsy * cp;
|
|
y = cr * sy * cp - sr * cy * sp;
|
|
z = sr * cy * cp + cr * sy * sp;
|
|
w = cycr * cp - srsy * sp;
|
|
normalize();
|
|
}
|
|
Quat::Quat(const Vec3 &v, float angle) {
|
|
angle *= 0.5f;
|
|
Vec3 vn(v);
|
|
vn.normalize();
|
|
|
|
float sin_angle = sin(angle);
|
|
|
|
x = vn.x * sin_angle;
|
|
y = vn.y * sin_angle;
|
|
z = vn.z * sin_angle;
|
|
w = cos(angle);
|
|
}
|
|
Quat Quat::operator*(const Quat &quat_) const {
|
|
Quat new_Quat;
|
|
new_Quat.x = w*quat_.x + x*quat_.w + y*quat_.z - z*quat_.y;
|
|
new_Quat.y = w*quat_.y + y*quat_.w + z*quat_.x - x*quat_.z;
|
|
new_Quat.z = w*quat_.z + z*quat_.w + x*quat_.y - y*quat_.x;
|
|
new_Quat.w = w*quat_.w - x*quat_.x - y*quat_.y - z*quat_.z;
|
|
|
|
return new_Quat;
|
|
}
|
|
Quat::~Quat() {}
|
|
// rotate Vec3 by Quat
|
|
Vec3 Quat::operator*(const Vec3 &vec) const {
|
|
Vec3 newvec(vec);
|
|
newvec.normalize();
|
|
|
|
Quat vec_quat, res_quat;
|
|
vec_quat.x = newvec.x;
|
|
vec_quat.y = newvec.y;
|
|
vec_quat.z = newvec.z;
|
|
vec_quat.w = 0.0f;
|
|
|
|
res_quat = vec_quat * getConjugate();
|
|
res_quat = *this * res_quat;
|
|
return (Vec3(res_quat.x, res_quat.y, res_quat.z));
|
|
}
|
|
void Quat::operator*=(const Quat &quat_) {
|
|
w = w*quat_.w - x*quat_.x - y*quat_.y - z*quat_.z;
|
|
x = w*quat_.x + x*quat_.w + y*quat_.z - z*quat_.y;
|
|
y = w*quat_.y - x*quat_.z + y*quat_.w + z*quat_.x;
|
|
z = w*quat_.z + x*quat_.y - y*quat_.x + z*quat_.w;
|
|
}
|
|
|
|
void Quat::normalize() {
|
|
float magnitude = sqrt(w*w + x*x + y*y + z*z);
|
|
x /= magnitude;
|
|
y /= magnitude;
|
|
z /= magnitude;
|
|
w /= magnitude;
|
|
}
|
|
|
|
Quat Quat::getConjugate() const {
|
|
return Quat(-x, -y, -z, w);
|
|
}
|
|
float Quat::getPitch() {
|
|
return asin(2.0f * (w * x - z * y));
|
|
}
|
|
float Quat::getYaw() {
|
|
return atan2(2.0f * (w * y + x * z), 1.0f - 2.0f * (x * x + y * y));
|
|
}
|
|
float Quat::getRoll() {
|
|
return atan2(2.0f * (w * z + y * x), 1.0f - 2.0f * (x * x + z * z));
|
|
}
|
|
Mat4 Quat::toMat4() const {
|
|
float x2 = x * x;
|
|
float y2 = y * y;
|
|
float z2 = z * z;
|
|
float xy = x * y;
|
|
float xz = x * z;
|
|
float yz = y * z;
|
|
float wx = w * x;
|
|
float wy = w * y;
|
|
float wz = w * z;
|
|
|
|
return Mat4(
|
|
Vec4(1.0f - 2.0f * (y2 + z2), 2.0f * (xy - wz), 2.0f * (xz + wy), 0.0f),
|
|
Vec4(2.0f * (xy + wz), 1.0f - 2.0f * (x2 + z2), 2.0f * (yz - wx), 0.0f),
|
|
Vec4(2.0f * (xz - wy), 2.0f * (yz + wx), 1.0f - 2.0f * (x2 + y2), 0.0f),
|
|
Vec4(0.0f, 0.0f, 0.0f, 1.0f)
|
|
);
|
|
}
|
|
float *Quat::toMatrix(float matrix[]) const {
|
|
float x2 = x * x;
|
|
float y2 = y * y;
|
|
float z2 = z * z;
|
|
float xy = x * y;
|
|
float xz = x * z;
|
|
float yz = y * z;
|
|
float wx = w * x;
|
|
float wy = w * y;
|
|
float wz = w * z;
|
|
|
|
matrix[0] = 1.0f - 2.0f * (y2 + z2); matrix[1] = 2.0f * (xy - wz); matrix[2] = 2.0f * (xz + wy); matrix[3] = 0.0f;
|
|
matrix[4] = 2.0f * (xy + wz); matrix[5] = 1.0f - 2.0f * (x2 + z2); matrix[6] = 2.0f * (yz - wx); matrix[7] = 0.0f;
|
|
matrix[8] = 2.0f * (xz - wy); matrix[9] = 2.0f * (yz + wx); matrix[10] = 1.0f - 2.0f * (x2 + y2); matrix[11] = 0.0f;
|
|
matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f;
|
|
return matrix;
|
|
}
|