Quick answer: q and -q represent the same rotation but slerp between them differently. If dot(a, b) < 0, negate one before slerp to take the shortest arc.
A turret should rotate the short way to face a target. With glm::slerp it sometimes spins almost all the way around — the quaternions are on opposite hemispheres.
The Double-Cover Problem
Every rotation has two quaternion representations: q and -q. They’re the same orientation, but slerp interpolates along the arc between the literal 4D vectors — and one of those arcs is the long way around.
Fix: Check the Dot Product
glm::quat shortestSlerp(glm::quat a, glm::quat b, float t)
{
if (glm::dot(a, b) < 0.0f)
b = -b; // flip to the same hemisphere
return glm::slerp(a, b, t);
}
A negative dot product means the quaternions point to opposite hemispheres. Negating one puts them on the same side — slerp then takes the short arc.
Note on glm Versions
Some glm versions’ slerp already handle this; some don’t. Don’t rely on it — the explicit dot-check wrapper is correct everywhere and costs nothing.
Normalize Inputs
Slerp assumes unit quaternions. Accumulated float error can drift them — glm::normalize the operands (and the result) if they’ve been through many operations.
Verifying
The turret always rotates the short way to its target, including across the ±180° boundary. No surprise full spins.
“q and -q are the same rotation. Flip to the same hemisphere before slerp for the shortest arc.”
Wrap this once as your project’s only slerp — the raw glm::slerp is a footgun you don’t want call sites reaching for.