diff --git a/libs/common/include/helpers/mathFuncs.h b/libs/common/include/helpers/mathFuncs.h index 20929602b..ddd697bcc 100644 --- a/libs/common/include/helpers/mathFuncs.h +++ b/libs/common/include/helpers/mathFuncs.h @@ -50,7 +50,7 @@ constexpr U clamp(T val, U min, U max) noexcept // Here all values are positive or have the same signedness return static_cast(clamp(static_cast(val), static_cast(min), static_cast(max))); } -// Linear interpolation between [startVal, endVal]. Difference between those 2 and elapsedTime should be smallish +/// Linear interpolation between [startVal, endVal]. Difference between those 2 and elapsedTime should be smallish template constexpr T interpolate(const T startVal, const T endVal, const U elapsedTime, const V duration) noexcept { @@ -66,4 +66,17 @@ constexpr T interpolate(const T startVal, const T endVal, const U elapsedTime, c else // Special case for unsigned values return static_cast(startVal - ((startVal - endVal) * elapsedTime) / duration); } + +/// Linear interpolation, similar to C++20's std::lerp() +constexpr float lerp(const float startVal, const float endVal, const float ratio) noexcept +{ + return startVal + ratio * (endVal - startVal); +} + +/// Inverse function to lerp(): Returns the ratio of value in [startVal, endVal] +template +constexpr T inverseLerp(const T startVal, const T endVal, const T value) noexcept +{ + return (value - startVal) / (endVal - startVal); +} } // namespace helpers diff --git a/tests/common/testMathHelpers.cpp b/tests/common/testMathHelpers.cpp index 8462d6b6e..210793569 100644 --- a/tests/common/testMathHelpers.cpp +++ b/tests/common/testMathHelpers.cpp @@ -188,4 +188,26 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Interpolate, T, TimeTypes) } } +BOOST_AUTO_TEST_CASE(Lerp) +{ + const auto startVal = 5.0f; + const auto endVal = 10.0f; + BOOST_TEST(helpers::lerp(startVal, endVal, .0f) == startVal); + BOOST_TEST(helpers::lerp(startVal, endVal, 1.0f) == endVal); + BOOST_TEST(helpers::lerp(startVal, endVal, .5f) == 7.5f); + BOOST_TEST(helpers::lerp(startVal, endVal, 2.0f) == 15.0f); + BOOST_TEST(helpers::lerp(startVal, endVal, -.5f) == 2.5f); +} + +BOOST_AUTO_TEST_CASE(InverseLerp) +{ + const auto startVal = 5.0f; + const auto endVal = 10.0f; + BOOST_TEST(helpers::inverseLerp(startVal, endVal, startVal) == .0f); + BOOST_TEST(helpers::inverseLerp(startVal, endVal, endVal) == 1.0f); + BOOST_TEST(helpers::inverseLerp(startVal, endVal, 7.5f) == .5f); + BOOST_TEST(helpers::inverseLerp(startVal, endVal, 15.0f) == 2.0f); + BOOST_TEST(helpers::inverseLerp(startVal, endVal, 2.5f) == -.5f); +} + BOOST_AUTO_TEST_SUITE_END()