2
\$\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\$

2 Answers 2

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .