prime/src/MetroidPrime/CEulerAngles.cpp
Luke Street abef49951c Minor CEulerAngles progress
Former-commit-id: 67f01bc9cd41528478f6f153dc3f9dd1c07567d1
2022-12-07 00:13:59 -05:00

57 lines
1.9 KiB
C++

#include "MetroidPrime/CEulerAngles.hpp"
#include "Kyoto/Math/CMath.hpp"
#include "Kyoto/Math/CMatrix3f.hpp"
#include "Kyoto/Math/CQuaternion.hpp"
#include "Kyoto/Math/CTransform4f.hpp"
#include "Kyoto/Math/CloseEnough.hpp"
CEulerAngles CEulerAngles::sIdentity(0.f, 0.f, 0.f);
CEulerAngles CEulerAngles::FromTransform(const CTransform4f& xf) {
// TODO: actually CMatrix3f::FromTransform and uninlined, why?
CMatrix3f mtx(xf);
float sq = sqrt(mtx.Get11() * mtx.Get11() + mtx.Get01() * mtx.Get01());
if (!close_enough(sq, 0.f)) {
double yaw = -atan2(mtx.Get01(), mtx.Get11());
double pitch = -atan2(mtx.Get20(), mtx.Get22());
double roll = -atan2(-mtx.Get21(), sq);
return CEulerAngles(roll, pitch, yaw);
} else {
double pitch = -atan2(-mtx.Get02(), mtx.Get00());
double roll = -atan2(-mtx.Get21(), sq);
return CEulerAngles(roll, pitch, 0.f);
}
}
CEulerAngles CEulerAngles::FromQuaternion(const CQuaternion& quat) {
float quatDot = CQuaternion::Dot(quat, quat);
float t0 = 0.f;
if (quatDot > 0.f)
t0 = 2.f / quatDot;
double t1 = 1.0 - (t0 * quat.GetX() * quat.GetX() + t0 * quat.GetZ() * quat.GetZ());
double t2 = t0 * quat.GetY() * quat.GetX() - t0 * quat.GetZ() * quat.GetW();
double t3 = t1 * t1 + t2 * t2;
double t4 = 0.0;
if (t3 > 0.0)
t4 = CMath::SqrtD(t3);
double t5 = t0 * quat.GetZ() * quat.GetY() + t0 * quat.GetX() * quat.GetW();
if (close_enough(t4, 0.0)) {
return CEulerAngles(
-atan2(-t5, t4),
-atan2(-(t0 * quat.GetZ() * quat.GetX() + t0 * quat.GetY() * quat.GetW()),
1.0 - (t0 * quat.GetY() * quat.GetY() + t0 * quat.GetZ() * quat.GetZ())),
0.0f);
} else {
return CEulerAngles(
-atan2(-t5, t4),
-atan2(t0 * quat.GetZ() * quat.GetX() - t0 * quat.GetY() * quat.GetW(),
1.0 - (t0 * quat.GetX() * quat.GetX() + t0 * quat.GetY() * quat.GetY())),
-atan2(t2, t1));
}
}