|
|
|
@ -153,6 +153,15 @@ namespace glm |
|
|
|
|
return -sqrt(w); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
GLM_FUNC_QUALIFIER T length2 |
|
|
|
|
( |
|
|
|
|
detail::tquat<T> const & q |
|
|
|
|
) |
|
|
|
|
{ |
|
|
|
|
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
GLM_FUNC_QUALIFIER detail::tquat<T> shortMix |
|
|
|
|
( |
|
|
|
@ -205,4 +214,43 @@ namespace glm |
|
|
|
|
{ |
|
|
|
|
return glm::normalize(x * (T(1) - a) + (y * a)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
GLM_FUNC_QUALIFIER detail::tquat<T> rotation |
|
|
|
|
( |
|
|
|
|
detail::tvec3<T> const & orig, |
|
|
|
|
detail::tvec3<T> const & dest |
|
|
|
|
) |
|
|
|
|
{ |
|
|
|
|
T cosTheta = dot(orig, dest); |
|
|
|
|
detail::tvec3<T> rotationAxis; |
|
|
|
|
|
|
|
|
|
if(cosTheta < T(-1) + epsilon<T>()) |
|
|
|
|
{ |
|
|
|
|
// 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(detail::tvec3<T>(0, 0, 1), orig); |
|
|
|
|
if(length2(rotationAxis) < epsilon<T>()) // bad luck, they were parallel, try again! |
|
|
|
|
rotationAxis = cross(detail::tvec3<T>(1, 0, 0), orig); |
|
|
|
|
|
|
|
|
|
rotationAxis = normalize(rotationAxis); |
|
|
|
|
return angleAxis(pi<T>(), rotationAxis); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Implementation from Stan Melax's Game Programming Gems 1 article |
|
|
|
|
rotationAxis = cross(orig, dest); |
|
|
|
|
|
|
|
|
|
T s = sqrt((T(1) + cosTheta) * T(2)); |
|
|
|
|
T invs = T(1) / s; |
|
|
|
|
|
|
|
|
|
return detail::tquat<T>( |
|
|
|
|
s * T(0.5f), |
|
|
|
|
rotationAxis.x * invs, |
|
|
|
|
rotationAxis.y * invs, |
|
|
|
|
rotationAxis.z * invs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}//namespace glm |
|
|
|
|