Reputation: 13
I am trying to implement Quaternion to my engine for entity transform->rotation like from Unity engine.
And i need to convert from quaternion to Euler angles and back but i got a strange wrong result.
I tried this in C++ with GLM:
Vector3 QuaternionToEulerAngles(Quaternion quat)
{
glm::vec3 euler = glm::degrees(glm::eulerAngles(glm::quat(quat.X, quat.Y, quat.Z, quat.W)));
return Vector3(euler.x, euler.y, euler.z);
}
Quaternion EulerAnglesToQuaternion(Vector3 vec)
{
glm::quat xQuat = glm::angleAxis(glm::radians(vec.X), glm::vec3{ 1.f, 0.f, 0.f });
glm::quat yQuat = glm::angleAxis(glm::radians(vec.Y), glm::vec3{ 0.f, 1.f, 0.f });
glm::quat zQuat = glm::angleAxis(glm::radians(vec.Z), glm::vec3{ 0.f, 0.f, 1.f });
glm::quat finalOrientation = xQuat * yQuat * zQuat;
return Quaternion(finalOrientation.x, finalOrientation.y, finalOrientation.z, finalOrientation.w);
}
And i tried this in C#:
public Quaternion ToQuaternion()
{
float xOver2 = X * Mathf.Deg2Rad * 0.5f;
float yOver2 = Y * Mathf.Deg2Rad * 0.5f;
float zOver2 = Z * Mathf.Deg2Rad * 0.5f;
float sinXOver2 = Mathf.Sin(xOver2);
float cosXOver2 = Mathf.Cos(xOver2);
float sinYOver2 = Mathf.Sin(yOver2);
float cosYOver2 = Mathf.Cos(yOver2);
float sinZOver2 = Mathf.Sin(zOver2);
float cosZOver2 = Mathf.Cos(zOver2);
Quaternion result = new();
result.X = cosYOver2 * sinXOver2 * cosZOver2 + sinYOver2 * cosXOver2 * sinZOver2;
result.Y = sinYOver2 * cosXOver2 * cosZOver2 - cosYOver2 * sinXOver2 * sinZOver2;
result.Z = cosYOver2 * cosXOver2 * sinZOver2 - sinYOver2 * sinXOver2 * cosZOver2;
result.W = cosYOver2 * cosXOver2 * cosZOver2 + sinYOver2 * sinXOver2 * sinZOver2;
return result;
}
public Vector3 ToEulerAngles()
{
float sqw = W * W;
float sqx = X * X;
float sqy = Y * Y;
float sqz = Z * Z;
float unit = sqx + sqy + sqz + sqw;
float test = X * W - Y * Z;
Vector3 v;
if (test > 0.4995f * unit)
{ // singularity at north pole
v.Y = 2f * Mathf.Atan2(Y, X);
v.X = Mathf.PI / 2;
v.Z = 0;
return NormalizeAngles(v * Mathf.Rad2Deg);
}
if (test < -0.4995f * unit)
{ // singularity at south pole
v.Y = -2f * Mathf.Atan2(Y, X);
v.X = -Mathf.PI / 2;
v.Z = 0;
return NormalizeAngles(v * Mathf.Rad2Deg);
}
Quaternion q = new(W, Z, X, Y);
v.Y = Mathf.Atan2(2f * q.X * q.W + 2f * q.Y * q.Z, 1 - 2f * (q.Z * q.Z + q.W * q.W));
v.X = Mathf.Asin(2f * (q.X * q.Z - q.W * q.Y));
v.Z = Mathf.Atan2(2f * q.X * q.Y + 2f * q.Z * q.W, 1 - 2f * (q.Y * q.Y + q.Z * q.Z));
return NormalizeAngles(v * Mathf.Rad2Deg);
}
And i also tried the code from wiki https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
Upvotes: 0
Views: 73