diff --git a/src/Math/Functions.h b/src/Math/Functions.h index 76bff57b4..b313780b0 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -153,6 +153,30 @@ template Vector clamp(const Vector& } #endif +/** +@brief Linear interpolation of two values +@param a First value +@param b Second value +@param t Interpolation phase (from range @f$ [0; 1] @f$) + +The interpolation for vectors is done as in following, similarly for scalars: @f[ + \boldsymbol v_{LERP} = (1 - t) \boldsymbol v_A + t \boldsymbol v_B +@f] +@see Quaternion::lerp() +@todo http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + (when SIMD is in place) +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline T lerp(const T& a, const T& b, U t); +#else +template inline T lerp(T a, T b, U t) { + return (U(1) - t)*a + t*b; +} +template inline Vector lerp(const Vector& a, const Vector& b, U t) { + return (U(1) - t)*a + t*b; +} +#endif + /** @brief Normalize integral value diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index 1615c4e41..1d513f8bc 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -72,6 +72,7 @@ template class Quaternion { * Expects that both quaternions are normalized. @f[ * q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|} * @f] + * @see slerp(), Math::lerp() */ inline static Quaternion lerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { CORRADE_ASSERT(MathTypeTraits::equals(normalizedA.dot(), T(1)) && MathTypeTraits::equals(normalizedB.dot(), T(1)), @@ -91,6 +92,7 @@ template class Quaternion { * ~~~~~~~~~~ * \theta = acos \left( \frac{q_A \cdot q_B}{|q_A| \cdot |q_B|} \right) * @f] + * @see lerp() */ inline static Quaternion slerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { CORRADE_ASSERT(MathTypeTraits::equals(normalizedA.dot(), T(1)) && MathTypeTraits::equals(normalizedB.dot(), T(1)), diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index dd88b08cc..049c9be67 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -28,6 +28,7 @@ class FunctionsTest: public Corrade::TestSuite::Tester { void max(); void abs(); void clamp(); + void lerp(); void normalizeUnsigned(); void normalizeSigned(); void denormalizeUnsigned(); @@ -50,6 +51,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::max, &FunctionsTest::abs, &FunctionsTest::clamp, + &FunctionsTest::lerp, &FunctionsTest::normalizeUnsigned, &FunctionsTest::normalizeSigned, &FunctionsTest::denormalizeUnsigned, @@ -85,6 +87,23 @@ void FunctionsTest::clamp() { CORRADE_COMPARE(Math::clamp(Vector3(0.5f, -1.6f, 9.5f), -1.0f, 5.0f), Vector3(0.5f, -1.0f, 5.0f)); } +void FunctionsTest::lerp() { + /* Floating-point / integral scalar */ + CORRADE_COMPARE(Math::lerp(2.0f, 5.0f, 0.5f), 3.5f); + CORRADE_COMPARE(Math::lerp(2, 5, 0.5f), 3); + + /* Floating-point vector */ + Vector3 a(-1.0f, 2.0f, 3.0f); + Vector3 b(3.0f, -2.0f, 11.0f); + CORRADE_COMPARE(Math::lerp(a, b, 0.25f), Vector3(0.0f, 1.0f, 5.0f)); + + /* Integer vector */ + typedef Math::Vector<3, std::int32_t> Vector3ub; + Vector3ub c(0, 128, 64); + Vector3ub d(16, 0, 32); + CORRADE_COMPARE(Math::lerp(c, d, 0.25f), Vector3ub(4, 96, 56)); +} + void FunctionsTest::normalizeUnsigned() { CORRADE_COMPARE((Math::normalize(0)), 0.0f); CORRADE_COMPARE((Math::normalize(255)), 1.0f); diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index d274b5af5..9035fdaeb 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -58,7 +58,6 @@ class VectorTest: public Corrade::TestSuite::Tester { void projected(); void projectedOntoNormalized(); void angle(); - void lerp(); void debug(); void configuration(); @@ -101,7 +100,6 @@ VectorTest::VectorTest() { &VectorTest::projected, &VectorTest::projectedOntoNormalized, &VectorTest::angle, - &VectorTest::lerp, &VectorTest::debug, &VectorTest::configuration); @@ -320,18 +318,6 @@ void VectorTest::angle() { rad(1.162514f)); } -void VectorTest::lerp() { - Vector3 a(-1.0f, 2.0f, 3.0f); - Vector3 b(3.0f, -2.0f, 11.0f); - - CORRADE_COMPARE(Vector3::lerp(a, b, 0.25f), Vector3(0.0f, 1.0f, 5.0f)); - - typedef Math::Vector<3, std::int32_t> Vector3ub; - Vector3ub c(0, 128, 64); - Vector3ub d(16, 0, 32); - CORRADE_COMPARE(Vector3ub::lerp(c, d, 0.25f), Vector3ub(4, 96, 56)); -} - void VectorTest::debug() { std::ostringstream o; Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 977ed935b..edc480ec2 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -90,22 +90,6 @@ template class Vector { return std::acos(dot(normalizedA, normalizedB)); } - /** - * @brief Linear interpolation of two vectors - * @param a First vector - * @param b Second vector - * @param t Interpolation phase (from range @f$ [0; 1] @f$) - * - * The interpolation is done as in following: @f[ - * \boldsymbol v_{LERP} = (1 - t) \boldsymbol v_A + t \boldsymbol v_B - * @f] - * @todo http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ - * (when SIMD is in place) - */ - template inline static Vector lerp(const Vector& a, const Vector& b, U t) { - return (U(1) - t)*a + t*b; - } - /** @brief Construct zero-filled vector */ inline constexpr /*implicit*/ Vector(): _data() {} @@ -587,9 +571,6 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit } \ inline constexpr static const Type& from(const T* data) { \ return *reinterpret_cast*>(data); \ - } \ - template inline static const Type lerp(const Math::Vector& a, const Math::Vector& b, U t) { \ - return Math::Vector::lerp(a, b, t); \ } \ \ inline Type& operator=(const Type& other) { \