Browse Source

Math: initial implementation of Quaternion class.

Still practically unusable.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
89c2bf913c
  1. 1
      src/CMakeLists.txt
  2. 1
      src/Math/CMakeLists.txt
  3. 27
      src/Math/Quaternion.cpp
  4. 168
      src/Math/Quaternion.h
  5. 2
      src/Math/Test/CMakeLists.txt
  6. 105
      src/Math/Test/MathQuaternionTest.cpp

1
src/CMakeLists.txt

@ -103,6 +103,7 @@ add_library(MagnumObjects OBJECT ${Magnum_SRCS})
# Files shared between main library and math unit test library # Files shared between main library and math unit test library
set(MagnumMath_SRCS set(MagnumMath_SRCS
Math/Math.cpp Math/Math.cpp
Math/Quaternion.cpp
Math/RectangularMatrix.cpp Math/RectangularMatrix.cpp
Math/Vector.cpp) Math/Vector.cpp)
add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS}) add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS})

1
src/Math/CMakeLists.txt

@ -9,6 +9,7 @@ set(MagnumMath_HEADERS
Matrix4.h Matrix4.h
Point2D.h Point2D.h
Point3D.h Point3D.h
Quaternion.h
RectangularMatrix.h RectangularMatrix.h
Swizzle.h Swizzle.h
Vector.h Vector.h

27
src/Math/Quaternion.cpp

@ -0,0 +1,27 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "Quaternion.h"
namespace Magnum { namespace Math {
#ifndef DOXYGEN_GENERATING_OUTPUT
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Quaternion<float>&);
#ifndef MAGNUM_TARGET_GLES
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Quaternion<double>&);
#endif
#endif
}}

168
src/Math/Quaternion.h

@ -0,0 +1,168 @@
#ifndef Magnum_Math_Quaternion_h
#define Magnum_Math_Quaternion_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Math::Quaternion
*/
#include <cmath>
#include <Utility/Debug.h>
#include "Vector3.h"
#include "MathTypeTraits.h"
namespace Magnum { namespace Math {
/** @brief %Quaternion */
template<class T> class Quaternion {
public:
/** @brief Default constructor */
inline constexpr Quaternion(): _scalar(T(1)) {}
/** @brief Create quaternion from vector and scalar */
inline constexpr Quaternion(const Vector3<T>& vector, T scalar): _vector(vector), _scalar(scalar) {}
/** @brief Equality comparison */
inline bool operator==(const Quaternion<T>& other) const {
return _vector == other._vector && MathTypeTraits<T>::equals(_scalar, other._scalar);
}
/** @brief Non-equality comparison */
inline bool operator!=(const Quaternion<T>& other) const {
return !operator==(other);
}
/** @brief %Vector part */
inline constexpr Vector3<T> vector() const { return _vector; }
/** @brief %Scalar part */
inline constexpr T scalar() const { return _scalar; }
/**
* @brief Multiply with scalar and assign
*
* The computation is done in-place.
*/
inline Quaternion<T>& operator*=(T number) {
_vector *= number;
_scalar *= number;
return *this;
}
/**
* @brief Divide with scalar and assign
*
* The computation is done in-place.
*/
inline Quaternion<T>& operator/=(T number) {
_vector /= number;
_scalar /= number;
return *this;
}
/**
* @brief Multiply with scalar
*
* @see operator*=(T)
*/
inline constexpr Quaternion<T> operator*(T scalar) const {
return Quaternion<T>(*this)*=scalar;
}
/**
* @brief Divide with scalar
*
* @see operator/=(T)
*/
inline constexpr Quaternion<T> operator/(T scalar) const {
return Quaternion<T>(*this)/=scalar;
}
/**
* @brief Multiply with quaternion
*
* The computation is *not* done in-place.
*/
inline constexpr Quaternion<T> operator*(const Quaternion<T>& other) const {
return {_scalar*other._vector + other._scalar*_vector + Vector3<T>::cross(_vector, other._vector),
_scalar*other._scalar - Vector3<T>::dot(_vector, other._vector)};
}
/**
* @brief Multiply with quaternion and assign
*
* @see operator*(const Quaternion<T>&) const
*/
inline Quaternion<T>& operator*=(const Quaternion<T>& other) {
return (*this = *this * other);
}
/** @brief %Quaternion length squared */
inline constexpr T lengthSquared() const {
return _vector.dot() + _scalar*_scalar;
}
/** @brief %Quaternion length */
inline constexpr T length() const {
return std::sqrt(lengthSquared());
}
/** @brief Normalized quaternion */
inline constexpr Quaternion<T> normalized() const {
return (*this)/length();
}
/** @brief Conjugated quaternion */
inline constexpr Quaternion<T> conjugated() const {
return {-_vector, _scalar};
}
/**
* @brief Inverted quaternion
*
* If the quaternion is already normalized, this function is
* equivalent to conjugated().
*/
inline constexpr Quaternion<T> inverted() const {
return conjugated()/lengthSquared();
}
private:
Vector3<T> _vector;
T _scalar;
};
/** @debugoperator{Magnum::Math::Geometry::Rectangle} */
template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Quaternion<T>& value) {
debug << "Quaternion({";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false);
debug << value.vector().x() << ", " << value.vector().y() << ", " << value.vector().z() << "}, " << value.scalar() << ")";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true);
return debug;
}
/* Explicit instantiation for commonly used types */
#ifndef DOXYGEN_GENERATING_OUTPUT
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<float>&);
#ifndef MAGNUM_TARGET_GLES
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<double>&);
#endif
#endif
}}
#endif

2
src/Math/Test/CMakeLists.txt

@ -18,4 +18,6 @@ corrade_add_test(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathQuaternionTest MathQuaternionTest.cpp LIBRARIES MagnumMathTestLib)
set_target_properties(MathVectorTest MathMatrix3Test MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) set_target_properties(MathVectorTest MathMatrix3Test MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

105
src/Math/Test/MathQuaternionTest.cpp

@ -0,0 +1,105 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "Math/Quaternion.h"
namespace Magnum { namespace Math { namespace Test {
class QuaternionTest: public Corrade::TestSuite::Tester {
public:
explicit QuaternionTest();
void construct();
void multiplyDivideScalar();
void multiply();
void length();
void normalized();
void conjugated();
void inverted();
void debug();
};
typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;
QuaternionTest::QuaternionTest() {
addTests(&QuaternionTest::construct,
&QuaternionTest::multiplyDivideScalar,
&QuaternionTest::multiply,
&QuaternionTest::length,
&QuaternionTest::normalized,
&QuaternionTest::conjugated,
&QuaternionTest::inverted,
&QuaternionTest::debug);
}
void QuaternionTest::construct() {
Quaternion q({1.0f, 2.0f, 3.0f}, -4.0f);
CORRADE_COMPARE(q.vector(), Vector3(1.0f, 2.0f, 3.0f));
CORRADE_COMPARE(q.scalar(), -4.0f);
CORRADE_COMPARE(Quaternion(), Quaternion({0.0f, 0.0f, 0.0f}, {1.0f}));
}
void QuaternionTest::multiplyDivideScalar() {
Quaternion a({1.0f, 3.0f, -2.0f}, -4.0f);
Quaternion b({-1.5f, -4.5f, 3.0f}, 6.0f);
CORRADE_COMPARE(a*-1.5f, b);
CORRADE_COMPARE(b/-1.5f, a);
}
void QuaternionTest::multiply() {
CORRADE_COMPARE(Quaternion({-6.0f, -9.0f, 15.0f}, 0.5f)*Quaternion({2.0f, 3.0f, -5.0f}, 2.0f),
Quaternion({-11.0f, -16.5f, 27.5f}, 115.0f));
}
void QuaternionTest::length() {
CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).length(), std::sqrt(30.0f));
}
void QuaternionTest::normalized() {
CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).normalized(),
Quaternion({1.0f, 3.0f, -2.0f}, -4.0f)/std::sqrt(30.0f));
}
void QuaternionTest::conjugated() {
CORRADE_COMPARE(Quaternion({1.0f, 3.0f, -2.0f}, -4.0f).conjugated(),
Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f));
}
void QuaternionTest::inverted() {
Quaternion a = Quaternion({1.0f, 3.0f, -2.0f}, -4.0f);
Quaternion inverted = a.inverted();
CORRADE_COMPARE(a*inverted, Quaternion());
CORRADE_COMPARE(inverted*a, Quaternion());
CORRADE_COMPARE(inverted, Quaternion({-1.0f, -3.0f, 2.0f}, -4.0f)/30.0f);
}
void QuaternionTest::debug() {
std::ostringstream o;
Corrade::Utility::Debug(&o) << Quaternion({1.0f, 2.0f, 3.0f}, -4.0f);
CORRADE_COMPARE(o.str(), "Quaternion({1, 2, 3}, -4)\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::QuaternionTest)
Loading…
Cancel
Save