From a7f77f41b98c34fe73cd77945bb4a28c9ea95483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 14 Oct 2013 20:30:40 +0200 Subject: [PATCH] SceneGraph: new TranslationTransformation class. Translation-only transformation, supports also integer coordinates. --- src/SceneGraph/CMakeLists.txt | 1 + src/SceneGraph/Object.h | 2 + src/SceneGraph/SceneGraph.h | 11 + src/SceneGraph/Test/CMakeLists.txt | 2 + .../Test/TranslationTransformationTest.cpp | 146 ++++++++++++ src/SceneGraph/TranslationTransformation.h | 207 ++++++++++++++++++ src/SceneGraph/instantiation.cpp | 3 + 7 files changed, 372 insertions(+) create mode 100644 src/SceneGraph/Test/TranslationTransformationTest.cpp create mode 100644 src/SceneGraph/TranslationTransformation.h diff --git a/src/SceneGraph/CMakeLists.txt b/src/SceneGraph/CMakeLists.txt index 56b097090..32b018ceb 100644 --- a/src/SceneGraph/CMakeLists.txt +++ b/src/SceneGraph/CMakeLists.txt @@ -63,6 +63,7 @@ set(MagnumSceneGraph_HEADERS Object.hpp Scene.h SceneGraph.h + TranslationTransformation.h magnumSceneGraphVisibility.h) diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 75bd939fc..277edfee9 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -85,6 +85,8 @@ See @ref compilation-speedup-hpp for more information. - @ref MatrixTransformation3D "Object>" - @ref RigidMatrixTransformation2D "Object>" - @ref RigidMatrixTransformation3D "Object>" + - @ref TranslationTransformation2D "Object>" + - @ref TranslationTransformation3D "Object>" @see Scene, AbstractFeature, AbstractTransformation, DebugTools::ObjectRenderer */ diff --git a/src/SceneGraph/SceneGraph.h b/src/SceneGraph/SceneGraph.h index 2dd49f622..8d5b73043 100644 --- a/src/SceneGraph/SceneGraph.h +++ b/src/SceneGraph/SceneGraph.h @@ -191,6 +191,17 @@ typedef BasicRigidMatrixTransformation3D RigidMatrixTransformation3D; template class Scene; +template class TranslationTransformation; +#ifndef CORRADE_GCC46_COMPATIBILITY +template using BasicTranslationTransformation2D = TranslationTransformation<2, T, TranslationType>; +template using BasicTranslationTransformation3D = TranslationTransformation<3, T, TranslationType>; +typedef BasicTranslationTransformation2D TranslationTransformation2D; +typedef BasicTranslationTransformation3D TranslationTransformation3D; +#else +typedef TranslationTransformation<2, Float> TranslationTransformation2D; +typedef TranslationTransformation<3, Float> TranslationTransformation3D; +#endif + }} #endif diff --git a/src/SceneGraph/Test/CMakeLists.txt b/src/SceneGraph/Test/CMakeLists.txt index 902c2f283..0ba37c03a 100644 --- a/src/SceneGraph/Test/CMakeLists.txt +++ b/src/SceneGraph/Test/CMakeLists.txt @@ -32,9 +32,11 @@ corrade_add_test(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphT corrade_add_test(SceneGraphRigidMatrixTrans___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphRigidMatrixTrans___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph) +corrade_add_test(SceneGraphTranslationTransfo___Test TranslationTransformationTest.cpp LIBRARIES MagnumSceneGraph) set_target_properties(SceneGraphDualComplexTransfo___Test SceneGraphDualQuaternionTran___Test SceneGraphRigidMatrixTrans___2DTest SceneGraphRigidMatrixTrans___3DTest + SceneGraphTranslationTransfo___Test PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT") diff --git a/src/SceneGraph/Test/TranslationTransformationTest.cpp b/src/SceneGraph/Test/TranslationTransformationTest.cpp new file mode 100644 index 000000000..018f64fae --- /dev/null +++ b/src/SceneGraph/Test/TranslationTransformationTest.cpp @@ -0,0 +1,146 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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 +#include + +#include "SceneGraph/TranslationTransformation.h" +#include "SceneGraph/Scene.h" + +/* For Object2Di */ +#include "SceneGraph/Object.hpp" + +namespace Magnum { namespace SceneGraph { namespace Test { + +typedef Object Object2D; +typedef Scene Scene2D; + +class TranslationTransformationTest: public TestSuite::Tester { + public: + explicit TranslationTransformationTest(); + + void fromMatrix(); + void toMatrix(); + void compose(); + void inverted(); + + void setTransformation(); + void resetTransformation(); + void transform(); + void translate(); + + void integral(); +}; + +TranslationTransformationTest::TranslationTransformationTest() { + addTests({&TranslationTransformationTest::fromMatrix, + &TranslationTransformationTest::toMatrix, + &TranslationTransformationTest::compose, + &TranslationTransformationTest::inverted, + + &TranslationTransformationTest::setTransformation, + &TranslationTransformationTest::resetTransformation, + &TranslationTransformationTest::transform, + &TranslationTransformationTest::translate, + + &TranslationTransformationTest::integral}); +} + +void TranslationTransformationTest::fromMatrix() { + std::ostringstream o; + Error::setOutput(&o); + Implementation::Transformation::fromMatrix(Matrix3::scaling(Vector2(4.0f))); + CORRADE_COMPARE(o.str(), "SceneGraph::TranslationTransformation: the matrix doesn't represent pure translation\n"); + + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(Matrix3::translation(v)), v); +} + +void TranslationTransformationTest::toMatrix() { + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(v), Matrix3::translation(v)); +} + +void TranslationTransformationTest::compose() { + const Vector2 parent(-0.5f, 2.0f); + const Vector2 child(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), Vector2(0.5f, 1.7f)); +} + +void TranslationTransformationTest::inverted() { + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::inverted(v), Vector2(-1.0f, 0.3f)); +} + +void TranslationTransformationTest::setTransformation() { + Object2D o; + + /* Dirty after setting transformation */ + o.setClean(); + CORRADE_VERIFY(!o.isDirty()); + o.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(o.isDirty()); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({1.0f, -0.3f})); + + /* Scene cannot be transformed */ + Scene2D s; + s.setClean(); + s.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(!s.isDirty()); + CORRADE_COMPARE(s.transformationMatrix(), Matrix3()); +} + +void TranslationTransformationTest::resetTransformation() { + Object2D o; + o.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(o.transformationMatrix() != Matrix3()); + o.resetTransformation(); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3()); +} + +void TranslationTransformationTest::transform() { + Object2D o; + o.setTransformation({1.0f, -0.3f}) + .transform({-0.5f, 2.0f}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({0.5f, 1.7f})); +} + +void TranslationTransformationTest::translate() { + Object2D o; + o.setTransformation({1.0f, -0.3f}) + .translate({-0.5f, 2.0f}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({1.0f, -0.3f})*Matrix3::translation({-0.5f, 2.0f})); +} + +void TranslationTransformationTest::integral() { + typedef Object> Object2Di; + + Object2Di o; + o.translate({3, -7}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({3, -7})); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::TranslationTransformationTest) diff --git a/src/SceneGraph/TranslationTransformation.h b/src/SceneGraph/TranslationTransformation.h new file mode 100644 index 000000000..182078cdf --- /dev/null +++ b/src/SceneGraph/TranslationTransformation.h @@ -0,0 +1,207 @@ +#ifndef Magnum_SceneGraph_TranslationTransformation_h +#define Magnum_SceneGraph_TranslationTransformation_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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. +*/ + +/** @file + * @brief Class @ref Magnum::SceneGraph::TranslationTransformation, alias @ref Magnum::SceneGraph::BasicTranslationTransformation2D, @ref Magnum::SceneGraph::BasicTranslationTransformation3D, typedef @ref Magnum::SceneGraph::TranslationTransformation2D, @ref Magnum::SceneGraph::BasicTranslationTransformation3D + */ + +#include "Math/Matrix3.h" +#include "Math/Matrix4.h" +#include "SceneGraph/AbstractTranslation.h" +#include "SceneGraph/Object.h" + +namespace Magnum { namespace SceneGraph { + +/** +@brief Translation-only transformation + +Uses @ref Math::Vector2 or @ref Math::Vector3 as underlying type. By default +the translation is stored with the same underlying type as resulting +transformation matrix, but it's possible to store translation in e.g. integral +coordinates while having floating-point transformation matrix. + +Note that translation is commutative, so all @ref TransformationType parameters +have no effect and are included only for compatibility with other +transformation implementations. + +@see @ref BasicTranslationTransformation2D, @ref BasicTranslationTransformation3D, + @ref TranslationTransformation2D, @ref TranslationTransformation3D, + @ref scenegraph +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class TranslationTransformation: public AbstractTranslation { + public: + /** @brief Underlying transformation type */ + typedef typename DimensionTraits::VectorType DataType; + + /** @brief Object transformation */ + typename DimensionTraits::VectorType transformation() const { return _transformation; } + + /** + * @brief Set transformation + * @return Reference to self (for method chaining) + */ + Object>& setTransformation(const typename DimensionTraits::VectorType& transformation) { + /* Setting transformation is forbidden for the scene */ + /** @todo Assert for this? */ + /** @todo Do this in some common code so we don't need to include Object? */ + if(!static_cast>*>(this)->isScene()) { + _transformation = transformation; + static_cast>*>(this)->setDirty(); + } + + return static_cast>&>(*this); + } + + /** @copydoc AbstractTranslation::resetTransformation() */ + Object>& resetTransformation() { + return setTransformation({}); + } + + /** + * @brief Add transformation + * @param transformation Transformation + * @return Reference to self (for method chaining) + * + * Equivalent to @ref translate(), provided only for compatibility with + * other implementations. + */ + Object>& transform(const typename DimensionTraits::VectorType& transformation, TransformationType = TransformationType::Global) { + return translate(transformation); + } + + /** + * @brief Translate object + * @param vector Translation vector + * @return Reference to self (for method chaining) + * + * @see @ref Vector2::xAxis(), @ref Vector2::yAxis(), @ref Vector3::xAxis(), + * @ref Vector3::yAxis(), @ref Vector3::zAxis() + */ + Object>& translate(const typename DimensionTraits::VectorType& vector, TransformationType = TransformationType::Global) { + _transformation += vector; + return static_cast>&>(*this); + } + + private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const typename DimensionTraits::VectorType& vector, TransformationType) override final { + translate(vector); + } + + typename DimensionTraits::VectorType _transformation; +}; + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for two-dimensional scenes supporting translation + +Convenience alternative to %TranslationTransformation<2, T, TranslationType>. +See @ref TranslationTransformation for more information. +@note Not available on GCC < 4.7. Use %TranslationTransformation<2, T, TranslationType> + instead. +@see @ref TranslationTransformation2D, @ref BasicTranslationTransformation3D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +using BasicTranslationTransformation2D = TranslationTransformation<2, T, TranslationType>; +#endif + +/** +@brief Base transformation for two-dimensional float scenes supporting translation + +@see @ref TranslationTransformation3D +*/ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef BasicTranslationTransformation2D TranslationTransformation2D; +#else +typedef TranslationTransformation<2, Float> TranslationTransformation2D; +#endif + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for three-dimensional scenes supporting translation + +Convenience alternative to %TranslationTransformation<3, T, TranslationType>. +See @ref TranslationTransformation for more information. +@note Not available on GCC < 4.7. Use %TranslationTransformation<3, T, TranslationType> + instead. +@see @ref TranslationTransformation3D, @ref BasicTranslationTransformation2D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +using BasicTranslationTransformation3D = TranslationTransformation<3, T, TranslationType>; +#endif + +/** +@brief Base transformation for three-dimensional float scenes supporting translation + +@see @ref TranslationTransformation2D +*/ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef BasicTranslationTransformation3D TranslationTransformation3D; +#else +typedef TranslationTransformation<3, Float> TranslationTransformation3D; +#endif + +namespace Implementation { + +template struct Transformation> { + static typename DimensionTraits::VectorType fromMatrix(const typename DimensionTraits::MatrixType& matrix) { + CORRADE_ASSERT((matrix.rotationScaling() == Math::Matrix()), + "SceneGraph::TranslationTransformation: the matrix doesn't represent pure translation", {}); + return typename DimensionTraits::VectorType(matrix.translation()); + } + + constexpr static typename DimensionTraits::MatrixType toMatrix(const typename DimensionTraits::VectorType& transformation) { + return DimensionTraits::MatrixType::translation(typename DimensionTraits::VectorType(transformation)); + } + + static typename DimensionTraits::VectorType compose(const typename DimensionTraits::VectorType& parent, const typename DimensionTraits::VectorType& child) { + return parent+child; + } + + static typename DimensionTraits::VectorType inverted(const typename DimensionTraits::VectorType& transformation) { + return -transformation; + } +}; + +} + +}} + +#endif diff --git a/src/SceneGraph/instantiation.cpp b/src/SceneGraph/instantiation.cpp index 4f589bdbe..b0648c0f8 100644 --- a/src/SceneGraph/instantiation.cpp +++ b/src/SceneGraph/instantiation.cpp @@ -33,6 +33,7 @@ #include "SceneGraph/Object.hpp" #include "SceneGraph/RigidMatrixTransformation2D.h" #include "SceneGraph/RigidMatrixTransformation3D.h" +#include "SceneGraph/TranslationTransformation.h" namespace Magnum { namespace SceneGraph { @@ -58,6 +59,8 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object>; template class MAGNUM_SCENEGRAPH_EXPORT Object>; template class MAGNUM_SCENEGRAPH_EXPORT Object>; +template class MAGNUM_SCENEGRAPH_EXPORT Object>; +template class MAGNUM_SCENEGRAPH_EXPORT Object>; #endif }}