message: Compute the rotation between two vectors
diff: @@ -126,6 +126,44 @@ public:
  constexpr static TQuaternion MATH_PURE fromAxisAngle(const TVec3<A>& axis, B angle) {
  return TQuaternion(std::sin(angle * 0.5) * normalize(axis), std::cos(angle * 0.5));
  }
  +
  + // constructs a quaternion from orig to dest.
  + // it returns the shortest arc and `from` and `to` must be normalized.
  + template<typename A, typename B, typename = enable_if_arithmetic_t<A, B>>
  + constexpr static TQuaternion MATH_PURE fromDirectedRotation(const TVec3<A>& from, const TVec3<B>& to) {
  + // see the implementation of glm/gtx/quaternion.hpp
  + T cosTheta = dot(from, to);
  + TVec3<T> rotationAxis;
  +
  + if (cosTheta >= T(1) - std::numeric_limits<T>::epsilon()) {
  + // orig and dest point in the same direction
  + return TQuaternion(1, 0, 0, 0);
  + }
  +
  + if (cosTheta < T(-1) + std::numeric_limits<T>::epsilon()) {
  + // special case when vectors in opposite directions :
  + // there is no "ideal" rotation axis
  + // So guess one; any will do as long as it's perpendicular to start
  + // This implementation favors a rotation around the Up axis (Y),
  + // since it's often what you want to do.
  + rotationAxis = cross(TVec3<T>(0, 0, 1), from);
  +
  + if (length2(rotationAxis) < std::numeric_limits<T>::epsilon()) {
  + // bad luck, they were parallel, try again!
  + rotationAxis = cross(TVec3<T>(1, 0, 0), from);
  + }
  +
  + rotationAxis = normalize(rotationAxis);
  + return fromAxisAngle(rotationAxis, F_PI);
  + }
  +
  + // implementation from Stan Melax's Game Programming Gems 1 article
  + rotationAxis = cross(from, to);
  +
  + const T s = std::sqrt((T(1) + cosTheta) * T(2));
  + return TQuaternion(s * T(0.5),
  + rotationAxis.x / s, rotationAxis.y / s, rotationAxis.z / s);
  + }
  };
  } // namespace details
  