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.