From b5a2cb6b1123f5a66c0d2fa96371822fa16ece63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 20 Aug 2013 00:20:32 +0200 Subject: [PATCH] DebugTools: properly implemented special cases for CapsuleRenderer. --- .../CapsuleRendererTransformation.h | 20 ++++++++-- src/DebugTools/Test/CapsuleRendererTest.cpp | 40 +++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/DebugTools/Implementation/CapsuleRendererTransformation.h b/src/DebugTools/Implementation/CapsuleRendererTransformation.h index 4886d3578..5f9271a67 100644 --- a/src/DebugTools/Implementation/CapsuleRendererTransformation.h +++ b/src/DebugTools/Implementation/CapsuleRendererTransformation.h @@ -26,6 +26,7 @@ #include +#include "Math/Functions.h" #include "Math/Matrix3.h" #include "Math/Matrix4.h" #include "Magnum.h" @@ -72,10 +73,21 @@ template<> std::array capsuleRendererTransformation<3>(const Vector3 Vector3 capDistance; if(length >= Math::TypeTraits::epsilon()) { const Vector3 directionNormalized = direction/length; - rotation.up() = directionNormalized; - rotation.right() = Vector3::cross(rotation.up(), Vector3::zAxis()).normalized(); - rotation.backward() = Vector3::cross(rotation.right(), rotation.up()); - CORRADE_INTERNAL_ASSERT(rotation.up().isNormalized() && rotation.backward().isNormalized()); + const Float dot = Vector3::dot(directionNormalized, Vector3::zAxis()); + + /* Direction is parallel to Z axis, special rotation case */ + if(Math::abs(dot) > 1.0f - Math::TypeTraits::epsilon()) { + rotation.up() = dot*Vector3::zAxis(); + rotation.right() = Vector3::xAxis(); + rotation.backward() = -dot*Vector3::yAxis(); + + /* Common case */ + } else { + rotation.up() = directionNormalized; + rotation.right() = Vector3::cross(rotation.up(), Vector3::zAxis()).normalized(); + rotation.backward() = Vector3::cross(rotation.right(), rotation.up()); + CORRADE_INTERNAL_ASSERT(rotation.up().isNormalized() && rotation.backward().isNormalized()); + } capDistance = directionNormalized*radius; } diff --git a/src/DebugTools/Test/CapsuleRendererTest.cpp b/src/DebugTools/Test/CapsuleRendererTest.cpp index 06900d664..4c0f7d762 100644 --- a/src/DebugTools/Test/CapsuleRendererTest.cpp +++ b/src/DebugTools/Test/CapsuleRendererTest.cpp @@ -36,6 +36,8 @@ class CapsuleRendererTest: public TestSuite::Tester { void common2D(); void zeroLength3D(); + void parallel3D(); + void antiParallel3D(); void common3D(); }; @@ -44,6 +46,8 @@ CapsuleRendererTest::CapsuleRendererTest() { &CapsuleRendererTest::common2D, &CapsuleRendererTest::zeroLength3D, + &CapsuleRendererTest::parallel3D, + &CapsuleRendererTest::antiParallel3D, &CapsuleRendererTest::common3D}); } @@ -100,6 +104,42 @@ void CapsuleRendererTest::zeroLength3D() { CORRADE_COMPARE(transformation[2].translation(), a); } +void CapsuleRendererTest::parallel3D() { + const Vector3 a(0.5f, 3.0f, 7.0f); + const Vector3 b(0.5f, 3.0f, 11.0f); + std::array transformation = Implementation::capsuleRendererTransformation<3>(a, b, 3.5f); + + const auto rotation = Matrix4::rotationX(Deg(90.0f)); + const auto scaling = (rotation*Matrix4::scaling(Vector3(3.5f))).rotationScaling(); + CORRADE_COMPARE(transformation[0].rotationScaling(), scaling); + CORRADE_COMPARE(transformation[1].rotationScaling(), + (rotation*Matrix4::scaling({3.5f, 2.0f, 3.5f})).rotationScaling()); + CORRADE_COMPARE(transformation[2].rotationScaling(), scaling); + + const auto capDistance = Vector3::zAxis(3.5f); + CORRADE_COMPARE(transformation[0].translation(), a+capDistance); + CORRADE_COMPARE(transformation[1].translation(), a+Vector3::zAxis(2.0f)); + CORRADE_COMPARE(transformation[2].translation(), b-capDistance); +} + +void CapsuleRendererTest::antiParallel3D() { + const Vector3 a(0.5f, 3.0f, 7.0f); + const Vector3 b(0.5f, 3.0f, 3.0f); + std::array transformation = Implementation::capsuleRendererTransformation<3>(a, b, 3.5f); + + const auto rotation = Matrix4::rotationX(-Deg(90.0f)); + const auto rotationScaling = (rotation*Matrix4::scaling(Vector3(3.5f))).rotationScaling(); + CORRADE_COMPARE(transformation[0].rotationScaling(), rotationScaling); + CORRADE_COMPARE(transformation[1].rotationScaling(), + (rotation*Matrix4::scaling({3.5f, 2.0f, 3.5f})).rotationScaling()); + CORRADE_COMPARE(transformation[2].rotationScaling(), rotationScaling); + + const auto capDistance = Vector3::zAxis(-3.5f); + CORRADE_COMPARE(transformation[0].translation(), a+capDistance); + CORRADE_COMPARE(transformation[1].translation(), a+Vector3::zAxis(-2.0f)); + CORRADE_COMPARE(transformation[2].translation(), b-capDistance); +} + void CapsuleRendererTest::common3D() { const Vector3 a(0.5f, 3.0f, 7.0f); const Vector3 b(7.5f, -1.0f, 1.5f);