I have published a first article about how to build a quaternion from two arbitrary direction vectors that will transform one of the directions into the other. That article was deliberately omitting the special case when the two vectors were facing away from each other, which required special treatment. So I wrote a second article explaining how to quickly pick an orthogonal vector.

Combining the results from the two articles should be straightforward. Here is the resulting, final function:

/* Build a unit quaternion representing the rotation * from u to v. The input vectors need not be normalised. */ quat quat::fromtwovectors(vec3 u, vec3 v) { float norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); float real_part = norm_u_norm_v + dot(u, v); vec3 w; if (real_part < 1.e-6f * norm_u_norm_v) { /* If u and v are exactly opposite, rotate 180 degrees * around an arbitrary orthogonal axis. Axis normalisation * can happen later, when we normalise the quaternion. */ real_part = 0.0f; w = abs(u.x) > abs(u.z) ? vec3(-u.y, u.x, 0.f) : vec3(0.f, -u.z, u.y); } else { /* Otherwise, build quaternion the standard way. */ w = cross(u, v); } return normalize(quat(real_part, w.x, w.y, w.z)); }

If you know you are exclusively dealing with unit vectors, you can replace all occurrences of `norm_u_norm_v` with the value `1.0f` in order to avoid a useless square root.