diff --git a/src/SceneGraph/AbstractTransformation.h b/src/SceneGraph/AbstractTransformation.h index 1717d576f..5f828a7a1 100644 --- a/src/SceneGraph/AbstractTransformation.h +++ b/src/SceneGraph/AbstractTransformation.h @@ -142,7 +142,18 @@ class MAGNUM_SCENEGRAPH_EXPORT AbstractTransformation { * @brief Reset object transformation * @return Pointer to self (for method chaining) */ - virtual AbstractTransformation* resetTransformation() = 0; + AbstractTransformation* resetTransformation() { + doResetTransformation(); + return this; + } + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @brief Polymorphic implementation for resetTransformation() */ + virtual void doResetTransformation() = 0; }; /** @brief Transformation type */ diff --git a/src/SceneGraph/AbstractTranslationRotation2D.h b/src/SceneGraph/AbstractTranslationRotation2D.h index d301fb155..1d1e48560 100644 --- a/src/SceneGraph/AbstractTranslationRotation2D.h +++ b/src/SceneGraph/AbstractTranslationRotation2D.h @@ -54,7 +54,10 @@ class AbstractTranslationRotation2D: public AbstractTransformation<2, T> { * * @see Vector2::xAxis(), Vector2::yAxis() */ - virtual AbstractTranslationRotation2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotation2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { + doTranslate(vector, type); + return this; + } /** * @brief Rotate object @@ -62,12 +65,29 @@ class AbstractTranslationRotation2D: public AbstractTransformation<2, T> { * @param type Transformation type * @return Pointer to self (for method chaining) */ - virtual AbstractTranslationRotation2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotation2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { + doRotate(angle, type); + return this; + } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - AbstractTranslationRotation2D* resetTransformation() override = 0; + AbstractTranslationRotation2D* resetTransformation() { + AbstractTransformation<2, T>::resetTransformation(); + return this; + } #endif + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @brief Polymorphic implementation for translate() */ + virtual void doTranslate(const Math::Vector2& vector, TransformationType type) = 0; + + /** @brief Polymorphic implementation for rotate() */ + virtual void doRotate(Math::Rad angle, TransformationType type) = 0; }; }} diff --git a/src/SceneGraph/AbstractTranslationRotation3D.h b/src/SceneGraph/AbstractTranslationRotation3D.h index a8355eebd..c3853efa1 100644 --- a/src/SceneGraph/AbstractTranslationRotation3D.h +++ b/src/SceneGraph/AbstractTranslationRotation3D.h @@ -55,7 +55,10 @@ class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { * * @see Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis() */ - virtual AbstractTranslationRotation3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotation3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { + doTranslate(vector, type); + return this; + } /** * @brief Rotate object @@ -67,7 +70,10 @@ class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { * @see rotateX(), rotateY(), rotateZ(), Vector3::xAxis(), * Vector3::yAxis(), Vector3::zAxis() */ - virtual AbstractTranslationRotation3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotation3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { + doRotate(angle, normalizedAxis, type); + return this; + } /** * @brief Rotate object around X axis @@ -78,8 +84,9 @@ class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { * In some implementations faster than calling * `rotate(angle, Vector3::xAxis())`. */ - virtual AbstractTranslationRotation3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { - return rotate(angle, Math::Vector3::xAxis(), type); + AbstractTranslationRotation3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { + doRotateX(angle, type); + return this; } /** @@ -91,8 +98,9 @@ class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { * In some implementations faster than calling * `rotate(angle, Vector3::yAxis())`. */ - virtual AbstractTranslationRotation3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { - return rotate(angle, Math::Vector3::yAxis(), type); + AbstractTranslationRotation3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { + doRotateX(angle, type); + return this; } /** @@ -104,14 +112,56 @@ class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { * In some implementations faster than calling * `rotate(angle, Vector3::zAxis())`. */ - virtual AbstractTranslationRotation3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { - return rotate(angle, Math::Vector3::zAxis(), type); + AbstractTranslationRotation3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { + doRotateZ(angle, type); + return this; } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - AbstractTranslationRotation3D* resetTransformation() override = 0; + AbstractTranslationRotation3D* resetTransformation() { + AbstractTransformation<2, T>::resetTransformation(); + return this; + } #endif + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @brief Polymorphic implementation for translate() */ + virtual void doTranslate(const Math::Vector3& vector, TransformationType type) = 0; + + /** @brief Polymorphic implementation for rotate() */ + virtual void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) = 0; + + /** + * @brief Polymorphic implementation for rotateX() + * + * Default implementation calls rotate() with Math::Vector3::xAxis(). + */ + virtual void doRotateX(Math::Rad angle, TransformationType type) { + rotate(angle, Math::Vector3::xAxis(), type); + } + + /** + * @brief Polymorphic implementation for rotateY() + * + * Default implementation calls rotate() with Math::Vector3::yAxis(). + */ + virtual void doRotateY(Math::Rad angle, TransformationType type) { + rotate(angle, Math::Vector3::yAxis(), type); + } + + /** + * @brief Polymorphic implementation for rotateZ() + * + * Default implementation calls rotate() with Math::Vector3::zAxis(). + */ + virtual void doRotateZ(Math::Rad angle, TransformationType type) { + rotate(angle, Math::Vector3::zAxis(), type); + } }; }} diff --git a/src/SceneGraph/AbstractTranslationRotationScaling2D.h b/src/SceneGraph/AbstractTranslationRotationScaling2D.h index 448b4617f..5f2f5cc40 100644 --- a/src/SceneGraph/AbstractTranslationRotationScaling2D.h +++ b/src/SceneGraph/AbstractTranslationRotationScaling2D.h @@ -54,14 +54,34 @@ class AbstractTranslationRotationScaling2D: public AbstractTranslationRotation2D * * @see Vector2::xScale(), Vector2::yScale() */ - virtual AbstractTranslationRotationScaling2D* scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotationScaling2D* scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { + doScale(vector, type); + return this; + } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - AbstractTranslationRotationScaling2D* resetTransformation() override = 0; - AbstractTranslationRotationScaling2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) = 0; - AbstractTranslationRotationScaling2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotationScaling2D* resetTransformation() { + AbstractTranslationRotation2D::resetTransformation(); + return this; + } + AbstractTranslationRotationScaling2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation2D::translate(vector, type); + return this; + } + AbstractTranslationRotationScaling2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation2D::rotate(angle, type); + return this; + } #endif + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @brief Polymorphic implementation for scale() */ + virtual void doScale(const Math::Vector2& vector, TransformationType type) = 0; }; }} diff --git a/src/SceneGraph/AbstractTranslationRotationScaling3D.h b/src/SceneGraph/AbstractTranslationRotationScaling3D.h index f201b40c2..2852632c4 100644 --- a/src/SceneGraph/AbstractTranslationRotationScaling3D.h +++ b/src/SceneGraph/AbstractTranslationRotationScaling3D.h @@ -54,17 +54,46 @@ class AbstractTranslationRotationScaling3D: public AbstractTranslationRotation3D * * @see Vector3::xScale(), Vector3::yScale(), Vector3::zScale() */ - virtual AbstractTranslationRotationScaling3D* scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) = 0; + AbstractTranslationRotationScaling3D* scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { + doScale(vector, type); + return this; + } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - AbstractTranslationRotationScaling3D* resetTransformation() override = 0; - AbstractTranslationRotationScaling3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) = 0; - AbstractTranslationRotationScaling3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) = 0; - AbstractTranslationRotationScaling3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) = 0; - AbstractTranslationRotationScaling3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) = 0; - AbstractTranslationRotationScaling3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) override = 0; + AbstractTranslationRotationScaling3D* resetTransformation() { + AbstractTranslationRotation3D::resetTransformation(); + return this; + } + AbstractTranslationRotationScaling3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation3D::translate(vector, type); + return this; + } + AbstractTranslationRotationScaling3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation3D::rotate(angle, normalizedAxis, type); + return this; + } + AbstractTranslationRotationScaling3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation3D::rotateX(angle, type); + return this; + } + AbstractTranslationRotationScaling3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation3D::rotateY(angle, type); + return this; + } + AbstractTranslationRotationScaling3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { + AbstractTranslationRotation3D::rotateZ(angle, type); + return this; + } #endif + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @brief Polymorphic implementation for scale() */ + virtual void doScale(const Math::Vector3& vector, TransformationType type) = 0; }; }} diff --git a/src/SceneGraph/DualComplexTransformation.h b/src/SceneGraph/DualComplexTransformation.h index 2a963dfd5..8cd00b8ff 100644 --- a/src/SceneGraph/DualComplexTransformation.h +++ b/src/SceneGraph/DualComplexTransformation.h @@ -81,9 +81,9 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { * the object subsequently. * @see DualComplex::normalized() */ - DualComplexTransformation* normalizeRotation() { + Object>* normalizeRotation() { setTransformationInternal(_transformation.normalized()); - return this; + return static_cast>*>(this); } /** @@ -93,16 +93,18 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { * Expects that the dual complex number is normalized. * @see DualComplex::isNormalized() */ - DualComplexTransformation* setTransformation(const Math::DualComplex& transformation) { + Object>* setTransformation(const Math::DualComplex& transformation) { CORRADE_ASSERT(transformation.isNormalized(), - "SceneGraph::DualComplexTransformation::setTransformation(): the dual complex number is not normalized", this); + "SceneGraph::DualComplexTransformation::setTransformation(): the dual complex number is not normalized", + static_cast>*>(this)); setTransformationInternal(transformation); - return this; + return static_cast>*>(this); } - DualComplexTransformation* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ + Object>* resetTransformation() { setTransformationInternal({}); - return this; + return static_cast>*>(this); } /** @@ -114,20 +116,21 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { * Expects that the dual complex number is normalized. * @see DualComplex::isNormalized() */ - DualComplexTransformation* transform(const Math::DualComplex& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::DualComplex& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isNormalized(), - "SceneGraph::DualComplexTransformation::transform(): the dual complex number is not normalized", this); + "SceneGraph::DualComplexTransformation::transform(): the dual complex number is not normalized", + static_cast>*>(this)); transformInternal(transformation, type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling2D::translate() * Same as calling transform() with DualComplex::translation(). */ - DualComplexTransformation* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { transformInternal(Math::DualComplex::translation(vector), type); - return this; + return static_cast>*>(this); } /** @@ -139,9 +142,9 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { * Same as calling transform() with DualComplex::rotation(). * @see normalizeRotation() */ - DualComplexTransformation* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { transformInternal(Math::DualComplex::rotation(angle), type); - return this; + return static_cast>*>(this); } /** @@ -150,9 +153,9 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { * if you want to move it above all. * @return Pointer to self (for method chaining) */ - DualComplexTransformation* move(Object>* under) { + Object>* move(Object>* under) { static_cast*>(this)->Containers::template LinkedList>>::move(this, under); - return this; + return static_cast>*>(this); } protected: @@ -160,6 +163,16 @@ class DualComplexTransformation: public AbstractTranslationRotation2D { explicit DualComplexTransformation() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector2& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, TransformationType type) override final { + doRotate(angle, type); + } + /* No assertions fired, for internal use */ void setTransformationInternal(const Math::DualComplex& transformation) { /* Setting transformation is forbidden for the scene */ diff --git a/src/SceneGraph/DualQuaternionTransformation.h b/src/SceneGraph/DualQuaternionTransformation.h index 2bcf86d27..03d3e59b9 100644 --- a/src/SceneGraph/DualQuaternionTransformation.h +++ b/src/SceneGraph/DualQuaternionTransformation.h @@ -83,9 +83,9 @@ class DualQuaternionTransformation: public AbstractTranslationRotation3D { * the object subsequently. * @see DualQuaternion::normalized() */ - DualQuaternionTransformation* normalizeRotation() { + Object>* normalizeRotation() { setTransformation(_transformation.normalized()); - return this; + return static_cast>*>(this); } /** @@ -95,16 +95,18 @@ class DualQuaternionTransformation: public AbstractTranslationRotation3D { * Expects that the dual quaternion is normalized. * @see DualQuaternion::isNormalized() */ - DualQuaternionTransformation* setTransformation(const Math::DualQuaternion& transformation) { + Object>* setTransformation(const Math::DualQuaternion& transformation) { CORRADE_ASSERT(transformation.isNormalized(), - "SceneGraph::DualQuaternionTransformation::setTransformation(): the dual quaternion is not normalized", this); + "SceneGraph::DualQuaternionTransformation::setTransformation(): the dual quaternion is not normalized", + static_cast>*>(this)); setTransformationInternal(transformation); - return this; + return static_cast>*>(this); } - DualQuaternionTransformation* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ + Object>* resetTransformation() { setTransformation({}); - return this; + return static_cast>*>(this); } /** @@ -116,20 +118,21 @@ class DualQuaternionTransformation: public AbstractTranslationRotation3D { * Expects that the dual quaternion is normalized. * @see DualQuaternion::isNormalized() */ - DualQuaternionTransformation* transform(const Math::DualQuaternion& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::DualQuaternion& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isNormalized(), - "SceneGraph::DualQuaternionTransformation::transform(): the dual quaternion is not normalized", this); + "SceneGraph::DualQuaternionTransformation::transform(): the dual quaternion is not normalized", + static_cast>*>(this)); transformInternal(transformation, type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling3D::translate() * Same as calling transform() with DualQuaternion::translation(). */ - DualQuaternionTransformation* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { transformInternal(Math::DualQuaternion::translation(vector), type); - return this; + return static_cast>*>(this); } /** @@ -143,24 +146,21 @@ class DualQuaternionTransformation: public AbstractTranslationRotation3D { * @see Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis(), * normalizeRotation() */ - DualQuaternionTransformation* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { transformInternal(Math::DualQuaternion::rotation(angle, normalizedAxis), type); - return this; + return static_cast>*>(this); } /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - DualQuaternionTransformation* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) override { - AbstractTranslationRotation3D::rotateX(angle, type); - return this; + Object>* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { + return rotate(angle, Math::Vector3::xAxis(), type); } - DualQuaternionTransformation* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) override { - AbstractTranslationRotation3D::rotateY(angle, type); - return this; + Object>* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { + return rotate(angle, Math::Vector3::yAxis(), type); } - DualQuaternionTransformation* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) override { - AbstractTranslationRotation3D::rotateZ(angle, type); - return this; + Object>* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { + return rotate(angle, Math::Vector3::zAxis(), type); } #endif @@ -169,6 +169,16 @@ class DualQuaternionTransformation: public AbstractTranslationRotation3D { explicit DualQuaternionTransformation() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector3& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) override final { + rotate(angle, normalizedAxis, type); + } + /* No assertions fired, for internal use */ void setTransformationInternal(const Math::DualQuaternion& transformation) { /* Setting transformation is forbidden for the scene */ diff --git a/src/SceneGraph/MatrixTransformation2D.h b/src/SceneGraph/MatrixTransformation2D.h index 46242c577..4f82dab87 100644 --- a/src/SceneGraph/MatrixTransformation2D.h +++ b/src/SceneGraph/MatrixTransformation2D.h @@ -76,7 +76,7 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { * @brief Set transformation * @return Pointer to self (for method chaining) */ - MatrixTransformation2D* setTransformation(const Math::Matrix3& transformation) { + Object>* setTransformation(const Math::Matrix3& 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? */ @@ -85,7 +85,7 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { static_cast>*>(this)->setDirty(); } - return this; + return static_cast>*>(this); } /** @@ -94,42 +94,43 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { * @param type Transformation type * @return Pointer to self (for method chaining) */ - MatrixTransformation2D* transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { setTransformation(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); - return this; + return static_cast>*>(this); } - MatrixTransformation2D* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ + Object>* resetTransformation() { setTransformation({}); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling2D::translate() * Same as calling transform() with Matrix3::translation(). */ - MatrixTransformation2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { transform(Math::Matrix3::translation(vector), type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling2D::rotate() * Same as calling transform() with Matrix3::rotation(). */ - MatrixTransformation2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { transform(Math::Matrix3::rotation(angle), type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling2D::scale() * Same as calling transform() with Matrix3::scaling(). */ - MatrixTransformation2D* scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) override { + Object>* scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { transform(Math::Matrix3::scaling(vector), type); - return this; + return static_cast>*>(this); } /** @@ -141,9 +142,9 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { * * Same as calling transform() with Matrix3::reflection(). */ - MatrixTransformation2D* reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { + Object>* reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { transform(Math::Matrix3::reflection(normal), type); - return this; + return static_cast>*>(this); } /** @@ -152,9 +153,9 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { * if you want to move it above all. * @return Pointer to self (for method chaining) */ - MatrixTransformation2D* move(Object>* under) { + Object>* move(Object>* under) { static_cast*>(this)->Containers::template LinkedList>>::move(this, under); - return this; + return static_cast>*>(this); } protected: @@ -162,6 +163,20 @@ class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { explicit MatrixTransformation2D() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector2& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, TransformationType type) override final { + doRotate(angle, type); + } + + void doScale(const Math::Vector2& vector, TransformationType type) override final { + scale(vector, type); + } + Math::Matrix3 _transformation; }; diff --git a/src/SceneGraph/MatrixTransformation3D.h b/src/SceneGraph/MatrixTransformation3D.h index 08c42853c..2c3527eef 100644 --- a/src/SceneGraph/MatrixTransformation3D.h +++ b/src/SceneGraph/MatrixTransformation3D.h @@ -76,7 +76,7 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * @brief Set transformation * @return Pointer to self (for method chaining) */ - MatrixTransformation3D* setTransformation(const Math::Matrix4& transformation) { + Object>* setTransformation(const Math::Matrix4& 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? */ @@ -85,12 +85,13 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { static_cast>*>(this)->setDirty(); } - return this; + return static_cast>*>(this); } - MatrixTransformation3D* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ + Object>* resetTransformation() { setTransformation({}); - return this; + return static_cast>*>(this); } /** @@ -99,28 +100,28 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * @param type Transformation type * @return Pointer to self (for method chaining) */ - MatrixTransformation3D* transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { setTransformation(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling3D::translate() * Same as calling transform() with Matrix4::translation(). */ - MatrixTransformation3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::translation(vector), type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling3D::rotate() * Same as calling transform() with Matrix4::rotation(). */ - MatrixTransformation3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::rotation(angle, normalizedAxis), type); - return this; + return static_cast>*>(this); } /** @@ -131,9 +132,9 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * * Same as calling transform() with Matrix4::rotationX(). */ - MatrixTransformation3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::rotationX(angle), type); - return this; + return static_cast>*>(this); } /** @@ -144,9 +145,9 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * * Same as calling transform() with Matrix4::rotationY(). */ - MatrixTransformation3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::rotationY(angle), type); - return this; + return static_cast>*>(this); } /** @@ -157,18 +158,18 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * * Same as calling transform() with Matrix4::rotationZ(). */ - MatrixTransformation3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::rotationZ(angle), type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling3D::scale() * Same as calling transform() with Matrix4::scaling(). */ - MatrixTransformation3D* scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) override { + Object>* scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::scaling(vector), type); - return this; + return static_cast>*>(this); } /** @@ -180,9 +181,9 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { * * Same as calling transform() with Matrix4::reflection(). */ - MatrixTransformation3D* reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { + Object>* reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { transform(Math::Matrix4::reflection(normal), type); - return this; + return static_cast>*>(this); } protected: @@ -190,6 +191,32 @@ class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { explicit MatrixTransformation3D() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector3& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) override final { + rotate(angle, normalizedAxis, type); + } + + void doRotateX(Math::Rad angle, TransformationType type) override final { + rotateX(angle, type); + } + + void doRotateY(Math::Rad angle, TransformationType type) override final { + rotateY(angle, type); + } + + void doRotateZ(Math::Rad angle, TransformationType type) override final { + rotateZ(angle, type); + } + + void doScale(const Math::Vector3& vector, TransformationType type) override final { + scale(vector, type); + } + Math::Matrix4 _transformation; }; diff --git a/src/SceneGraph/RigidMatrixTransformation2D.h b/src/SceneGraph/RigidMatrixTransformation2D.h index 0dc794349..74dd96428 100644 --- a/src/SceneGraph/RigidMatrixTransformation2D.h +++ b/src/SceneGraph/RigidMatrixTransformation2D.h @@ -84,11 +84,11 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * Normalizes the rotation part using Math::Algorithms::gramSchmidt() * to prevent rounding errors when rotating the object subsequently. */ - RigidMatrixTransformation2D* normalizeRotation() { + Object>* normalizeRotation() { setTransformationInternal(Math::Matrix3::from( Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), _transformation.translation())); - return this; + return static_cast>*>(this); } /** @@ -98,16 +98,18 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * Expects that the matrix represents rigid transformation. * @see Matrix3::isRigidTransformation() */ - RigidMatrixTransformation2D* setTransformation(const Math::Matrix3& transformation) { + Object>* setTransformation(const Math::Matrix3& transformation) { CORRADE_ASSERT(transformation.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation2D::setTransformation(): the matrix doesn't represent rigid transformation", this); + "SceneGraph::RigidMatrixTransformation2D::setTransformation(): the matrix doesn't represent rigid transformation", + static_cast>*>(this)); setTransformationInternal(transformation); - return this; + return static_cast>*>(this); } - RigidMatrixTransformation2D* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ + Object>* resetTransformation() { setTransformationInternal({}); - return this; + return static_cast>*>(this); } /** @@ -119,20 +121,21 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * Expects that the matrix represents rigid transformation. * @see Matrix3::isRigidTransformation() */ - RigidMatrixTransformation2D* transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation2D::transform(): the matrix doesn't represent rigid transformation", this); + "SceneGraph::RigidMatrixTransformation2D::transform(): the matrix doesn't represent rigid transformation", + static_cast>*>(this)); transformInternal(transformation, type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling2D::translate() * Same as calling transform() with Matrix3::translation(). */ - RigidMatrixTransformation2D* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix3::translation(vector), type); - return this; + return static_cast>*>(this); } /** @@ -144,9 +147,9 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * Same as calling transform() with Matrix3::rotation(). * @see normalizeRotation() */ - RigidMatrixTransformation2D* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix3::rotation(angle), type); - return this; + return static_cast>*>(this); } /** @@ -158,9 +161,9 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * * Same as calling transform() with Matrix3::reflection(). */ - RigidMatrixTransformation2D* reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { + Object>* reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix3::reflection(normal), type); - return this; + return static_cast>*>(this); } /** @@ -169,9 +172,9 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { * if you want to move it above all. * @return Pointer to self (for method chaining) */ - RigidMatrixTransformation2D* move(Object>* under) { + Object>* move(Object>* under) { static_cast*>(this)->Containers::template LinkedList>>::move(this, under); - return this; + return static_cast>*>(this); } protected: @@ -179,6 +182,16 @@ class RigidMatrixTransformation2D: public AbstractTranslationRotation2D { explicit RigidMatrixTransformation2D() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector2& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, TransformationType type) override final { + doRotate(angle, type); + } + /* No assertions fired, for internal use */ void setTransformationInternal(const Math::Matrix3& transformation) { /* Setting transformation is forbidden for the scene */ diff --git a/src/SceneGraph/RigidMatrixTransformation3D.h b/src/SceneGraph/RigidMatrixTransformation3D.h index 7ca937c71..1d13702e4 100644 --- a/src/SceneGraph/RigidMatrixTransformation3D.h +++ b/src/SceneGraph/RigidMatrixTransformation3D.h @@ -84,11 +84,11 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Normalizes the rotation part using Math::Algorithms::gramSchmidt() * to prevent rounding errors when rotating the object subsequently. */ - RigidMatrixTransformation3D* normalizeRotation() { + Object>* normalizeRotation() { setTransformation(Math::Matrix4::from( Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), _transformation.translation())); - return this; + return static_cast>*>(this); } /** @@ -98,16 +98,18 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Expects that the matrix represents rigid transformation. * @see Matrix4::isRigidTransformation() */ - RigidMatrixTransformation3D* setTransformation(const Math::Matrix4& transformation) { + Object>* setTransformation(const Math::Matrix4& transformation) { CORRADE_ASSERT(transformation.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation3D::setTransformation(): the matrix doesn't represent rigid transformation", this); + "SceneGraph::RigidMatrixTransformation3D::setTransformation(): the matrix doesn't represent rigid transformation", + static_cast>*>(this)); setTransformationInternal(transformation); - return this; + return static_cast>*>(this); } - RigidMatrixTransformation3D* resetTransformation() override { + /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ + Object>* resetTransformation() { setTransformation({}); - return this; + return static_cast>*>(this); } /** @@ -119,20 +121,21 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Expects that the matrix represents rigid transformation. * @see Matrix4::isRigidTransformation() */ - RigidMatrixTransformation3D* transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { + Object>* transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { CORRADE_ASSERT(transformation.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation3D::transform(): the matrix doesn't represent rigid transformation", this); + "SceneGraph::RigidMatrixTransformation3D::transform(): the matrix doesn't represent rigid transformation", + static_cast>*>(this)); transformInternal(transformation, type); - return this; + return static_cast>*>(this); } /** * @copydoc AbstractTranslationRotationScaling3D::translate() * Same as calling transform() with Matrix4::translation(). */ - RigidMatrixTransformation3D* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) override { + Object>* translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::translation(vector), type); - return this; + return static_cast>*>(this); } /** @@ -146,9 +149,9 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * @see rotateX(), rotateY(), rotateZ(), Vector3::xAxis(), * Vector3::yAxis(), Vector3::zAxis(), normalizeRotation() */ - RigidMatrixTransformation3D* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) override { + Object>* rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::rotation(angle, normalizedAxis), type); - return this; + return static_cast>*>(this); } /** @@ -160,9 +163,9 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Same as calling transform() with Matrix4::rotationX(). * @see normalizeRotation() */ - RigidMatrixTransformation3D* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::rotationX(angle), type); - return this; + return static_cast>*>(this); } /** @@ -174,9 +177,9 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Same as calling transform() with Matrix4::rotationY(). * @see normalizeRotation() */ - RigidMatrixTransformation3D* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::rotationY(angle), type); - return this; + return static_cast>*>(this); } /** @@ -188,9 +191,9 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * Same as calling transform() with Matrix4::rotationZ(). * @see normalizeRotation() */ - RigidMatrixTransformation3D* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) override { + Object>* rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::rotationZ(angle), type); - return this; + return static_cast>*>(this); } /** @@ -202,9 +205,9 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { * * Same as calling transform() with Matrix4::reflection(). */ - RigidMatrixTransformation3D* reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { + Object>* reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { transformInternal(Math::Matrix4::reflection(normal), type); - return this; + return static_cast>*>(this); } protected: @@ -212,6 +215,28 @@ class RigidMatrixTransformation3D: public AbstractTranslationRotation3D { explicit RigidMatrixTransformation3D() = default; private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const Math::Vector3& vector, TransformationType type) override final { + translate(vector, type); + } + + void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) override final { + rotate(angle, normalizedAxis, type); + } + + void doRotateX(Math::Rad angle, TransformationType type) override final { + rotateX(angle, type); + } + + void doRotateY(Math::Rad angle, TransformationType type) override final { + rotateY(angle, type); + } + + void doRotateZ(Math::Rad angle, TransformationType type) override final { + rotateZ(angle, type); + } + /* No assertions fired, for internal use */ void setTransformationInternal(const Math::Matrix4& transformation) { /* Setting transformation is forbidden for the scene */