diff --git a/src/util/Interpolation.hpp b/src/util/Interpolation.hpp index d0f62a00..757bb6f4 100644 --- a/src/util/Interpolation.hpp +++ b/src/util/Interpolation.hpp @@ -3,34 +3,41 @@ #include #include +const float INTERPOLATION_DURATION = 0.15f; // seconds + namespace util { template class VecInterpolation { bool enabled; glm::vec prevPos {std::numeric_limits::quiet_NaN()}; glm::vec nextPos {}; - T refreshInterval = 0.0; + mutable glm::vec interpolationStep {}; + glm::vec currentDuration {INTERPOLATION_DURATION}; T timer = 0.0; - T intervalUpdateFactor = 0.1; public: VecInterpolation(bool enabled) : enabled(enabled) {} void refresh(const glm::vec& position) { - auto current = getCurrent(); - prevPos = current; + prevPos = getCurrent(); nextPos = position; - refreshInterval = timer * intervalUpdateFactor + - refreshInterval * (1.0 - intervalUpdateFactor); - timer = 0.0; - + if constexpr (angular) { - for (int i = 0; i < N; i++) { - T diff = nextPos[i] - prevPos[i]; - if (glm::abs(diff) > 180.0f) { - nextPos[i] += (diff > 0.0f ? -360.0f : 360.0f); + for (glm::length_t i = 0; i < N; i++) { + const float shortestAngle = std::fmod((std::fmod((nextPos[i] - prevPos[i]), 360.0f) + 540.0f), 360.0f) - 180.0f; + if (std::abs(interpolationStep[i]) > 90.0f) { + currentDuration[i] = INTERPOLATION_DURATION * (1.0f - std::abs(shortestAngle) / 180.0f); + } else { + currentDuration[i] = INTERPOLATION_DURATION; + } + interpolationStep[i] = shortestAngle / currentDuration[i]; + if (glm::abs(nextPos[i]) > 180.0f) { + nextPos[i] += (nextPos[i] > 0.0f ? -360.0f : 360.0f); } } + } else { + interpolationStep = (nextPos - prevPos) / currentDuration.x; } + timer = 0.0; } void updateTimer(T delta) { @@ -38,15 +45,16 @@ namespace util { } glm::vec getCurrent() const { - if (refreshInterval < 0.001 || std::isnan(prevPos.x)) { - return nextPos; + glm::vec interpolated; + for (glm::length_t i = 0; i < N; i++) { + if (timer >= currentDuration[i] || std::isnan(prevPos[i])) { + interpolated[i] = nextPos[i]; + interpolationStep[i] = 0.0f; + } else { + interpolated[i] = prevPos[i] + interpolationStep[i] * timer; + } } - T t = timer / refreshInterval; - return nextPos * t + prevPos * (1.0f - t); - } - - T getRefreshInterval() const { - return refreshInterval; + return interpolated; } bool isEnabled() const {