Browse Source

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.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
23a94b2709
  1. 41
      src/Math/Quaternion.h
  2. 9
      src/Math/Test/MathQuaternionTest.cpp
  3. 5
      src/Math/Vector.h

41
src/Math/Quaternion.h

@ -33,6 +33,19 @@ namespace Magnum { namespace Math {
/** @brief %Quaternion */ /** @brief %Quaternion */
template<class T> class Quaternion { template<class T> class Quaternion {
public: 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<T>& a, const Quaternion<T>& b) {
/** @todo Use four-component SIMD implementation when available */
return Vector3<T>::dot(a.vector(), b.vector()) + a.scalar()*b.scalar();
}
/** /**
* @brief Linear interpolation of two quaternions * @brief Linear interpolation of two quaternions
* @param normalizedA First quaternion * @param normalizedA First quaternion
@ -44,7 +57,7 @@ template<class T> class Quaternion {
* @f] * @f]
*/ */
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.lengthSquared(), T(1)) && MathTypeTraits<T>::equals(normalizedB.lengthSquared(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)),
"Math::Quaternion::lerp(): quaternions must be normalized", Quaternion<T>({}, std::numeric_limits<T>::quiet_NaN())); "Math::Quaternion::lerp(): quaternions must be normalized", Quaternion<T>({}, std::numeric_limits<T>::quiet_NaN()));
return ((T(1) - t)*normalizedA + t*normalizedB).normalized(); return ((T(1) - t)*normalizedA + t*normalizedB).normalized();
} }
@ -96,7 +109,7 @@ template<class T> class Quaternion {
* @see rotationAxis(), fromRotation() * @see rotationAxis(), fromRotation()
*/ */
inline T rotationAngle() const { inline T rotationAngle() const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(lengthSquared(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),
"Math::Quaternion::rotationAngle(): quaternion must be normalized", "Math::Quaternion::rotationAngle(): quaternion must be normalized",
std::numeric_limits<T>::quiet_NaN()); std::numeric_limits<T>::quiet_NaN());
return T(2)*std::acos(_scalar); return T(2)*std::acos(_scalar);
@ -111,7 +124,7 @@ template<class T> class Quaternion {
* @see rotationAngle(), fromRotation() * @see rotationAngle(), fromRotation()
*/ */
inline Vector3<T> rotationAxis() const { inline Vector3<T> rotationAxis() const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(lengthSquared(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),
"Math::Quaternion::rotationAxis(): quaternion must be normalized", "Math::Quaternion::rotationAxis(): quaternion must be normalized",
{}); {});
return _vector/std::sqrt(1-pow<2>(_scalar)); return _vector/std::sqrt(1-pow<2>(_scalar));
@ -249,24 +262,28 @@ template<class T> class Quaternion {
} }
/** /**
* @brief %Quaternion length squared * @brief Dot product of the quaternion
* *
* Should be used instead of length() for comparing quaternion length * Should be used instead of length() for comparing quaternion length
* with other values, because it doesn't compute the square root. @f[ * 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] * @f]
* @see dot(const Quaternion<T>&, const Quaternion<T>&)
*/ */
inline T lengthSquared() const { inline T dot() const {
return _vector.dot() + _scalar*_scalar; return dot(*this, *this);
} }
/** /**
* @brief %Quaternion length * @brief %Quaternion length
* *
* @see lengthSquared() * @f[
* |q| = \sqrt{q \cdot q}
* @f]
* @see dot() const
*/ */
inline T length() const { inline T length() const {
return std::sqrt(lengthSquared()); return std::sqrt(dot());
} }
/** @brief Normalized quaternion (of length 1) */ /** @brief Normalized quaternion (of length 1) */
@ -290,11 +307,11 @@ template<class T> class Quaternion {
* *
* See invertedNormalized() which is faster for normalized * See invertedNormalized() which is faster for normalized
* quaternions. @f[ * 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] * @f]
*/ */
inline Quaternion<T> inverted() const { inline Quaternion<T> inverted() const {
return conjugated()/lengthSquared(); return conjugated()/dot();
} }
/** /**
@ -306,7 +323,7 @@ template<class T> class Quaternion {
* @f] * @f]
*/ */
inline Quaternion<T> invertedNormalized() const { inline Quaternion<T> invertedNormalized() const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(lengthSquared(), T(1)), CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),
"Math::Quaternion::invertedNormalized(): quaternion must be normalized", "Math::Quaternion::invertedNormalized(): quaternion must be normalized",
Quaternion<T>({}, std::numeric_limits<T>::quiet_NaN())); Quaternion<T>({}, std::numeric_limits<T>::quiet_NaN()));
return conjugated(); return conjugated();

9
src/Math/Test/MathQuaternionTest.cpp

@ -31,6 +31,7 @@ class QuaternionTest: public Corrade::TestSuite::Tester {
void negated(); void negated();
void multiplyDivideScalar(); void multiplyDivideScalar();
void multiply(); void multiply();
void dot();
void length(); void length();
void normalized(); void normalized();
void conjugated(); void conjugated();
@ -52,6 +53,7 @@ QuaternionTest::QuaternionTest() {
&QuaternionTest::negated, &QuaternionTest::negated,
&QuaternionTest::multiplyDivideScalar, &QuaternionTest::multiplyDivideScalar,
&QuaternionTest::multiply, &QuaternionTest::multiply,
&QuaternionTest::dot,
&QuaternionTest::length, &QuaternionTest::length,
&QuaternionTest::normalized, &QuaternionTest::normalized,
&QuaternionTest::conjugated, &QuaternionTest::conjugated,
@ -100,6 +102,13 @@ void QuaternionTest::multiply() {
Quaternion({-11.0f, -16.5f, 27.5f}, 115.0f)); 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() { void QuaternionTest::length() {
CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f)); CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f));
} }

5
src/Math/Vector.h

@ -200,7 +200,7 @@ template<std::size_t size, class T> class Vector: public RectangularMatrix<1, si
* *
* Should be used instead of length() for comparing vector length with * Should be used instead of length() for comparing vector length with
* other values, because it doesn't compute the square root. @f[ * 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] * @f]
* @see dot(const Vector<size, T>&, const Vector<size, T>&) * @see dot(const Vector<size, T>&, const Vector<size, T>&)
*/ */
@ -211,6 +211,9 @@ template<std::size_t size, class T> class Vector: public RectangularMatrix<1, si
/** /**
* @brief %Vector length * @brief %Vector length
* *
* @f[
* |a| = \sqrt{a \cdot a}
* @f]
* @see dot() const * @see dot() const
*/ */
inline T length() const { inline T length() const {

Loading…
Cancel
Save