oscar7070
oscar7070

Reputation: 13

Quaternion to eulerAngles and back

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

Answers (0)

Related Questions