0
\$\begingroup\$

Suppose that I have an orientation Quaternion Q, I can compute its forward vector from V = Q * Vector3.forward easily.

Inversely, suppose that I have its forward vector V, how do I compute Q?

I know that is not possible, please tell me what's needed beside V, in order to compute Q.

Motivation behind the problem: I have a forward direction of a game object, I want to find out its up direction and its right direction. I can find out all these 3 directions if I have the orientation Quaternion.

\$\endgroup\$
  • \$\begingroup\$ Do you know the method Quaternion.LookRotation ? \$\endgroup\$ – DMGregory Oct 13 '18 at 20:38
  • \$\begingroup\$ yes. i know but it's not creating the same rotation as Q \$\endgroup\$ – off99555 Oct 13 '18 at 21:53
  • \$\begingroup\$ You passed both the forward and up parameters? \$\endgroup\$ – DMGregory Oct 13 '18 at 21:54
  • \$\begingroup\$ I don't have the up vector. \$\endgroup\$ – off99555 Oct 13 '18 at 23:53
  • \$\begingroup\$ Maybe you should tell us what you do have then. So far all we know is that you have a forward vector, but you already know that's insufficient on its own. \$\endgroup\$ – DMGregory Oct 14 '18 at 0:01
0
\$\begingroup\$

You can calculate a right and up directly from the forward. however it is not going to be a unique up and right because there is an extra degree of freedom you need to consider.

Code from Building an Orthonormal Basis, Revisited

void branchlessONB(const Vec3f &n, Vec3f &b1, Vec3f &b2){
    float sign = copysignf(1.0f, n.z);
    const float a = -1.0f / (sign + n.z);
    const float b = n.x * n.y * a; 
    b1 = Vec3f(1.0f + sign * n.x * n.x * a, sign * b, -sign * n.x);
    b2 = Vec3f(b, sign + n.y * n.y * a, -n.y);
}
\$\endgroup\$
1
\$\begingroup\$

Unless your forward vector is directed exactly up, you can easily find the right and up vectors in Unity:

Vector3 right = Vector3.Cross(Vector3.up, forward);
Vector3 up = Vector3.Cross(forward, right);

Otherwise, right and up will be zero and you will be experiencing gimbal lock, a problem that has plenty of different solutions depending on your case. Choosing an arbitrary right vector may be a solution. The final code could be:

Vector3 right = Vector3.Angle(Vector3.up, forward) < 0.001)
              ? Vector3.right : Vector3.Cross(Vector3.up, forward);
Vector3 up = Vector3.Cross(forward, right);
\$\endgroup\$
  • \$\begingroup\$ Similar to gimbal lock, the method you propose has a singularity when looking straight up or straight down, but it's not caused by gimbal lock in this case because we're not rotating on gimbals (dependent rotation axes). The symptoms are also different: in gimbal lock, we'll still have a valid orientation but we'll lose a degree of freedom, left with only two axes. The singularity in this construction won't cause a loss of a degree of freedom, it will cause either an invalid/underspecified orientation, or once dealt with, a discontinuous change in orientation for a continuous change in inputs. \$\endgroup\$ – DMGregory Oct 15 '18 at 12:39
  • \$\begingroup\$ I want right and up vector that is relative to the object entirely. So the right vector needs to not be parallel to the ground like this. I think your code gives right vector that is parallel to the ground. \$\endgroup\$ – off99555 Oct 15 '18 at 19:44
  • \$\begingroup\$ @off99555 then there is one piece of missing information: the roll value, otherwise many values for the right vector can be good, especially the one parallel to the ground. \$\endgroup\$ – sam hocevar Oct 16 '18 at 7:18
0
\$\begingroup\$

In order to convert a direction-vector to a quaternion, use Quaternion.LookRotation(v). The (optional) second argument isn't the up-vector of the object. It's the up-vector of the world.

\$\endgroup\$
  • \$\begingroup\$ The second argument is an approximate up vector you want the resulting rotation to have. (ie. you want it to get as close as possible to resultQuaternion * (0, 1, 0) == secondArgument given the forward vector provided in the first argument} It defaults to the world up vector if not specified, so if we're specifying it, then it's generally because we don't want the world up vector. \$\endgroup\$ – DMGregory Oct 15 '18 at 12:30

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.