Hi everybody,
I was always amazed in the bad way how Quaternion to Euler gives so much imprecise result.
Here he code I use:
void Quaternion::FromEulerAngles(const float X, const float Y, const float Z)
{
const float HP = 0.5f * X;
const float HY = 0.5f * Y;
const float HR = 0.5f * Z;
const float SinHP = CMath::Sin(HP);
const float SinHY = CMath::Sin(HY);
const float SinHR = CMath::Sin(HR);
const float CosHP = CMath::Cos(HP);
const float CosHY = CMath::Cos(HY);
const float CosHR = CMath::Cos(HR);
x = CosHY * SinHP * CosHR + SinHY * CosHP * SinHR;
y = SinHY * CosHP * CosHR - CosHY * SinHP * SinHR;
z = CosHY * CosHP * SinHR - SinHY * SinHP * CosHR;
w = CosHY * CosHP * CosHR + SinHY * SinHP * SinHR;
}
void Quaternion::ToEulerAngles(float* X, float* Y, float* Z) const
{
const float SingularityTest = (x * y) + (z * w);
if (SingularityTest > 0.4999995f)
{
*Y = 2.0f * std::atan2(x, w);
*Z = Math::HALF_PI;
*X = 0.0f;
}
else if (SingularityTest < -0.4999995f)
{
*Y = -2.0f * std::atan2(x, w);
*Z = -Math::HALF_PI;
*X = 0.0f;
}
else
{
const float zz = z * z;
*Y = std::atan2(2.0f * ((y * w) - (x * z)), 1.0f - 2.0f * ((y * y) + zz));
*Z = std::asin(2.0f * SingularityTest);
*X = std::atan2(2.0f * ((x * w) - (y * z)), 1.0f - 2.0f * ((x * x) + zz));
}
}
It's not just a little imprecision but really the result is noticeable because the difference is large when you create the quaternion after the conversion and see the result on a mesh.
Is it normal and no way to have better result exists?
Thanks