diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 897e077cb..760f87bc8 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -53,8 +53,9 @@ namespace Implementation { template constexpr static T pow(T) { return T(1); } }; - template struct IsBoolVector: std::false_type {}; - template struct IsBoolVector>: std::true_type {}; + template struct IsBoolVectorOrScalar: std::false_type {}; + template<> struct IsBoolVectorOrScalar: std::true_type {}; + template struct IsBoolVectorOrScalar>: std::true_type {}; template struct IsVectorOrScalar: std::is_arithmetic::type {}; template class Derived, class T> struct IsVectorOrScalar>: std::true_type {}; @@ -562,7 +563,7 @@ See @ref select() for constant interpolation using the same API. */ template inline #ifndef DOXYGEN_GENERATING_OUTPUT - typename std::enable_if::value && !Implementation::IsBoolVector::value, T>::type + typename std::enable_if::value && !Implementation::IsBoolVectorOrScalar::value, T>::type #else T #endif @@ -570,6 +571,13 @@ lerp(const T& a, const T& b, U t) { return Implementation::lerp(a, b, t); } +/** @overload +@m_keyword{mix(),GLSL mix(),} +*/ +template inline T lerp(const T& a, const T& b, bool t) { + return t ? b : a; +} + /** @overload Similar to the above, but instead of multiplication and addition it just does component-wise selection from either @p a or @p b based on values in @p t. diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index 5653664fc..fb51bb7d5 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -27,7 +27,7 @@ #include #include "Magnum/Math/Functions.h" -#include "Magnum/Math/Vector3.h" +#include "Magnum/Math/Vector4.h" namespace Magnum { namespace Math { namespace Test { @@ -59,6 +59,7 @@ struct FunctionsTest: Corrade::TestSuite::Tester { void lerpBool(); void lerpInverted(); void select(); + void selectBool(); void fma(); void logIntegral(); @@ -77,6 +78,7 @@ typedef Math::Deg Deg; typedef Math::Rad Rad; typedef Math::Vector2 Vector2; typedef Math::Vector3 Vector3; +typedef Math::Vector4 Vector4; typedef Math::Vector3 Vector3ub; typedef Math::Vector3 Vector3b; typedef Math::Vector3 Vector3i; @@ -107,6 +109,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::lerpBool, &FunctionsTest::lerpInverted, &FunctionsTest::select, + &FunctionsTest::selectBool, &FunctionsTest::fma, &FunctionsTest::logIntegral, @@ -292,6 +295,11 @@ void FunctionsTest::lerp() { } void FunctionsTest::lerpBool() { + /* Scalar interpolation phase */ + CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, true), (Vector3i{5, 6, 7})); + CORRADE_COMPARE(Math::lerp(BoolVector<3>{5}, BoolVector<3>{true}, false), BoolVector<3>{5}); + + /* Vector interpolation phase */ CORRADE_COMPARE(Math::lerp(Vector3i{1, 2, 3}, Vector3i{5, 6, 7}, BoolVector<3>(5)), (Vector3i{5, 2, 7})); CORRADE_COMPARE(Math::lerp(BoolVector<3>{false}, BoolVector<3>{true}, BoolVector<3>(5)), BoolVector<3>{5}); } @@ -323,6 +331,12 @@ void FunctionsTest::select() { CORRADE_COMPARE(Math::select(a, b, Vector3(0.25f, 1.5f, 1.0f)), Vector3(-1.0f, -2.0f, 11.0f)); } +void FunctionsTest::selectBool() { + CORRADE_COMPARE(Math::select(true, false, 0.5f), true); + CORRADE_COMPARE(Math::select(Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, 1.1f), Math::BoolVector<4>{0x5}); + CORRADE_COMPARE(Math::select(Math::BoolVector<4>{0xa}, Math::BoolVector<4>{0x5}, Vector4{1.1f, -1.0f, 1.3f, 0.5f}), Math::BoolVector<4>{0xf}); +} + 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),