Browse Source

Math: initial implementation of DualQuaternion class.

Currently practically unusable.
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
5615a4c7f6
  1. 1
      src/CMakeLists.txt
  2. 1
      src/Math/CMakeLists.txt
  3. 27
      src/Math/DualQuaternion.cpp
  4. 159
      src/Math/DualQuaternion.h
  5. 1
      src/Math/Math.h
  6. 2
      src/Math/Quaternion.h
  7. 1
      src/Math/Test/CMakeLists.txt
  8. 114
      src/Math/Test/DualQuaternionTest.cpp

1
src/CMakeLists.txt

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

1
src/Math/CMakeLists.txt

@ -2,6 +2,7 @@ set(MagnumMath_HEADERS
BoolVector.h
Constants.h
Dual.h
DualQuaternion.h
Functions.h
Math.h
MathTypeTraits.h

27
src/Math/DualQuaternion.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 "DualQuaternion.h"
namespace Magnum { namespace Math {
#ifndef DOXYGEN_GENERATING_OUTPUT
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const DualQuaternion<float>&);
#ifndef MAGNUM_TARGET_GLES
template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const DualQuaternion<double>&);
#endif
#endif
}}

159
src/Math/DualQuaternion.h

@ -0,0 +1,159 @@
#ifndef Magnum_Math_DualQuaternion_h
#define Magnum_Math_DualQuaternion_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::DualQuaternion
*/
#include "Math/Dual.h"
#include "Math/Quaternion.h"
namespace Magnum { namespace Math {
/**
@brief %Dual quaternion
@see Dual, Quaternion
*/
template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
public:
/**
* @brief Default constructor
*
* All components set to zero except real scalar part, which is `1`.
* @todoc Remove workaround when Doxygen is predictable
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
inline constexpr /*implicit*/ DualQuaternion();
#else
inline constexpr /*implicit*/ DualQuaternion(): Dual<Quaternion<T>>({}, {{}, T(0)}) {}
#endif
/**
* @brief Construct dual quaternion from real and dual part
*
* @f[
* \hat q = q_0 + \epsilon q_\epsilon
* @f]
*/
inline constexpr /*implicit*/ DualQuaternion(const Quaternion<T>& real, const Quaternion<T>& dual): Dual<Quaternion<T>>(real, dual) {}
/**
* @brief Quaternion-conjugated dual quaternion
*
* @f[
* \hat q^* = q_0^* + q_\epsilon^*
* @f]
* @see dualConjugated(), conjugated(), Quaternion::conjugated()
*/
inline DualQuaternion<T> quaternionConjugated() const {
return {this->real().conjugated(), this->dual().conjugated()};
}
/**
* @brief Dual-conjugated dual quaternion
*
* @f[
* \overline{\hat q} = q_0 - \epsilon q_\epsilon
* @f]
* @see quaternionConjugated(), conjugated(), Dual::conjugated()
*/
inline DualQuaternion<T> dualConjugated() const {
return Dual<Quaternion<T>>::conjugated();
}
/**
* @brief Conjugated dual quaternion
*
* Both quaternion and dual conjugation. @f[
* \overline{\hat q^*} = q_0^* - \epsilon q_\epsilon^* = q_0^* + \epsilon [\boldsymbol q_{\epsilon V}, -q_S]
* @f]
* @see quaternionConjugated(), dualConjugated(), Quaternion::conjugated(),
* Dual::conjugated()
*/
inline DualQuaternion<T> conjugated() const {
return {this->real().conjugated(), {this->dual().vector(), -this->dual().scalar()}};
}
/**
* @brief %Dual quaternion norm
*
* @f[
* ||\hat q|| = \sqrt{\hat q^* \hat q} = ||q_0|| + \epsilon \frac{q_0 \cdot q_\epsilon}{||q_0||}
* @f]
*/
inline Dual<T> norm() const {
T norm = this->real().length();
return {norm, Quaternion<T>::dot(this->real(), this->dual())/norm};
}
/**
* @brief Inverted dual quaternion
*
* See invertedNormalized() which is faster for normalized
* dual quaternions. @f[
* \hat q^{-1} = \frac{\hat q^*}{||\hat q||^2}
* @f]
*/
inline DualQuaternion<T> inverted() const {
return quaternionConjugated()/Math::pow<2>(norm());
}
/**
* @brief Inverted normalized dual quaternion
*
* Equivalent to quaternionConjugated(). Expects that the quaternion is
* normalized. @f[
* \hat q^{-1} = \frac{\hat q^*}{||\hat q||^2} = \hat q^*
* @f]
*/
inline DualQuaternion<T> invertedNormalized() const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(norm(), T(1)),
"Math::DualQuaternion::invertedNormalized(): dual quaternion must be normalized", {});
return quaternionConjugated();
}
MAGNUM_DUAL_SUBCLASS_IMPLEMENTATION(DualQuaternion, Quaternion)
private:
/* Used by Dual operators and dualConjugated() */
DualQuaternion<T>(const Dual<Quaternion<T>>& other): Dual<Quaternion<T>>(other) {}
};
/** @debugoperator{Magnum::Math::DualQuaternion} */
template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const DualQuaternion<T>& value) {
debug << "DualQuaternion({{";
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false);
debug << value.real().vector().x() << ", " << value.real().vector().y() << ", " << value.real().vector().z()
<< "}, " << value.real().scalar() << "}, {{"
<< value.dual().vector().x() << ", " << value.dual().vector().y() << ", " << value.dual().vector().z()
<< "}, " << value.dual().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 DualQuaternion<float>&);
#ifndef MAGNUM_TARGET_GLES
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const DualQuaternion<double>&);
#endif
#endif
}}
#endif

1
src/Math/Math.h

@ -28,6 +28,7 @@ namespace Magnum { namespace Math {
/* Class Constants used only statically */
template<class T> class Dual;
template<class> class DualQuaternion;
template<std::size_t, class> class Matrix;
template<class> class Matrix3;

2
src/Math/Quaternion.h

@ -33,7 +33,7 @@ namespace Magnum { namespace Math {
/**
@brief %Quaternion
@see Magnum::Quaternion
@see DualQuaternion, Magnum::Quaternion
*/
template<class T> class Quaternion {
public:

1
src/Math/Test/CMakeLists.txt

@ -19,5 +19,6 @@ corrade_add_test(MathSwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathDualTest DualTest.cpp)
corrade_add_test(MathQuaternionTest QuaternionTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(MathDualQuaternionTest DualQuaternionTest.cpp LIBRARIES MagnumMathTestLib)
set_target_properties(MathVectorTest MathMatrix3Test MathMatrix4Test MathQuaternionTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

114
src/Math/Test/DualQuaternionTest.cpp

@ -0,0 +1,114 @@
/*
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/DualQuaternion.h"
namespace Magnum { namespace Math { namespace Test {
class DualQuaternionTest: public Corrade::TestSuite::Tester {
public:
explicit DualQuaternionTest();
void construct();
void constructDefault();
void norm();
void quaternionConjugated();
void dualConjugated();
void conjugated();
void inverted();
void debug();
};
typedef Math::Dual<float> Dual;
typedef Math::DualQuaternion<float> DualQuaternion;
typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;
DualQuaternionTest::DualQuaternionTest() {
addTests(&DualQuaternionTest::construct,
&DualQuaternionTest::constructDefault,
&DualQuaternionTest::norm,
&DualQuaternionTest::quaternionConjugated,
&DualQuaternionTest::dualConjugated,
&DualQuaternionTest::conjugated,
&DualQuaternionTest::inverted,
&DualQuaternionTest::debug);
}
void DualQuaternionTest::construct() {
DualQuaternion q({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
CORRADE_COMPARE(q.real(), Quaternion({1.0f, 2.0f, 3.0f}, -4.0f));
CORRADE_COMPARE(q.dual(), Quaternion({0.5f, -3.1f, 3.3f}, 2.0f));
}
void DualQuaternionTest::constructDefault() {
CORRADE_COMPARE(DualQuaternion(), DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}));
}
void DualQuaternionTest::norm() {
CORRADE_COMPARE(DualQuaternion().norm(), 1.0f);
DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.0f, 3.0f}, 2.0f});
CORRADE_COMPARE(a.norm(), Dual(5.477226f, -0.821584f));
}
void DualQuaternionTest::quaternionConjugated() {
DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f});
DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f, 3.1f, -3.3f}, 2.0f});
CORRADE_COMPARE(a.quaternionConjugated(), b);
}
void DualQuaternionTest::dualConjugated() {
DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f});
DualQuaternion b({{1.0f, 2.0f, 3.0f}, -4.0f}, {{-0.5f, 3.1f, -3.3f}, -2.0f});
CORRADE_COMPARE(a.dualConjugated(), b);
}
void DualQuaternionTest::conjugated() {
DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, 2.0f});
DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{ 0.5f, -3.1f, 3.3f}, -2.0f});
CORRADE_COMPARE(a.conjugated(), b);
}
void DualQuaternionTest::inverted() {
DualQuaternion a({{ 1.0f, 2.0f, 3.0f}, -4.0f}, {{ 2.5f, -3.1f, 3.3f}, 2.0f});
DualQuaternion b({{-0.033333f, -0.066667f, -0.1f}, -0.133333f}, {{-0.087333f, 0.095333f, -0.122f}, 0.050667f});
CORRADE_COMPARE(a*a.inverted(), DualQuaternion());
CORRADE_COMPARE(a.inverted(), b);
}
void DualQuaternionTest::debug() {
std::ostringstream o;
Debug(&o) << DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
CORRADE_COMPARE(o.str(), "DualQuaternion({{1, 2, 3}, -4}, {{0.5, -3.1, 3.3}, 2})\n");
}
}}}
CORRADE_TEST_MAIN(Magnum::Math::Test::DualQuaternionTest)
Loading…
Cancel
Save