go-gl / mathgl

A pure Go 3D math library.
BSD 3-Clause "New" or "Revised" License
554 stars 65 forks source link

Quaternion Slerp honors closest distance. #90

Closed nitrix closed 1 year ago

nitrix commented 1 year ago

Hello,

This is a fix to the quaternion spherical linear interpolation to make it choose the shortest linear path which is the intended behavior in graphical animations.

You'll find that my changes are in the same spirit as them. Added a test too.

// Make sure we take the shortest path in case dot product is negative.
if dot < 0.0 {
    q2 = q2.Scale(-1)
    dot = -dot
}

This is a very well known problem. Wikipedia documents it here in detail: https://en.wikipedia.org/wiki/Slerp#Quaternion_Slerp

However, because the covering is double (q and −q map to the same rotation), the rotation path may turn either the "short way" (less than 180°) or the "long way" (more than 180°). Long paths can be prevented by negating one end if the dot product, cos Ω, is negative, thus ensuring that −90° ≤ Ω ≤ 90°.

I ran into this corner case using mathgl, my fork will stay up until the changes can get upstream: https://github.com/nitrix/mathgl/tree/fix/quat-slerp-closest

Cheers, Alex.