Browse Source

Math: creating rotation and translation DualQuaternion.

pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
3ad264893e
  1. 68
      src/Math/DualQuaternion.h
  2. 10
      src/Math/Matrix4.h
  3. 6
      src/Math/Quaternion.h
  4. 8
      src/Math/Test/CMakeLists.txt
  5. 30
      src/Math/Test/DualQuaternionTest.cpp

68
src/Math/DualQuaternion.h

@ -31,6 +31,36 @@ namespace Magnum { namespace Math {
*/
template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
public:
/**
* @brief Rotation dual quaternion
* @param angle Rotation angle (counterclockwise, in radians)
* @param normalizedAxis Normalized rotation axis
*
* Expects that the rotation axis is normalized. @f[
* \hat q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2] + \epsilon [\boldsymbol 0, 0]
* @f]
* @see rotationAngle(), rotationAxis(), Quaternion::rotation(),
* Matrix4::rotation(), Vector3::xAxis(), Vector3::yAxis(),
* Vector3::zAxis(), deg(), rad()
*/
inline static DualQuaternion<T> rotation(T angle, const Vector3<T>& normalizedAxis) {
return {Quaternion<T>::rotation(angle, normalizedAxis), {{}, T(0)}};
}
/**
* @brief Translation dual quaternion
* @param vector Translation vector
*
* @f[
* \hat q = [\boldsymbol 0, 1] + \epsilon [\frac{\boldsymbol v}{2}, 0]
* @f]
* @see translation() const, Matrix3::translation(const Vector2&),
* Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis()
*/
inline static DualQuaternion<T> translation(const Vector3<T>& vector) {
return {{}, {vector/T(2), T(0)}};
}
/**
* @brief Default constructor
*
@ -52,6 +82,44 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
*/
inline constexpr /*implicit*/ DualQuaternion(const Quaternion<T>& real, const Quaternion<T>& dual): Dual<Quaternion<T>>(real, dual) {}
/**
* @brief Rotation angle of unit dual quaternion
*
* Expects that the real part of the quaternion is normalized. @f[
* \theta = 2 \cdot acos q_{S 0}
* @f]
* @see rotationAxis(), rotation(), Quaternion::rotationAngle()
*/
inline T rotationAngle() const {
return this->real().rotationAngle();
}
/**
* @brief Rotation axis of unit dual quaternion
*
* Expects that the quaternion is normalized. Returns either unit-length
* vector for valid rotation quaternion or NaN vector for
* default-constructed quaternion. @f[
* \boldsymbol a = \frac{\boldsymbol q_{V 0}}{\sqrt{1 - q_{S 0}^2}}
* @f]
* @see rotationAngle(), rotation(), Quaternion::rotationAxis()
*/
inline Vector3<T> rotationAxis() const {
return this->real().rotationAxis();
}
/**
* @brief Translation part of unit dual quaternion
*
* @f[
* \boldsymbol a = 2 (q_\epsilon q_0^*)_V
* @f]
* @see translation(const Vector3&)
*/
inline Vector3<T> translation() const {
return (this->dual()*this->real().conjugated()).vector()*T(2);
}
/**
* @brief Quaternion-conjugated dual quaternion
*

10
src/Math/Matrix4.h

@ -39,8 +39,9 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D translation
* @param vector Translation vector
*
* @see translation(), Matrix3::translation(const Vector2&),
* Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis()
* @see translation(), DualQuaternion::translation(),
* Matrix3::translation(const Vector2&), Vector3::xAxis(),
* Vector3::yAxis(), Vector3::zAxis()
*/
inline constexpr static Matrix4<T> translation(const Vector3<T>& vector) {
return {{ T(1), T(0), T(0), T(0)},
@ -70,8 +71,9 @@ template<class T> class Matrix4: public Matrix<4, T> {
*
* Expects that the rotation axis is normalized. If possible, use
* faster alternatives like rotationX(), rotationY() and rotationZ().
* @see rotation() const, Quaternion::rotation(), Matrix3::rotation(T),
* Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis(), deg(), rad()
* @see rotation() const, DualQuaternion::rotation(),
* Quaternion::rotation(), Matrix3::rotation(T), Vector3::xAxis(),
* Vector3::yAxis(), Vector3::zAxis(), deg(), rad()
*/
static Matrix4<T> rotation(T angle, const Vector3<T>& normalizedAxis) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedAxis.dot(), T(1)),

6
src/Math/Quaternion.h

@ -103,14 +103,16 @@ template<class T> class Quaternion {
}
/**
* @brief Create quaternion from rotation
* @brief Rotation quaternion
* @param angle Rotation angle (counterclockwise, in radians)
* @param normalizedAxis Normalized rotation axis
*
* Expects that the rotation axis is normalized. @f[
* q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2]
* @f]
* @see Matrix4::rotation()
* @see rotationAngle(), rotationAxis(), DualQuaternion::rotation(),
* Matrix4::rotation(), Vector3::xAxis(), Vector3::yAxis(),
* Vector3::zAxis(), deg(), rad()
*/
inline static Quaternion<T> rotation(T angle, const Vector3<T>& normalizedAxis) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedAxis.dot(), T(1)),

8
src/Math/Test/CMakeLists.txt

@ -21,4 +21,10 @@ 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)
set_target_properties(
MathVectorTest
MathMatrix3Test
MathMatrix4Test
MathDualQuaternionTest
MathQuaternionTest
PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

30
src/Math/Test/DualQuaternionTest.cpp

@ -16,6 +16,7 @@
#include <sstream>
#include <TestSuite/Tester.h>
#include "Math/Constants.h"
#include "Math/DualQuaternion.h"
namespace Magnum { namespace Math { namespace Test {
@ -34,6 +35,9 @@ class DualQuaternionTest: public Corrade::TestSuite::Tester {
void conjugated();
void inverted();
void rotation();
void translation();
void debug();
};
@ -53,6 +57,9 @@ DualQuaternionTest::DualQuaternionTest() {
&DualQuaternionTest::conjugated,
&DualQuaternionTest::inverted,
&DualQuaternionTest::rotation,
&DualQuaternionTest::translation,
&DualQuaternionTest::debug);
}
@ -102,6 +109,29 @@ void DualQuaternionTest::inverted() {
CORRADE_COMPARE(a.inverted(), b);
}
void DualQuaternionTest::rotation() {
std::ostringstream o;
Error::setOutput(&o);
float angle = deg(120.0f);
Vector3 axis(1.0f/Constants<float>::sqrt3());
CORRADE_COMPARE(DualQuaternion::rotation(angle, axis*2.0f), DualQuaternion());
CORRADE_COMPARE(o.str(), "Math::Quaternion::rotation(): axis must be normalized\n");
DualQuaternion q = DualQuaternion::rotation(angle, axis);
CORRADE_COMPARE(q, DualQuaternion({Vector3(0.5f, 0.5f, 0.5f), 0.5f}, {{}, 0.0f}));
CORRADE_COMPARE(q.rotationAngle(), angle);
CORRADE_COMPARE(q.rotationAxis(), axis);
}
void DualQuaternionTest::translation() {
Vector3 vec(1.0f, -3.5f, 0.5f);
DualQuaternion q = DualQuaternion::translation(vec);
CORRADE_COMPARE(q, DualQuaternion({}, {{0.5f, -1.75f, 0.25f}, 0.0f}));
CORRADE_COMPARE(q.translation(), vec);
}
void DualQuaternionTest::debug() {
std::ostringstream o;

Loading…
Cancel
Save