From 23a94b27097af8e9b8a9c84ceaa2857de9bbde41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Jan 2013 18:53:14 +0100 Subject: [PATCH] Math: Quaternion has dot product too! Original lengthSquared() renamed to parameterless dot(), it is now consistent with what Vector has. Also updated related Vector documentation. --- src/Math/Quaternion.h | 41 ++++++++++++++++++++-------- src/Math/Test/MathQuaternionTest.cpp | 9 ++++++ src/Math/Vector.h | 5 +++- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/Math/Quaternion.h b/src/Math/Quaternion.h index 5498ca159..d4775c629 100644 --- a/src/Math/Quaternion.h +++ b/src/Math/Quaternion.h @@ -33,6 +33,19 @@ namespace Magnum { namespace Math { /** @brief %Quaternion */ template class Quaternion { public: + /** + * @brief Dot product + * + * @f[ + * p \cdot q = \boldsymbol p_V \cdot \boldsymbol q_V + p_S q_S + * @f] + * @see dot() const + */ + inline static T dot(const Quaternion& a, const Quaternion& b) { + /** @todo Use four-component SIMD implementation when available */ + return Vector3::dot(a.vector(), b.vector()) + a.scalar()*b.scalar(); + } + /** * @brief Linear interpolation of two quaternions * @param normalizedA First quaternion @@ -44,7 +57,7 @@ template class Quaternion { * @f] */ inline static Quaternion lerp(const Quaternion& normalizedA, const Quaternion& normalizedB, T t) { - CORRADE_ASSERT(MathTypeTraits::equals(normalizedA.lengthSquared(), T(1)) && MathTypeTraits::equals(normalizedB.lengthSquared(), T(1)), + CORRADE_ASSERT(MathTypeTraits::equals(normalizedA.dot(), T(1)) && MathTypeTraits::equals(normalizedB.dot(), T(1)), "Math::Quaternion::lerp(): quaternions must be normalized", Quaternion({}, std::numeric_limits::quiet_NaN())); return ((T(1) - t)*normalizedA + t*normalizedB).normalized(); } @@ -96,7 +109,7 @@ template class Quaternion { * @see rotationAxis(), fromRotation() */ inline T rotationAngle() const { - CORRADE_ASSERT(MathTypeTraits::equals(lengthSquared(), T(1)), + CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), "Math::Quaternion::rotationAngle(): quaternion must be normalized", std::numeric_limits::quiet_NaN()); return T(2)*std::acos(_scalar); @@ -111,7 +124,7 @@ template class Quaternion { * @see rotationAngle(), fromRotation() */ inline Vector3 rotationAxis() const { - CORRADE_ASSERT(MathTypeTraits::equals(lengthSquared(), T(1)), + CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), "Math::Quaternion::rotationAxis(): quaternion must be normalized", {}); return _vector/std::sqrt(1-pow<2>(_scalar)); @@ -249,24 +262,28 @@ template class Quaternion { } /** - * @brief %Quaternion length squared + * @brief Dot product of the quaternion * * Should be used instead of length() for comparing quaternion length * with other values, because it doesn't compute the square root. @f[ - * |q|^2 = \boldsymbol q_V \cdot \boldsymbol q_V + q_S q_S + * q \cdot q = \boldsymbol q_V \cdot \boldsymbol q_V + q_S^2 * @f] + * @see dot(const Quaternion&, const Quaternion&) */ - inline T lengthSquared() const { - return _vector.dot() + _scalar*_scalar; + inline T dot() const { + return dot(*this, *this); } /** * @brief %Quaternion length * - * @see lengthSquared() + * @f[ + * |q| = \sqrt{q \cdot q} + * @f] + * @see dot() const */ inline T length() const { - return std::sqrt(lengthSquared()); + return std::sqrt(dot()); } /** @brief Normalized quaternion (of length 1) */ @@ -290,11 +307,11 @@ template class Quaternion { * * See invertedNormalized() which is faster for normalized * quaternions. @f[ - * q^{-1} = \frac{q^*}{|q|^2} = \frac{[-\boldsymbol q_V, q_S]}{|q|^2} + * q^{-1} = \frac{q^*}{|q|^2} = \frac{[-\boldsymbol q_V, q_S]}{q \cdot q} * @f] */ inline Quaternion inverted() const { - return conjugated()/lengthSquared(); + return conjugated()/dot(); } /** @@ -306,7 +323,7 @@ template class Quaternion { * @f] */ inline Quaternion invertedNormalized() const { - CORRADE_ASSERT(MathTypeTraits::equals(lengthSquared(), T(1)), + CORRADE_ASSERT(MathTypeTraits::equals(dot(), T(1)), "Math::Quaternion::invertedNormalized(): quaternion must be normalized", Quaternion({}, std::numeric_limits::quiet_NaN())); return conjugated(); diff --git a/src/Math/Test/MathQuaternionTest.cpp b/src/Math/Test/MathQuaternionTest.cpp index 20414b0d6..d4d52cf96 100644 --- a/src/Math/Test/MathQuaternionTest.cpp +++ b/src/Math/Test/MathQuaternionTest.cpp @@ -31,6 +31,7 @@ class QuaternionTest: public Corrade::TestSuite::Tester { void negated(); void multiplyDivideScalar(); void multiply(); + void dot(); void length(); void normalized(); void conjugated(); @@ -52,6 +53,7 @@ QuaternionTest::QuaternionTest() { &QuaternionTest::negated, &QuaternionTest::multiplyDivideScalar, &QuaternionTest::multiply, + &QuaternionTest::dot, &QuaternionTest::length, &QuaternionTest::normalized, &QuaternionTest::conjugated, @@ -100,6 +102,13 @@ void QuaternionTest::multiply() { Quaternion({-11.0f, -16.5f, 27.5f}, 115.0f)); } +void QuaternionTest::dot() { + Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f); + Quaternion b({-0.5f, 1.5f, 3.0f}, 12.0f); + + CORRADE_COMPARE(Quaternion::dot(a, b), -50.0f); +} + void QuaternionTest::length() { CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f)); } diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 838b75c25..421dcdf41 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -200,7 +200,7 @@ template class Vector: public RectangularMatrix<1, si * * Should be used instead of length() for comparing vector length with * other values, because it doesn't compute the square root. @f[ - * |a|^2 = a \cdot a + * a \cdot a = \sum_{i=0}^{n-1} a_i^2 * @f] * @see dot(const Vector&, const Vector&) */ @@ -211,6 +211,9 @@ template class Vector: public RectangularMatrix<1, si /** * @brief %Vector length * + * @f[ + * |a| = \sqrt{a \cdot a} + * @f] * @see dot() const */ inline T length() const {