Created
May 9, 2019 08:39
-
-
Save JimmyCushnie/b4dddecdf391c1fc94ebc7df0c7072da to your computer and use it in GitHub Desktop.
Convert Euler angles to quaternions and quaternions to Euler angles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Vector3 QuaternionToEuler(Quaternion q) | |
{ | |
Vector3 euler; | |
// if the input quaternion is normalized, this is exactly one. Otherwise, this acts as a correction factor for the quaternion's not-normalizedness | |
float unit = (q.x * q.x) + (q.y * q.y) + (q.z * q.z) + (q.w * q.w); | |
// this will have a magnitude of 0.5 or greater if and only if this is a singularity case | |
float test = q.x * q.w - q.y * q.z; | |
if (test > 0.4995f * unit) // singularity at north pole | |
{ | |
euler.x = Mathf.PI / 2; | |
euler.y = 2f * Mathf.Atan2(q.y, q.x); | |
euler.z = 0; | |
} | |
else if (test < -0.4995f * unit) // singularity at south pole | |
{ | |
euler.x = -Mathf.PI / 2; | |
euler.y = -2f * Mathf.Atan2(q.y, q.x); | |
euler.z = 0; | |
} | |
else // no singularity - this is the majority of cases | |
{ | |
euler.x = Mathf.Asin(2f * (q.w * q.x - q.y * q.z)); | |
euler.y = Mathf.Atan2(2f * q.w * q.y + 2f * q.z * q.x, 1 - 2f * (q.x * q.x + q.y * q.y)); // I don't even fucking know, man. Fuck you quaternions. | |
euler.z = Mathf.Atan2(2f * q.w * q.z + 2f * q.x * q.y, 1 - 2f * (q.z * q.z + q.x * q.x)); | |
} | |
// all the math so far has been done in radians. Before returning, we convert to degrees... | |
euler *= Mathf.Rad2Deg; | |
//...and then ensure the degree values are between 0 and 360 | |
euler.x = euler.x.CapRange(360); | |
euler.y = euler.y.CapRange(360); | |
euler.z = euler.z.CapRange(360); | |
return euler; | |
} | |
Quaternion EulerToQuaternion(Vector3 euler) | |
{ | |
float xOver2 = euler.x * Mathf.Deg2Rad * 0.5f; | |
float yOver2 = euler.y * Mathf.Deg2Rad * 0.5f; | |
float zOver2 = euler.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; | |
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment