diff --git a/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl index da415ab0..742fbde3 100644 --- a/glm/gtc/quaternion.inl +++ b/glm/gtc/quaternion.inl @@ -326,7 +326,7 @@ namespace quaternion{ q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); } - +/* // (x * sin(1 - a) * angle / sin(angle)) + (y * sin(a) * angle / sin(angle)) template GLM_FUNC_QUALIFIER detail::tquat mix @@ -406,6 +406,18 @@ namespace quaternion{ return normalize(beta * x + alpha * y); } +*/ + template + GLM_FUNC_QUALIFIER detail::tquat mix + ( + detail::tquat const & x, + detail::tquat const & y, + T const & a + ) + { + T angle = acos(dot(x, y)); + return (sin((1 - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } template GLM_FUNC_QUALIFIER detail::tquat conjugate diff --git a/glm/gtx/quaternion.hpp b/glm/gtx/quaternion.hpp index 3e76481d..dcc43e88 100644 --- a/glm/gtx/quaternion.hpp +++ b/glm/gtx/quaternion.hpp @@ -109,7 +109,7 @@ namespace glm detail::tquat const & q, detail::tvec4 const & v); - //! Returns the q rotation angle. + //! Returns the quaternion rotation angle. //! From GLM_GTX_quaternion extension. template valType angle( @@ -191,6 +191,22 @@ namespace glm detail::tquat toQuat( detail::tmat4x4 const & x){return gtc::quaternion::quat_cast(x);} + //! Quaternion interpolation using the rotation short path. + //! From GLM_GTX_quaternion extension. + template + detail::tquat shortMix( + detail::tquat const & x, + detail::tquat const & y, + T const & a); + + //! Quaternion normalized linear interpolation. + //! From GLM_GTX_quaternion extension. + template + detail::tquat fastMix( + detail::tquat const & x, + detail::tquat const & y, + T const & a); + ///@} }//namespace quaternion diff --git a/glm/gtx/quaternion.inl b/glm/gtx/quaternion.inl index 00a4f888..aaf07171 100644 --- a/glm/gtx/quaternion.inl +++ b/glm/gtx/quaternion.inl @@ -245,6 +245,59 @@ namespace quaternion return detail::tvec3(pitch(x), yaw(x), roll(x)); } + template + GLM_FUNC_QUALIFIER detail::tquat shortMix + ( + detail::tquat const & x, + detail::tquat const & y, + T const & a + ) + { + if(a <= typename detail::tquat::value_type(0)) return x; + if(a >= typename detail::tquat::value_type(1)) return y; + + float fCos = dot(x, y); + detail::tquat y2(y); //BUG!!! tquat y2; + if(fCos < typename detail::tquat::value_type(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + float k0, k1; + if(fCos > typename detail::tquat::value_type(0.9999)) + { + k0 = typename detail::tquat::value_type(1) - a; + k1 = typename detail::tquat::value_type(0) + a; //BUG!!! 1.0f + a; + } + else + { + typename detail::tquat::value_type fSin = sqrt(T(1) - fCos * fCos); + typename detail::tquat::value_type fAngle = atan(fSin, fCos); + typename detail::tquat::value_type fOneOverSin = T(1) / fSin; + k0 = sin((typename detail::tquat::value_type(1) - a) * fAngle) * fOneOverSin; + k1 = sin((typename detail::tquat::value_type(0) + a) * fAngle) * fOneOverSin; + } + + return detail::tquat( + k0 * x.w + k1 * y2.w, + k0 * x.x + k1 * y2.x, + k0 * x.y + k1 * y2.y, + k0 * x.z + k1 * y2.z); + } + + template + GLM_FUNC_QUALIFIER detail::tquat fastMix + ( + detail::tquat const & x, + detail::tquat const & y, + T const & a + ) + { + return glm::normalize(x * (1 - a) + (y * a)); + } + }//namespace quaternion }//namespace gtx }//namespace glm