diff --git a/src/SceneGraph/AbstractCamera.hpp b/src/SceneGraph/AbstractCamera.hpp index d09bc894d..56f5c767f 100644 --- a/src/SceneGraph/AbstractCamera.hpp +++ b/src/SceneGraph/AbstractCamera.hpp @@ -88,7 +88,7 @@ template void AbstractCamera::se } template void AbstractCamera::draw(DrawableGroup& group) { - AbstractObject* scene = AbstractFeature::object()->sceneObject(); + AbstractObject* scene = AbstractFeature::object()->scene(); CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", ); /* Compute camera matrix */ diff --git a/src/SceneGraph/AbstractObject.h b/src/SceneGraph/AbstractObject.h index ae1ce7440..5bea28b75 100644 --- a/src/SceneGraph/AbstractObject.h +++ b/src/SceneGraph/AbstractObject.h @@ -56,10 +56,10 @@ for(AbstractFeature* feature = o->firstFeature(); feature; feature = feature->ne @see AbstractObject2D, AbstractObject3D */ -#ifndef DOXYGEN_GENERATING_OUTPUT -template class MAGNUM_SCENEGRAPH_EXPORT AbstractObject: private Containers::LinkedList> -#else +#ifdef DOXYGEN_GENERATING_OUTPUT template class AbstractObject +#else +template class MAGNUM_SCENEGRAPH_EXPORT AbstractObject: private Containers::LinkedList> #endif { friend class Containers::LinkedList>; @@ -99,17 +99,13 @@ template class AbstractObject } /** - * @brief %Scene object - * @return Root object which is also scene or `nullptr`, if the object - * is not part of any scene. - * - * @todo Rename to scene() when I fully understand and fix covariant - * return issues. + * @brief %Scene + * @return %Scene or `nullptr`, if the object is not part of any scene. */ - virtual AbstractObject* sceneObject() = 0; + AbstractObject* scene() { return doScene(); } /** @overload */ - virtual const AbstractObject* sceneObject() const = 0; + const AbstractObject* scene() const { return doScene(); } /** @{ @name Object transformation */ @@ -118,14 +114,18 @@ template class AbstractObject * * @see Object::transformation() */ - virtual typename DimensionTraits::MatrixType transformationMatrix() const = 0; + typename DimensionTraits::MatrixType transformationMatrix() const { + return doTransformationMatrix(); + } /** * @brief Transformation matrix relative to root object * * @see Object::absoluteTransformation() */ - virtual typename DimensionTraits::MatrixType absoluteTransformationMatrix() const = 0; + typename DimensionTraits::MatrixType absoluteTransformationMatrix() const { + return doAbsoluteTransformationMatrix(); + } /** * @brief Transformation matrices of given set of objects relative to this object @@ -133,10 +133,12 @@ template class AbstractObject * All transformations are premultiplied with @p initialTransformationMatrix, * if specified. * @warning This function cannot check if all objects are of the same - * Object type, use typesafe Object::transformations() when + * Object type, use typesafe Object::transformationMatrices() when * possible. */ - virtual std::vector::MatrixType> transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix = (typename DimensionTraits::MatrixType())) const = 0; + std::vector::MatrixType> transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix = (typename DimensionTraits::MatrixType())) const { + return doTransformationMatrices(objects, initialTransformationMatrix); + } /*@}*/ @@ -146,6 +148,18 @@ template class AbstractObject * See @ref scenegraph-caching for more information. */ + /** + * @brief Clean absolute transformations of given set of objects + * + * Only dirty objects in the list are cleaned. + * @warning This function cannot check if all objects are of the same + * Object type, use typesafe Object::setClean() when possible. + */ + static void setClean(const std::vector*>& objects) { + if(objects.empty()) return; + objects.front()->doSetClean(objects); + } + /** * @brief Whether absolute transformation is dirty * @@ -156,7 +170,7 @@ template class AbstractObject * * @see @ref scenegraph-caching */ - virtual bool isDirty() const = 0; + bool isDirty() const { return doIsDirty(); } /** * @brief Set object absolute transformation as dirty @@ -167,7 +181,7 @@ template class AbstractObject * function does nothing. * @see @ref scenegraph-caching, setClean(), isDirty() */ - virtual void setDirty() = 0; + void setDirty() { doSetDirty(); } /** * @brief Clean object absolute transformation @@ -182,19 +196,22 @@ template class AbstractObject * each object individually. * @see @ref scenegraph-caching, setDirty(), isDirty() */ - virtual void setClean() = 0; - - /** - * @brief Clean absolute transformations of given set of objects - * - * Only dirty objects in the list are cleaned. - * @warning This function cannot check if all objects are of the same - * Object type, use typesafe Object::setClean(const std::vector& objects) when - * possible. - */ - virtual void setClean(const std::vector*>& objects) const = 0; + void setClean() { doSetClean(); } /*@}*/ + + private: + virtual AbstractObject* doScene() = 0; + virtual const AbstractObject* doScene() const = 0; + + virtual typename DimensionTraits::MatrixType doTransformationMatrix() const = 0; + virtual typename DimensionTraits::MatrixType doAbsoluteTransformationMatrix() const = 0; + virtual std::vector::MatrixType> doTransformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix) const = 0; + + virtual bool doIsDirty() const = 0; + virtual void doSetDirty() = 0; + virtual void doSetClean() = 0; + virtual void doSetClean(const std::vector*>& objects) = 0; }; #ifndef CORRADE_GCC46_COMPATIBILITY diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 8757c8ab6..96022f1cc 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -104,15 +104,6 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs #endif public: - /** - * @brief Clean absolute transformations of given set of objects - * - * Only dirty objects in the list are cleaned. - * @see setClean(), AbstractObject::setClean() - */ - /* `objects` passed by copy intentionally (to avoid copy internally) */ - static void setClean(std::vector*> objects); - /** * @brief Constructor * @param parent Parent object @@ -127,7 +118,7 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs * Removes itself from parent's children list and destroys all own * children. */ - virtual ~Object() {} + ~Object(); /** * @{ @name Scene hierarchy @@ -135,17 +126,9 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs * See @ref scenegraph-hierarchy for more information. */ - /** @brief Whether this object is scene */ - virtual bool isScene() const { return false; } - - /** - * @brief %Scene - * @return %Scene or `nullptr`, if the object is not part of any scene. - */ + /** @copydoc AbstractObject::scene() */ Scene* scene(); - - /** @overload */ - const Scene* scene() const; + const Scene* scene() const; /**< @overload */ /** @brief Parent object or `nullptr`, if this is root object */ Object* parent() { @@ -223,11 +206,21 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs /** @{ @name Object transformation */ - typename DimensionTraits::MatrixType transformationMatrix() const override { + /** + * @brief Transformation matrix + * + * @see transformation() + */ + typename DimensionTraits::MatrixType transformationMatrix() const { return Transformation::toMatrix(Transformation::transformation()); } - typename DimensionTraits::MatrixType absoluteTransformationMatrix() const override { + /** + * @brief Transformation matrix relative to root object + * + * @see absoluteTransformation() + */ + typename DimensionTraits::MatrixType absoluteTransformationMatrix() const { return Transformation::toMatrix(absoluteTransformation()); } @@ -238,12 +231,21 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs */ typename Transformation::DataType absoluteTransformation() const; + /** + * @brief Transformation matrices of given set of objects relative to this object + * + * All transformations are premultiplied with @p initialTransformationMatrix, + * if specified. + * @see transformations() + */ + std::vector::MatrixType> transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix = (typename DimensionTraits::MatrixType())) const; + /** * @brief Transformations of given group of objects relative to this object * * All transformations can be premultiplied with @p initialTransformation, * if specified. - * @see AbstractObject::transformationMatrices() + * @see transformationMatrices() */ /* `objects` passed by copy intentionally (to allow move from transformationMatrices() and avoid copy in the function itself) */ @@ -251,19 +253,56 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs /*@}*/ - bool isDirty() const override { return !!(flags & Flag::Dirty); } - void setDirty() override; - void setClean() override; + /** + * @{ @name Transformation caching + * + * See @ref scenegraph-caching for more information. + */ + + /** + * @brief Clean absolute transformations of given set of objects + * + * Only dirty objects in the list are cleaned. + * @see setClean() + */ + /* `objects` passed by copy intentionally (to avoid copy internally) */ + static void setClean(std::vector*> objects); + + /** @copydoc AbstractObject::isDirty() */ + bool isDirty() const { return !!(flags & Flag::Dirty); } + + /** @copydoc AbstractObject::setDirty() */ + void setDirty(); + + /** @copydoc AbstractObject::setClean() */ + void setClean(); + + /*@}*/ + + #ifndef DOXYGEN_GENERATING_OUTPUT + public: + virtual bool isScene() const { return false; } + #endif private: - Object* sceneObject() override; - const Object* sceneObject() const override; + Object* doScene() override final; + const Object* doScene() const override final; + + typename DimensionTraits::MatrixType MAGNUM_SCENEGRAPH_LOCAL doTransformationMatrix() const override final { + return transformationMatrix(); + } + typename DimensionTraits::MatrixType MAGNUM_SCENEGRAPH_LOCAL doAbsoluteTransformationMatrix() const override final { + return absoluteTransformationMatrix(); + } - std::vector::MatrixType> transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix = (typename DimensionTraits::MatrixType())) const override; + std::vector::MatrixType> doTransformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix) const override final; typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector*>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const; - void setClean(const std::vector*>& objects) const override; + bool doIsDirty() const override final { return isDirty(); } + void doSetDirty() override final { setDirty(); } + void doSetClean() override final { setClean(); } + void doSetClean(const std::vector*>& objects) override final; void MAGNUM_SCENEGRAPH_LOCAL setClean(const typename Transformation::DataType& absoluteTransformation); diff --git a/src/SceneGraph/Object.hpp b/src/SceneGraph/Object.hpp index afd86f07c..950814a70 100644 --- a/src/SceneGraph/Object.hpp +++ b/src/SceneGraph/Object.hpp @@ -44,24 +44,26 @@ template AbstractObject::~Abstra template AbstractTransformation::AbstractTransformation() {} template AbstractTransformation::~AbstractTransformation() {} +template Object::~Object() = default; + template Scene* Object::scene() { - return static_cast*>(sceneObject()); + Object* p(this); + while(p && !p->isScene()) p = p->parent(); + return static_cast*>(p); } template const Scene* Object::scene() const { - return static_cast*>(sceneObject()); + const Object* p(this); + while(p && !p->isScene()) p = p->parent(); + return static_cast*>(p); } -template Object* Object::sceneObject() { - Object* p(this); - while(p && !p->isScene()) p = p->parent(); - return p; +template Object* Object::doScene() { + return scene(); } -template const Object* Object::sceneObject() const { - const Object* p(this); - while(p && !p->isScene()) p = p->parent(); - return p; +template const Object* Object::doScene() const { + return scene(); } template Object* Object::setParent(Object* parent) { @@ -159,13 +161,17 @@ template void Object::setClean() { } } -template std::vector::MatrixType> Object::transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix) const { +template std::vector::MatrixType> Object::doTransformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix) const { std::vector*> castObjects(objects.size()); for(std::size_t i = 0; i != objects.size(); ++i) /** @todo Ensure this doesn't crash, somehow */ castObjects[i] = static_cast*>(objects[i]); - std::vector transformations = this->transformations(std::move(castObjects), Transformation::fromMatrix(initialTransformationMatrix)); + return transformationMatrices(std::move(castObjects), initialTransformationMatrix); +} + +template std::vector::MatrixType> Object::transformationMatrices(const std::vector*>& objects, const typename DimensionTraits::MatrixType& initialTransformationMatrix) const { + std::vector transformations = this->transformations(std::move(objects), Transformation::fromMatrix(initialTransformationMatrix)); std::vector::MatrixType> transformationMatrices(transformations.size()); for(std::size_t i = 0; i != objects.size(); ++i) transformationMatrices[i] = Transformation::toMatrix(transformations[i]); @@ -317,7 +323,7 @@ template typename Transformation::DataType Object void Object::setClean(const std::vector*>& objects) const { +template void Object::doSetClean(const std::vector*>& objects) { std::vector*> castObjects(objects.size()); for(std::size_t i = 0; i != objects.size(); ++i) /** @todo Ensure this doesn't crash, somehow */ diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 42ae1d2e1..bdba1d6b6 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -42,7 +42,8 @@ template class Scene: public Object { public: explicit Scene() = default; - bool isScene() const { return true; } + private: + bool isScene() const override final { return true; } }; }} diff --git a/src/Shapes/ShapeGroup.cpp b/src/Shapes/ShapeGroup.cpp index bd4810f1f..d99b9d598 100644 --- a/src/Shapes/ShapeGroup.cpp +++ b/src/Shapes/ShapeGroup.cpp @@ -35,7 +35,7 @@ template void ShapeGroup::setClean() { for(std::size_t i = 0; i != this->size(); ++i) objects[i] = (*this)[i]->object(); - objects[0]->setClean(objects); + SceneGraph::AbstractObject::setClean(objects); } dirty = false;