mirror of https://github.com/mosra/magnum.git
9 changed files with 427 additions and 3 deletions
@ -0,0 +1,116 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include "CapsuleRenderer.h" |
||||
|
||||
#include "MeshView.h" |
||||
#include "DebugTools/ResourceManager.h" |
||||
#include "DebugTools/ShapeRenderer.h" |
||||
#include "Primitives/Capsule.h" |
||||
#include "Shapes/Capsule.h" |
||||
#include "Shaders/Flat.h" |
||||
#include "Trade/MeshData2D.h" |
||||
#include "Trade/MeshData3D.h" |
||||
|
||||
#include "DebugTools/Implementation/CapsuleRendererTransformation.h" |
||||
|
||||
namespace Magnum { namespace DebugTools { namespace Implementation { |
||||
|
||||
AbstractCapsuleRenderer<2>::AbstractCapsuleRenderer(): AbstractShapeRenderer<2>("capsule2d", "capsule2d-vertices", "capsule2d-indices") { |
||||
constexpr UnsignedInt rings = 10; |
||||
if(!wireframeMesh) createResources(Primitives::Capsule2D::wireframe(rings, 1, 1.0f)); |
||||
|
||||
/* Bottom hemisphere */ |
||||
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule2d-bottom"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(0, rings*4, 0, rings*2+1); |
||||
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
|
||||
/* Cylinder */ |
||||
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule2d-cylinder"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(rings*4, 4, rings*2+1, rings*2+3); |
||||
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
|
||||
/* Top hemisphere */ |
||||
if(!(top = ResourceManager::instance().get<MeshView>("capsule2d-top"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(rings*4+4, rings*4, rings*2+3, rings*4+4); |
||||
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
} |
||||
|
||||
AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>("capsule3d", "capsule3d-vertices", "capsule3d-indices") { |
||||
constexpr UnsignedInt rings = 10; |
||||
constexpr UnsignedInt segments = 20; |
||||
if(!wireframeMesh) createResources(Primitives::Capsule3D::wireframe(rings, 1, segments, 1.0f)); |
||||
|
||||
/* Bottom hemisphere */ |
||||
if(!(bottom = ResourceManager::instance().get<MeshView>("capsule3d-bottom"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(0, rings*8, 0, rings*4+1); |
||||
ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
|
||||
/* Cylinder */ |
||||
if(!(cylinder = ResourceManager::instance().get<MeshView>("capsule3d-cylinder"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(rings*8, segments*4+8, rings*4+1, rings*4+segments*2+5); |
||||
ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
|
||||
/* Top */ |
||||
if(!(top = ResourceManager::instance().get<MeshView>("capsule3d-top"))) { |
||||
auto view = new MeshView(wireframeMesh); |
||||
view->setIndexRange(rings*8+segments*4+8, rings*8, rings*4+segments*2+5, rings*8+segments*2+6); |
||||
ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
} |
||||
|
||||
template<UnsignedInt dimensions> CapsuleRenderer<dimensions>::CapsuleRenderer(const Shapes::Implementation::AbstractShape<dimensions>& capsule): capsule(static_cast<const Shapes::Implementation::Shape<Shapes::Capsule<dimensions>>&>(capsule).shape) {} |
||||
|
||||
template<UnsignedInt dimensions> void CapsuleRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) { |
||||
std::array<typename DimensionTraits<dimensions, Float>::MatrixType, 3> transformations = Implementation::capsuleRendererTransformation<dimensions>(capsule.a(), capsule.b(), capsule.radius()); |
||||
AbstractShapeRenderer<dimensions>::wireframeShader->setColor(options->color()) |
||||
.use(); |
||||
|
||||
/* Bottom */ |
||||
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[0]); |
||||
AbstractCapsuleRenderer<dimensions>::bottom->draw(); |
||||
|
||||
/* Cylinder */ |
||||
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[1]); |
||||
AbstractCapsuleRenderer<dimensions>::cylinder->draw(); |
||||
|
||||
/* Top */ |
||||
AbstractShapeRenderer<dimensions>::wireframeShader->setTransformationProjectionMatrix(projectionMatrix*transformations[2]); |
||||
AbstractCapsuleRenderer<dimensions>::top->draw(); |
||||
} |
||||
|
||||
template class CapsuleRenderer<2>; |
||||
template class CapsuleRenderer<3>; |
||||
|
||||
}}} |
||||
@ -0,0 +1,66 @@
|
||||
#ifndef Magnum_DebugTools_Implementation_CapsuleRenderer_h |
||||
#define Magnum_DebugTools_Implementation_CapsuleRenderer_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include "AbstractShapeRenderer.h" |
||||
|
||||
#include "Shapes/Shapes.h" |
||||
|
||||
#include "corradeCompatibility.h" |
||||
|
||||
namespace Magnum { namespace DebugTools { namespace Implementation { |
||||
|
||||
template<UnsignedInt dimensions> class AbstractCapsuleRenderer; |
||||
|
||||
template<> class AbstractCapsuleRenderer<2>: public AbstractShapeRenderer<2> { |
||||
public: |
||||
explicit AbstractCapsuleRenderer(); |
||||
|
||||
protected: |
||||
Resource<MeshView> bottom, cylinder, top; |
||||
}; |
||||
|
||||
template<> class AbstractCapsuleRenderer<3>: public AbstractShapeRenderer<3> { |
||||
public: |
||||
explicit AbstractCapsuleRenderer(); |
||||
|
||||
protected: |
||||
Resource<MeshView> bottom, cylinder, top; |
||||
}; |
||||
|
||||
template<UnsignedInt dimensions> class CapsuleRenderer: public AbstractCapsuleRenderer<dimensions> { |
||||
public: |
||||
explicit CapsuleRenderer(const Shapes::Implementation::AbstractShape<dimensions>& capsule); |
||||
CapsuleRenderer(const Shapes::Implementation::AbstractShape<dimensions>&&) = delete; |
||||
|
||||
void draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions, Float>::MatrixType& projectionMatrix) override; |
||||
|
||||
private: |
||||
const Shapes::Capsule<dimensions>& capsule; |
||||
}; |
||||
|
||||
}}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,93 @@
|
||||
#ifndef Magnum_DebugTools_Implementation_ForceRendererTransformation_h |
||||
#define Magnum_DebugTools_Implementation_ForceRendererTransformation_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <array> |
||||
|
||||
#include "Math/Matrix3.h" |
||||
#include "Math/Matrix4.h" |
||||
#include "Magnum.h" |
||||
#include "DimensionTraits.h" |
||||
|
||||
namespace Magnum { namespace DebugTools { namespace Implementation { |
||||
|
||||
template<UnsignedInt dimensions> std::array<typename DimensionTraits<dimensions, Float>::MatrixType, 3> capsuleRendererTransformation(const typename DimensionTraits<dimensions, Float>::VectorType& a, const typename DimensionTraits<dimensions, Float>::VectorType& b, Float radius); |
||||
|
||||
template<> inline std::array<Matrix3, 3> capsuleRendererTransformation<2>(const Vector2& a, const Vector2& b, const Float radius) { |
||||
/* Vector from capsule center to top hemisphere center */ |
||||
const Vector2 direction = 0.5f*(b - a); |
||||
const Float length = direction.length(); |
||||
|
||||
/* Capsule rotation and distance to caps after they are scaled to proper
|
||||
radius (if nonzero cylinder length) */ |
||||
Matrix3 rotation; |
||||
Vector2 capDistance; |
||||
if(length >= Math::TypeTraits<Float>::epsilon()) { |
||||
rotation.up() = direction/length; |
||||
rotation.right() = rotation.up().perpendicular(); |
||||
CORRADE_INTERNAL_ASSERT(rotation.right().isNormalized()); |
||||
|
||||
capDistance = direction*(radius/length); |
||||
} |
||||
|
||||
/* Scaling and translation of all parts */ |
||||
const auto rotationScaling = rotation*Matrix3::scaling(Vector2(radius)); |
||||
return {{ |
||||
Matrix3::translation(a+capDistance)*rotationScaling, |
||||
Matrix3::translation(0.5f*(a + b))*rotation*Matrix3::scaling({radius, length}), |
||||
Matrix3::translation(b-capDistance)*rotationScaling |
||||
}}; |
||||
} |
||||
|
||||
template<> std::array<Matrix4, 3> capsuleRendererTransformation<3>(const Vector3& a, const Vector3& b, const Float radius) { |
||||
/* Vector from capsule center to top hemisphere center */ |
||||
const Vector3 direction = 0.5f*(b - a); |
||||
const Float length = direction.length(); |
||||
|
||||
/* Capsule rotation and distance to caps after they are scaled to proper
|
||||
radius (if nonzero cylinder length) */ |
||||
Matrix4 rotation; |
||||
Vector3 capDistance; |
||||
if(length >= Math::TypeTraits<Float>::epsilon()) { |
||||
rotation.up() = direction/length; |
||||
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 = direction*(radius/length); |
||||
} |
||||
|
||||
/* Scaling and translation of all parts */ |
||||
const auto rotationScaling = rotation*Matrix4::scaling(Vector3(radius)); |
||||
return {{ |
||||
Matrix4::translation(a+capDistance)*rotationScaling, |
||||
Matrix4::translation(0.5f*(a + b))*rotation*Matrix4::scaling({radius, length, radius}), |
||||
Matrix4::translation(b-capDistance)*rotationScaling |
||||
}}; |
||||
} |
||||
|
||||
}}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,137 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <TestSuite/Tester.h> |
||||
|
||||
#include "DebugTools/Implementation/CapsuleRendererTransformation.h" |
||||
|
||||
namespace Magnum { namespace DebugTools { namespace Test { |
||||
|
||||
class CapsuleRendererTest: public TestSuite::Tester { |
||||
public: |
||||
explicit CapsuleRendererTest(); |
||||
|
||||
void zeroLength2D(); |
||||
void common2D(); |
||||
|
||||
void zeroLength3D(); |
||||
void common3D(); |
||||
}; |
||||
|
||||
CapsuleRendererTest::CapsuleRendererTest() { |
||||
addTests({&CapsuleRendererTest::zeroLength2D, |
||||
&CapsuleRendererTest::common2D, |
||||
|
||||
&CapsuleRendererTest::zeroLength3D, |
||||
&CapsuleRendererTest::common3D}); |
||||
} |
||||
|
||||
void CapsuleRendererTest::zeroLength2D() { |
||||
const Vector2 a(0.5f, 3.0f); |
||||
std::array<Matrix3, 3> transformation = Implementation::capsuleRendererTransformation<2>(a, a, 3.5f); |
||||
|
||||
const auto scaling = Math::Matrix<2, Float>::fromDiagonal(Vector2(3.5f)); |
||||
CORRADE_COMPARE(transformation[0].rotationScaling(), scaling); |
||||
CORRADE_COMPARE(transformation[1].rotationScaling(), (Math::Matrix<2, Float>::fromDiagonal({3.5f, 0.0f}))); |
||||
CORRADE_COMPARE(transformation[2].rotationScaling(), scaling); |
||||
|
||||
CORRADE_COMPARE(transformation[0].translation(), a); |
||||
CORRADE_COMPARE(transformation[1].translation(), a); |
||||
CORRADE_COMPARE(transformation[2].translation(), a); |
||||
} |
||||
|
||||
void CapsuleRendererTest::common2D() { |
||||
const Vector2 a(0.5f, 3.0f); |
||||
const Vector2 b(7.5f, -1.0f); |
||||
std::array<Matrix3, 3> transformation = Implementation::capsuleRendererTransformation<2>(a, b, 3.5f); |
||||
|
||||
/* Vector from capsule center to top hemisphere center */ |
||||
const Vector2 up(3.5f, -2.0f); |
||||
CORRADE_COMPARE(transformation[0].up(), up.resized(3.5f)); |
||||
CORRADE_COMPARE(transformation[1].up(), up); |
||||
CORRADE_COMPARE(transformation[2].up(), up.resized(3.5f)); |
||||
|
||||
const Vector2 right = Vector2(4.0f, 7.0f).resized(3.5f); |
||||
CORRADE_COMPARE(transformation[0].right(), right); |
||||
CORRADE_COMPARE(transformation[1].right(), right); |
||||
CORRADE_COMPARE(transformation[2].right(), right); |
||||
|
||||
/* Orthogonality */ |
||||
CORRADE_VERIFY(Vector2::dot(transformation[0].up(), transformation[0].right()) < Math::TypeTraits<Float>::epsilon()); |
||||
|
||||
const Vector2 capDistance = up.resized(3.5f); |
||||
CORRADE_COMPARE(transformation[0].translation(), a+capDistance); |
||||
CORRADE_COMPARE(transformation[1].translation(), 0.5f*(a + b)); |
||||
CORRADE_COMPARE(transformation[2].translation(), b-capDistance); |
||||
} |
||||
|
||||
void CapsuleRendererTest::zeroLength3D() { |
||||
const Vector3 a(0.5f, 3.0f, 7.0f); |
||||
std::array<Matrix4, 3> transformation = Implementation::capsuleRendererTransformation<3>(a, a, 3.5f); |
||||
|
||||
const auto scaling = Math::Matrix<3, Float>::fromDiagonal(Vector3(3.5f)); |
||||
CORRADE_COMPARE(transformation[0].rotationScaling(), scaling); |
||||
CORRADE_COMPARE(transformation[1].rotationScaling(), (Math::Matrix<3, Float>::fromDiagonal({3.5f, 0.0f, 3.5f}))); |
||||
CORRADE_COMPARE(transformation[2].rotationScaling(), scaling); |
||||
|
||||
CORRADE_COMPARE(transformation[0].translation(), a); |
||||
CORRADE_COMPARE(transformation[1].translation(), a); |
||||
CORRADE_COMPARE(transformation[2].translation(), a); |
||||
} |
||||
|
||||
void CapsuleRendererTest::common3D() { |
||||
const Vector3 a(0.5f, 3.0f, 7.0f); |
||||
const Vector3 b(7.5f, -1.0f, 1.5f); |
||||
std::array<Matrix4, 3> transformation = Implementation::capsuleRendererTransformation<3>(a, b, 3.5f); |
||||
|
||||
/* Vector from capsule center to top hemisphere center */ |
||||
const Vector3 up(3.5f, -2.0f, -2.75f); |
||||
CORRADE_COMPARE(transformation[0].up(), up.resized(3.5f)); |
||||
CORRADE_COMPARE(transformation[1].up(), up); |
||||
CORRADE_COMPARE(transformation[2].up(), up.resized(3.5f)); |
||||
|
||||
const auto right = Vector3(-2.0f, -3.5f, 0.0f).resized(3.5f); |
||||
CORRADE_COMPARE(transformation[0].right(), right); |
||||
CORRADE_COMPARE(transformation[1].right(), right); |
||||
CORRADE_COMPARE(transformation[2].right(), right); |
||||
|
||||
const auto backward = Vector3(9.625f, -5.5f, 16.25f).resized(3.5f); |
||||
CORRADE_COMPARE(transformation[0].backward(), backward); |
||||
CORRADE_COMPARE(transformation[1].backward(), backward); |
||||
CORRADE_COMPARE(transformation[2].backward(), backward); |
||||
|
||||
/* Orthogonality */ |
||||
CORRADE_VERIFY(Vector3::dot(transformation[0].up(), transformation[0].right()) < Math::TypeTraits<Float>::epsilon()); |
||||
CORRADE_VERIFY(Vector3::dot(transformation[0].up(), transformation[0].backward()) < Math::TypeTraits<Float>::epsilon()); |
||||
CORRADE_VERIFY(Vector3::dot(transformation[0].right(), transformation[0].backward()) < Math::TypeTraits<Float>::epsilon()); |
||||
|
||||
const Vector3 capDistance = up.resized(3.5f); |
||||
CORRADE_COMPARE(transformation[0].translation(), a+capDistance); |
||||
CORRADE_COMPARE(transformation[1].translation(), 0.5f*(a + b)); |
||||
CORRADE_COMPARE(transformation[2].translation(), b-capDistance); |
||||
} |
||||
|
||||
}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::DebugTools::Test::CapsuleRendererTest) |
||||
Loading…
Reference in new issue