- Home /
When does a Quaternion become invalid?
So my code suddenly threw the following error in the OnDrawGizmos() method Quaternion To Matrix conversion failed because input Quaternion is invalid {0.000000, 0.819208, 0.000000, 0.573472} l=0.999972
caused by Matrix4x4.TRS
. I narrowed the problem to the small test case by manually typing in the Quaternion values:
void Start () {
Quaternion quat = new Quaternion(0, 0.8192084f, 0, 0.5734719f);
Debug.Log("old Quat: " + quat.eulerAngles);
Vector3 euler = quat.eulerAngles;
Quaternion quat2 = Quaternion.Euler(euler);
Debug.Log("new Quat " + quat2.eulerAngles);
Vector3 pos = Vector3.right;
Vector3 scale = Vector3.one;
Matrix4x4 mat2 = Matrix4x4.TRS(pos, quat2, scale);
Matrix4x4 mat1 = Matrix4x4.TRS(pos, quat, scale);
}
Now, what's interesting: The last line throws the error mentioned above, the line second to last doesn't !!! So apparently there is some rounding going on when converting the Quaternion to Euler Angles and back to Quaternion. Still I'd love to have some explanation when a Quaternion is valid and when not?
Answer by Bunny83 · Mar 05, 2017 at 12:46 AM
Sure, your first quaternion isn't properly normalized. It has a length of "0.999971882048", though since float doesn't have that many digits it's rounded to "0.9999862". printing the eulerangles makes not much sense as they are calculated from the quaternion. If you want to compare the values, use
Debug.Log("old Quat: " + quat.ToString("F10"));
This will print the quaternion values with 10 decimal places. The result is:
old Quat: (0.0000000000, 0.8192084000, 0.0000000000, 0.5734719000)
new Quat: (0.0000000000, 0.8192197000, 0.0000000000, 0.5734798000)
The new quaternion has a length of about "0.9999909369577". Represented as a float will round to "1.0"
edit
If you want to properly normalize your quaternion, you can use this extension method:
public static class QuaternionExt
{
public static Quaternion GetNormalized(this Quaternion q)
{
float f = 1f / Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
return new Quaternion(q.x*f, q.y*f, q.z*f, q.w*f);
}
}
With that class somewhere in your project you can simply do
quat = quat.GetNormalized();
Running your test with the normalized quaternion doesn't create the error and both (quat and quat2) have the same values.
Your answer
Follow this Question
Related Questions
How to smoothly align an object to a surface, but only partially 2 Answers
Need help with Quaternions - Making a VR Combination Lock 1 Answer
Transform.Rotate producing unexpected results when being used after setting localEulerAngles 0 Answers
How is the rotation of a Transform converted into a Vector3 in the inspector ? 2 Answers