1
\$\begingroup\$

I have a unit vector representing the direction I want to "look" and a unit vector for up. They are orthogonal. How can I get the quaternion that represents that orientation from those two vectors?

\$\endgroup\$
1
\$\begingroup\$

If you have a method of getting the quaternion of the rotation matrix then just get the lookat matrix and use that method.

otherwise you can get the rotation R1 from (0,0,-1) to the look vector, This results in a lookat transformation with an arbitrary up.

then find that arbitrary up with R1*(0,1,0) and then find the rotation between that and the resulting up with the look vector as the rotation axis.

Concatenate the results and that will be the final transformation.

\$\endgroup\$
0
\$\begingroup\$

Something like this should do it:

Quaternion CreateFromLookAxis(Vector3 forward, Vector3 up)
{
    var m2 = Vector3.Normalize(forward); // Just in case.
    var m0 = Vector3.Normalize(Vector3.Cross(up, m2));
    var m1 = Vector3.Cross(m2, m0);

    var r0 = m0.x + m1.y + m2.z;
    var result = new Quaternion();
    if (r0 > 0f)
    {
        var r1 = (float)Math.Sqrt(r0 + 1f);
        result.w = r1 * 0.5f;
        r1 = 0.5f / r1;
        result.x = (m1.z - m2.y) * r1;
        result.y = (m2.x - m0.z) * r1;
        result.z = (m0.y - m1.x) * r1;
        return result;
    }
    // else
    if ((m0.x >= m1.y) && (m0.x >= m2.z))
    {
        var r1 = (float)Math.Sqrt(((1f + m0.x) - m1.y) - m2.z);
        var r2 = 0.5f / r1;
        result.x = 0.5f * r1;
        result.y = (m0.y + m1.x) * r2;
        result.z = (m0.z + m2.x) * r2;
        result.w = (m1.z - m2.y) * r2;
        return result;
    }
    // else
    if (m1.y > m2.z)
    {
        var r1 = (float)Math.Sqrt(((1f + m1.y) - m0.x) - m2.z);
        var r2 = 0.5f / r1;
        result.x = (m1.x + m0.y) * r2;
        result.y = 0.5f * r1;
        result.z = (m2.y + m1.z) * r2;
        result.w = (m2.x - m0.z) * r2;
        return result;
    }
    // else
    {
        var r1 = (float)Math.Sqrt(((1f + m2.z) - m0.x) - m1.y);
        var r2 = 0.5f / r1;
        result.x = (m2.x + m0.z) * r2;
        result.y = (m2.y + m1.z) * r2;
        result.z = 0.5f * r1;
        result.w = (m0.y - m1.x) * r2;
        return result;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.