Browse Source

Math: moved lerp() from Vector to Functions.h.

It does nothing special for vectors (unlike e.g. quaternion LERP) and
scalar overload is useful too.
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
0144c38a54
  1. 24
      src/Math/Functions.h
  2. 2
      src/Math/Quaternion.h
  3. 19
      src/Math/Test/FunctionsTest.cpp
  4. 14
      src/Math/Test/VectorTest.cpp
  5. 19
      src/Math/Vector.h

24
src/Math/Functions.h

@ -153,6 +153,30 @@ template<std::size_t size, class T> Vector<size, T> clamp(const Vector<size, T>&
} }
#endif #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<class T, class U> inline T lerp(const T& a, const T& b, U t);
#else
template<class T, class U> inline T lerp(T a, T b, U t) {
return (U(1) - t)*a + t*b;
}
template<std::size_t size, class T, class U> inline Vector<size, T> lerp(const Vector<size, T>& a, const Vector<size, T>& b, U t) {
return (U(1) - t)*a + t*b;
}
#endif
/** /**
@brief Normalize integral value @brief Normalize integral value

2
src/Math/Quaternion.h

@ -72,6 +72,7 @@ template<class T> class Quaternion {
* Expects that both quaternions are normalized. @f[ * Expects that both quaternions are normalized. @f[
* q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|} * q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|}
* @f] * @f]
* @see slerp(), Math::lerp()
*/ */
inline static Quaternion<T> lerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t) { inline static Quaternion<T> lerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)),
@ -91,6 +92,7 @@ template<class T> class Quaternion {
* ~~~~~~~~~~ * ~~~~~~~~~~
* \theta = acos \left( \frac{q_A \cdot q_B}{|q_A| \cdot |q_B|} \right) * \theta = acos \left( \frac{q_A \cdot q_B}{|q_A| \cdot |q_B|} \right)
* @f] * @f]
* @see lerp()
*/ */
inline static Quaternion<T> slerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t) { inline static Quaternion<T> slerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)),

19
src/Math/Test/FunctionsTest.cpp

@ -28,6 +28,7 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
void max(); void max();
void abs(); void abs();
void clamp(); void clamp();
void lerp();
void normalizeUnsigned(); void normalizeUnsigned();
void normalizeSigned(); void normalizeSigned();
void denormalizeUnsigned(); void denormalizeUnsigned();
@ -50,6 +51,7 @@ FunctionsTest::FunctionsTest() {
&FunctionsTest::max, &FunctionsTest::max,
&FunctionsTest::abs, &FunctionsTest::abs,
&FunctionsTest::clamp, &FunctionsTest::clamp,
&FunctionsTest::lerp,
&FunctionsTest::normalizeUnsigned, &FunctionsTest::normalizeUnsigned,
&FunctionsTest::normalizeSigned, &FunctionsTest::normalizeSigned,
&FunctionsTest::denormalizeUnsigned, &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)); 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() { void FunctionsTest::normalizeUnsigned() {
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f);

14
src/Math/Test/VectorTest.cpp

@ -58,7 +58,6 @@ class VectorTest: public Corrade::TestSuite::Tester {
void projected(); void projected();
void projectedOntoNormalized(); void projectedOntoNormalized();
void angle(); void angle();
void lerp();
void debug(); void debug();
void configuration(); void configuration();
@ -101,7 +100,6 @@ VectorTest::VectorTest() {
&VectorTest::projected, &VectorTest::projected,
&VectorTest::projectedOntoNormalized, &VectorTest::projectedOntoNormalized,
&VectorTest::angle, &VectorTest::angle,
&VectorTest::lerp,
&VectorTest::debug, &VectorTest::debug,
&VectorTest::configuration); &VectorTest::configuration);
@ -320,18 +318,6 @@ void VectorTest::angle() {
rad(1.162514f)); 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() { void VectorTest::debug() {
std::ostringstream o; std::ostringstream o;
Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f);

19
src/Math/Vector.h

@ -90,22 +90,6 @@ template<std::size_t size, class T> class Vector {
return std::acos(dot(normalizedA, normalizedB)); 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<class U> inline static Vector<size, T> lerp(const Vector<size, T>& a, const Vector<size, T>& b, U t) {
return (U(1) - t)*a + t*b;
}
/** @brief Construct zero-filled vector */ /** @brief Construct zero-filled vector */
inline constexpr /*implicit*/ Vector(): _data() {} inline constexpr /*implicit*/ Vector(): _data() {}
@ -587,9 +571,6 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
} \ } \
inline constexpr static const Type<T>& from(const T* data) { \ inline constexpr static const Type<T>& from(const T* data) { \
return *reinterpret_cast<const Type<T>*>(data); \ return *reinterpret_cast<const Type<T>*>(data); \
} \
template<class U> inline static const Type<T> lerp(const Math::Vector<size, T>& a, const Math::Vector<size, T>& b, U t) { \
return Math::Vector<size, T>::lerp(a, b, t); \
} \ } \
\ \
inline Type<T>& operator=(const Type<T>& other) { \ inline Type<T>& operator=(const Type<T>& other) { \

Loading…
Cancel
Save