diff --git a/doc/changelog.dox b/doc/changelog.dox index d99fcc394..6040ea0ab 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -52,6 +52,8 @@ See also: @ref Math::Intersection::aabbCone(), @ref Math::Intersection::rangeCone() - Added @ref Math::Constants::piQuarter() +- Added a convenience function @ref Math::select() as a constant + interpolation counterpart to @ref Math::lerp() - Ability to convert @ref Math::BoolVector from and to external representation diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index a9b3bdf7a..6e70e1fdf 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -544,6 +544,8 @@ template Vector sqrtInverted(const Vector&, const Quaternion&, T) @m_keyword{mix(),GLSL mix(),} */ @@ -591,7 +593,7 @@ template inline BoolVector lerp(const BoolVector& Returns interpolation phase *t*: @f[ t = \frac{\boldsymbol{v_{LERP}} - \boldsymbol{v_A}}{\boldsymbol{v_B} - \boldsymbol{v_A}} @f] -@see @ref lerp() +@see @ref lerp(), @ref select() */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline T lerpInverted(const T& a, const T& b, const T& lerp); @@ -604,6 +606,25 @@ template inline Vector lerpInverted } #endif +/** +@brief Constant interpolation of two values +@param a First value +@param b Second value +@param t Interpolation phase + +A constant interpolation counterpart to @ref lerp(): @f[ + \boldsymbol{v}_i = \begin{cases} + \boldsymbol{v_A}_i, & t_i < 1 \\ + \boldsymbol{v_B}_i, & t_i \ge 1 + \end{cases} +@f] + +Equivalent to calling @cpp Math::lerp(a, b, t >= U(1)) @ce. +*/ +template constexpr T select(const T& a, const T& b, U t) { + return lerp(a, b, t >= U(1)); +} + /** @brief Fused multiply-add diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index d1e4a758b..5653664fc 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -58,6 +58,7 @@ struct FunctionsTest: Corrade::TestSuite::Tester { void lerp(); void lerpBool(); void lerpInverted(); + void select(); void fma(); void logIntegral(); @@ -105,6 +106,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::lerp, &FunctionsTest::lerpBool, &FunctionsTest::lerpInverted, + &FunctionsTest::select, &FunctionsTest::fma, &FunctionsTest::logIntegral, @@ -304,6 +306,23 @@ void FunctionsTest::lerpInverted() { CORRADE_COMPARE(Math::lerpInverted(a, b, Vector3(0.0f, 0.0f, 9.0f)), Vector3(0.25f, 0.5f, 0.75f)); } +void FunctionsTest::select() { + /* Floating-point / integral scalar */ + CORRADE_COMPARE(Math::select(2.0f, 5.0f, 0.5f), 2.0f); + CORRADE_COMPARE(Math::select(2.0f, 5.0f, 1.0f), 5.0f); + CORRADE_COMPARE(Math::select(2, 5, -0.5f), 2); + CORRADE_COMPARE(Math::select(2, 5, 1.1f), 5); + + /* Floating-point vector */ + Vector3 a(-1.0f, 2.0f, 3.0f); + Vector3 b(3.0f, -2.0f, 11.0f); + CORRADE_COMPARE(Math::select(a, b, -0.25f), Vector3(-1.0f, 2.0f, 3.0f)); + CORRADE_COMPARE(Math::select(a, b, 5.5f), Vector3(3.0f, -2.0f, 11.0f)); + + /* Vector as interpolation phase */ + CORRADE_COMPARE(Math::select(a, b, Vector3(0.25f, 1.5f, 1.0f)), Vector3(-1.0f, -2.0f, 11.0f)); +} + void FunctionsTest::fma() { CORRADE_COMPARE(Math::fma(2.0f, 3.0f, 0.75f), 6.75f); CORRADE_COMPARE(Math::fma(Vector3( 2.0f, 1.5f, 0.5f),