Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: Clamping the dot product in a Slerp for Quaternion

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2013
    Posts
    28

    Clamping the dot product in a Slerp for Quaternion

    I'm looking at two different source for the Slerp method of interpolation between two quaternions. They are pretty similar except for one notable difference: one clamps the dot product between 0 and 1, and the other between -1 and 1. Here is one of them:

    Code :
    glm::fquat Slerp(const glm::fquat &v0, const glm::fquat &v1, float alpha)
    {
        float dot = glm::dot(v0, v1);
     
        const float DOT_THRESHOLD = 0.9995f;
        if (dot > DOT_THRESHOLD)
            return Lerp(v0, v1, alpha);
     
        glm::clamp(dot, -1.0f, 1.0f); //<-- The line in question
        float theta_0 = acosf(dot);
        float theta = theta_0*alpha;
     
        glm::fquat v2 = v1 - v0*dot;
        v2 = glm::normalize(v2);
     
        return v0*cos(theta) + v2*sin(theta);
    }

    Here is the other:

    Code :
    template <typename T>
    inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const
    {
        const T epsilon = 0.0005f;
        T dot = Dot(v1);
     
        if (dot > 1 - epsilon) {
            QuaternionT<T> result = v1 + (*this - v1).Scaled(t);
            result.Normalize();
            return result;
        }
     
        if (dot < 0) //<-The lower clamp
            dot = 0;
     
        if (dot > 1)
            dot = 1;
     
        T theta0 = std::acos(dot);
        T theta = theta0 * t;
     
        QuaternionT<T> v2 = (v1 - Scaled(dot));
        v2.Normalize();
     
        QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta));
        q.Normalize();
        return q;
    }

    I think it is worth noting also the the Lerp algorithm in the second one doesn't seem right for all cases?

    I just want some feedback on these differences and if they really matter at all.

  2. #2
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    490
    Clamping the dot product to -1..+1 should be a no-op if the quaternions are normalised, but it may provide robustness e.g. in the case of rounding error (passing a value outside that range to acos() will result in a domain error).
    Clamping to zero seems wrong; it effectively clamps the angle to 180 degrees (by clamping the half angle to 90 degrees). In the absence of additional steps, a negative dot product will result in the interpolation taking the long way around (i.e. rotating through an angle greater than 180 degrees). Typically, if the dot product is negative, you would negate one of the two quaternions (and their product) so that the interpolation takes the shorter path.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •