diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index 46f4fe0a..a06d6bc9 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -939,6 +939,10 @@ template struct Quat static Quat rotate(T degrees, T x, T y, T z); static Quat rotate(T degrees, Vec3 const &v); + /* Create a unit quaternion representing a rotation between two vectors. + * Input vectors need not be normalised. */ + static Quat rotate(Vec3 const &src, Vec3 const &dst); + /* Convert from Euler angles. The axes in fromeuler_xyx are * x, then y', then x", ie. the axes are attached to the model. * If you want to rotate around static axes, just reverse the order diff --git a/src/math/vector.cpp b/src/math/vector.cpp index 84d5f804..59c9de26 100644 --- a/src/math/vector.cpp +++ b/src/math/vector.cpp @@ -501,6 +501,14 @@ template<> quat quat::rotate(float degrees, float x, float y, float z) return quat::rotate(degrees, vec3(x, y, z)); } +template<> quat quat::rotate(vec3 const &src, vec3 const &dst) +{ + vec3 v = cross(src, dst); + float d = dot(src, dst) + lol::sqrt(sqlength(src) * sqlength(dst)); + + return normalize(quat(d, v.x, v.y, v.z)); +} + template<> quat slerp(quat const &qa, quat const &qb, float f) { float const magnitude = lol::sqrt(sqlength(qa) * sqlength(qb));