From 52434fb55c81df78ea3c57eb3a829cbc8cdc7a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Jun 2015 15:28:15 +0200 Subject: [PATCH] Math: ability to convert dual quaternions from/to external representation. Still undocumented feature. --- src/Magnum/Math/DualQuaternion.h | 12 +++++ src/Magnum/Math/Test/DualQuaternionTest.cpp | 49 ++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 694e080e1..a9415d67b 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -35,6 +35,10 @@ namespace Magnum { namespace Math { +namespace Implementation { + template struct DualQuaternionConverter; +} + /** @brief Dual quaternion @tparam T Underlying data type @@ -134,9 +138,17 @@ template class DualQuaternion: public Dual> { constexpr explicit DualQuaternion(const Vector3& vector): Dual>({}, {vector, T(0)}) {} #endif + /** @brief Construct dual quaternion from external representation */ + template::from(std::declval()))> constexpr explicit DualQuaternion(const U& other): DualQuaternion{Implementation::DualQuaternionConverter::from(other)} {} + /** @brief Copy constructor */ constexpr DualQuaternion(const Dual>& other): Dual>(other) {} + /** @brief Convert dual quaternion to external representation */ + template::to(std::declval>()))> constexpr explicit operator U() const { + return Implementation::DualQuaternionConverter::to(*this); + } + /** * @brief Whether the dual quaternion is normalized * diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 6dda7f02b..f5c6efa8b 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -28,7 +28,30 @@ #include "Magnum/Math/DualQuaternion.h" -namespace Magnum { namespace Math { namespace Test { +struct DualQuat { + struct { float x, y, z, w; } re; + struct { float x, y, z, w; } du; +}; + +namespace Magnum { namespace Math { + +namespace Implementation { + +template<> struct DualQuaternionConverter { + constexpr static DualQuaternion from(const DualQuat& other) { + return {{{other.re.x, other.re.y, other.re.z}, other.re.w}, + {{other.du.x, other.du.y, other.du.z}, other.du.w}}; + } + + constexpr static DualQuat to(const DualQuaternion& other) { + return {{other.real().vector().x(), other.real().vector().y(), other.real().vector().z(), other.real().scalar()}, + {other.dual().vector().x(), other.dual().vector().y(), other.dual().vector().z(), other.dual().scalar()}}; + } +}; + +} + +namespace Test { struct DualQuaternionTest: Corrade::TestSuite::Tester { explicit DualQuaternionTest(); @@ -37,6 +60,7 @@ struct DualQuaternionTest: Corrade::TestSuite::Tester { void constructDefault(); void constructFromVector(); void constructCopy(); + void convert(); void isNormalized(); @@ -73,6 +97,7 @@ DualQuaternionTest::DualQuaternionTest() { &DualQuaternionTest::constructDefault, &DualQuaternionTest::constructFromVector, &DualQuaternionTest::constructCopy, + &DualQuaternionTest::convert, &DualQuaternionTest::isNormalized, @@ -130,6 +155,28 @@ void DualQuaternionTest::constructCopy() { CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f})); } +void DualQuaternionTest::convert() { + constexpr DualQuat a{{1.5f, -3.5f, 7.0f, -0.5f}, {15.0f, 0.25f, -9.5f, 0.8f}}; + constexpr DualQuaternion b{{{1.5f, -3.5f, 7.0f}, -0.5f}, {{15.0f, 0.25f, -9.5f}, 0.8f}}; + + constexpr DualQuaternion c{a}; + CORRADE_COMPARE(c, b); + + constexpr DualQuat d(b); + CORRADE_COMPARE(d.re.x, a.re.x); + CORRADE_COMPARE(d.re.y, a.re.y); + CORRADE_COMPARE(d.re.z, a.re.z); + CORRADE_COMPARE(d.re.w, a.re.w); + CORRADE_COMPARE(d.du.x, a.du.x); + CORRADE_COMPARE(d.du.y, a.du.y); + CORRADE_COMPARE(d.du.z, a.du.z); + CORRADE_COMPARE(d.du.w, a.du.w); + + /* Implicit conversion is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); +} + void DualQuaternionTest::isNormalized() { CORRADE_VERIFY(!DualQuaternion({{1.0f, 2.0f, 3.0f}, 4.0f}, {}).isNormalized()); CORRADE_VERIFY((DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({3.0f, 1.0f, -0.5f})).isNormalized());