Browse Source

SceneGraph: make public Object API non-virtual too.

Calling functions directly on Object will result in non-virtual calls,
calling functions on AbstractObject will result in virtual calls. Also
removed now unneeded "hacks" like `sceneObject()` and properly hiding
unsafe functions taking `AbstractObject*` with safe functions taking
`Object*`. Also hide `isScene()` from public documentation, as it is
sort-of hack too.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
1071a251cd
  1. 2
      src/SceneGraph/AbstractCamera.hpp
  2. 73
      src/SceneGraph/AbstractObject.h
  3. 99
      src/SceneGraph/Object.h
  4. 32
      src/SceneGraph/Object.hpp
  5. 3
      src/SceneGraph/Scene.h
  6. 2
      src/Shapes/ShapeGroup.cpp

2
src/SceneGraph/AbstractCamera.hpp

@ -88,7 +88,7 @@ template<UnsignedInt dimensions, class T> void AbstractCamera<dimensions, T>::se
} }
template<UnsignedInt dimensions, class T> void AbstractCamera<dimensions, T>::draw(DrawableGroup<dimensions, T>& group) { template<UnsignedInt dimensions, class T> void AbstractCamera<dimensions, T>::draw(DrawableGroup<dimensions, T>& group) {
AbstractObject<dimensions, T>* scene = AbstractFeature<dimensions, T>::object()->sceneObject(); AbstractObject<dimensions, T>* scene = AbstractFeature<dimensions, T>::object()->scene();
CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", ); CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", );
/* Compute camera matrix */ /* Compute camera matrix */

73
src/SceneGraph/AbstractObject.h

@ -56,10 +56,10 @@ for(AbstractFeature* feature = o->firstFeature(); feature; feature = feature->ne
@see AbstractObject2D, AbstractObject3D @see AbstractObject2D, AbstractObject3D
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractObject: private Containers::LinkedList<AbstractFeature<dimensions, T>>
#else
template<UnsignedInt dimensions, class T = Float> class AbstractObject template<UnsignedInt dimensions, class T = Float> class AbstractObject
#else
template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractObject: private Containers::LinkedList<AbstractFeature<dimensions, T>>
#endif #endif
{ {
friend class Containers::LinkedList<AbstractFeature<dimensions, T>>; friend class Containers::LinkedList<AbstractFeature<dimensions, T>>;
@ -99,17 +99,13 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
} }
/** /**
* @brief %Scene object * @brief %Scene
* @return Root object which is also scene or `nullptr`, if the object * @return %Scene or `nullptr`, if the object is not part of any scene.
* is not part of any scene.
*
* @todo Rename to scene() when I fully understand and fix covariant
* return issues.
*/ */
virtual AbstractObject<dimensions, T>* sceneObject() = 0; AbstractObject<dimensions, T>* scene() { return doScene(); }
/** @overload */ /** @overload */
virtual const AbstractObject<dimensions, T>* sceneObject() const = 0; const AbstractObject<dimensions, T>* scene() const { return doScene(); }
/** @{ @name Object transformation */ /** @{ @name Object transformation */
@ -118,14 +114,18 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* *
* @see Object::transformation() * @see Object::transformation()
*/ */
virtual typename DimensionTraits<dimensions, T>::MatrixType transformationMatrix() const = 0; typename DimensionTraits<dimensions, T>::MatrixType transformationMatrix() const {
return doTransformationMatrix();
}
/** /**
* @brief Transformation matrix relative to root object * @brief Transformation matrix relative to root object
* *
* @see Object::absoluteTransformation() * @see Object::absoluteTransformation()
*/ */
virtual typename DimensionTraits<dimensions, T>::MatrixType absoluteTransformationMatrix() const = 0; typename DimensionTraits<dimensions, T>::MatrixType absoluteTransformationMatrix() const {
return doAbsoluteTransformationMatrix();
}
/** /**
* @brief Transformation matrices of given set of objects relative to this object * @brief Transformation matrices of given set of objects relative to this object
@ -133,10 +133,12 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* All transformations are premultiplied with @p initialTransformationMatrix, * All transformations are premultiplied with @p initialTransformationMatrix,
* if specified. * if specified.
* @warning This function cannot check if all objects are of the same * @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. * possible.
*/ */
virtual std::vector<typename DimensionTraits<dimensions, T>::MatrixType> transformationMatrices(const std::vector<AbstractObject<dimensions, T>*>& objects, const typename DimensionTraits<dimensions, T>::MatrixType& initialTransformationMatrix = (typename DimensionTraits<dimensions, T>::MatrixType())) const = 0; std::vector<typename DimensionTraits<dimensions, T>::MatrixType> transformationMatrices(const std::vector<AbstractObject<dimensions, T>*>& objects, const typename DimensionTraits<dimensions, T>::MatrixType& initialTransformationMatrix = (typename DimensionTraits<dimensions, T>::MatrixType())) const {
return doTransformationMatrices(objects, initialTransformationMatrix);
}
/*@}*/ /*@}*/
@ -146,6 +148,18 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* See @ref scenegraph-caching for more information. * 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<AbstractObject<dimensions, T>*>& objects) {
if(objects.empty()) return;
objects.front()->doSetClean(objects);
}
/** /**
* @brief Whether absolute transformation is dirty * @brief Whether absolute transformation is dirty
* *
@ -156,7 +170,7 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* *
* @see @ref scenegraph-caching * @see @ref scenegraph-caching
*/ */
virtual bool isDirty() const = 0; bool isDirty() const { return doIsDirty(); }
/** /**
* @brief Set object absolute transformation as dirty * @brief Set object absolute transformation as dirty
@ -167,7 +181,7 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* function does nothing. * function does nothing.
* @see @ref scenegraph-caching, setClean(), isDirty() * @see @ref scenegraph-caching, setClean(), isDirty()
*/ */
virtual void setDirty() = 0; void setDirty() { doSetDirty(); }
/** /**
* @brief Clean object absolute transformation * @brief Clean object absolute transformation
@ -182,19 +196,22 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
* each object individually. * each object individually.
* @see @ref scenegraph-caching, setDirty(), isDirty() * @see @ref scenegraph-caching, setDirty(), isDirty()
*/ */
virtual void setClean() = 0; void setClean() { doSetClean(); }
/**
* @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<AbstractObject<dimensions, T>*>& objects) const = 0;
/*@}*/ /*@}*/
private:
virtual AbstractObject<dimensions, T>* doScene() = 0;
virtual const AbstractObject<dimensions, T>* doScene() const = 0;
virtual typename DimensionTraits<dimensions, T>::MatrixType doTransformationMatrix() const = 0;
virtual typename DimensionTraits<dimensions, T>::MatrixType doAbsoluteTransformationMatrix() const = 0;
virtual std::vector<typename DimensionTraits<dimensions, T>::MatrixType> doTransformationMatrices(const std::vector<AbstractObject<dimensions, T>*>& objects, const typename DimensionTraits<dimensions, T>::MatrixType& initialTransformationMatrix) const = 0;
virtual bool doIsDirty() const = 0;
virtual void doSetDirty() = 0;
virtual void doSetClean() = 0;
virtual void doSetClean(const std::vector<AbstractObject<dimensions, T>*>& objects) = 0;
}; };
#ifndef CORRADE_GCC46_COMPATIBILITY #ifndef CORRADE_GCC46_COMPATIBILITY

99
src/SceneGraph/Object.h

@ -104,15 +104,6 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
#endif #endif
public: 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<Object<Transformation>*> objects);
/** /**
* @brief Constructor * @brief Constructor
* @param parent Parent object * @param parent Parent object
@ -127,7 +118,7 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* Removes itself from parent's children list and destroys all own * Removes itself from parent's children list and destroys all own
* children. * children.
*/ */
virtual ~Object() {} ~Object();
/** /**
* @{ @name Scene hierarchy * @{ @name Scene hierarchy
@ -135,17 +126,9 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* See @ref scenegraph-hierarchy for more information. * See @ref scenegraph-hierarchy for more information.
*/ */
/** @brief Whether this object is scene */ /** @copydoc AbstractObject::scene() */
virtual bool isScene() const { return false; }
/**
* @brief %Scene
* @return %Scene or `nullptr`, if the object is not part of any scene.
*/
Scene<Transformation>* scene(); Scene<Transformation>* scene();
const Scene<Transformation>* scene() const; /**< @overload */
/** @overload */
const Scene<Transformation>* scene() const;
/** @brief Parent object or `nullptr`, if this is root object */ /** @brief Parent object or `nullptr`, if this is root object */
Object<Transformation>* parent() { Object<Transformation>* parent() {
@ -223,11 +206,21 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
/** @{ @name Object transformation */ /** @{ @name Object transformation */
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType transformationMatrix() const override { /**
* @brief Transformation matrix
*
* @see transformation()
*/
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType transformationMatrix() const {
return Transformation::toMatrix(Transformation::transformation()); return Transformation::toMatrix(Transformation::transformation());
} }
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType absoluteTransformationMatrix() const override { /**
* @brief Transformation matrix relative to root object
*
* @see absoluteTransformation()
*/
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType absoluteTransformationMatrix() const {
return Transformation::toMatrix(absoluteTransformation()); return Transformation::toMatrix(absoluteTransformation());
} }
@ -238,12 +231,21 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
*/ */
typename Transformation::DataType absoluteTransformation() const; 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<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> transformationMatrices(const std::vector<Object<Transformation>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix = (typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType())) const;
/** /**
* @brief Transformations of given group of objects relative to this object * @brief Transformations of given group of objects relative to this object
* *
* All transformations can be premultiplied with @p initialTransformation, * All transformations can be premultiplied with @p initialTransformation,
* if specified. * if specified.
* @see AbstractObject::transformationMatrices() * @see transformationMatrices()
*/ */
/* `objects` passed by copy intentionally (to allow move from /* `objects` passed by copy intentionally (to allow move from
transformationMatrices() and avoid copy in the function itself) */ transformationMatrices() and avoid copy in the function itself) */
@ -251,19 +253,56 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
/*@}*/ /*@}*/
bool isDirty() const override { return !!(flags & Flag::Dirty); } /**
void setDirty() override; * @{ @name Transformation caching
void setClean() override; *
* 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<Object<Transformation>*> 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: private:
Object<Transformation>* sceneObject() override; Object<Transformation>* doScene() override final;
const Object<Transformation>* sceneObject() const override; const Object<Transformation>* doScene() const override final;
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType MAGNUM_SCENEGRAPH_LOCAL doTransformationMatrix() const override final {
return transformationMatrix();
}
typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType MAGNUM_SCENEGRAPH_LOCAL doAbsoluteTransformationMatrix() const override final {
return absoluteTransformationMatrix();
}
std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> transformationMatrices(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix = (typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType())) const override; std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> doTransformationMatrices(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix) const override final;
typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector<Object<Transformation>*>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const; typename Transformation::DataType MAGNUM_SCENEGRAPH_LOCAL computeJointTransformation(const std::vector<Object<Transformation>*>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const;
void setClean(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& 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<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects) override final;
void MAGNUM_SCENEGRAPH_LOCAL setClean(const typename Transformation::DataType& absoluteTransformation); void MAGNUM_SCENEGRAPH_LOCAL setClean(const typename Transformation::DataType& absoluteTransformation);

32
src/SceneGraph/Object.hpp

@ -44,24 +44,26 @@ template<UnsignedInt dimensions, class T> AbstractObject<dimensions, T>::~Abstra
template<UnsignedInt dimensions, class T> AbstractTransformation<dimensions, T>::AbstractTransformation() {} template<UnsignedInt dimensions, class T> AbstractTransformation<dimensions, T>::AbstractTransformation() {}
template<UnsignedInt dimensions, class T> AbstractTransformation<dimensions, T>::~AbstractTransformation() {} template<UnsignedInt dimensions, class T> AbstractTransformation<dimensions, T>::~AbstractTransformation() {}
template<class Transformation> Object<Transformation>::~Object() = default;
template<class Transformation> Scene<Transformation>* Object<Transformation>::scene() { template<class Transformation> Scene<Transformation>* Object<Transformation>::scene() {
return static_cast<Scene<Transformation>*>(sceneObject()); Object<Transformation>* p(this);
while(p && !p->isScene()) p = p->parent();
return static_cast<Scene<Transformation>*>(p);
} }
template<class Transformation> const Scene<Transformation>* Object<Transformation>::scene() const { template<class Transformation> const Scene<Transformation>* Object<Transformation>::scene() const {
return static_cast<const Scene<Transformation>*>(sceneObject()); const Object<Transformation>* p(this);
while(p && !p->isScene()) p = p->parent();
return static_cast<const Scene<Transformation>*>(p);
} }
template<class Transformation> Object<Transformation>* Object<Transformation>::sceneObject() { template<class Transformation> Object<Transformation>* Object<Transformation>::doScene() {
Object<Transformation>* p(this); return scene();
while(p && !p->isScene()) p = p->parent();
return p;
} }
template<class Transformation> const Object<Transformation>* Object<Transformation>::sceneObject() const { template<class Transformation> const Object<Transformation>* Object<Transformation>::doScene() const {
const Object<Transformation>* p(this); return scene();
while(p && !p->isScene()) p = p->parent();
return p;
} }
template<class Transformation> Object<Transformation>* Object<Transformation>::setParent(Object<Transformation>* parent) { template<class Transformation> Object<Transformation>* Object<Transformation>::setParent(Object<Transformation>* parent) {
@ -159,13 +161,17 @@ template<class Transformation> void Object<Transformation>::setClean() {
} }
} }
template<class Transformation> std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> Object<Transformation>::transformationMatrices(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix) const { template<class Transformation> std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> Object<Transformation>::doTransformationMatrices(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix) const {
std::vector<Object<Transformation>*> castObjects(objects.size()); std::vector<Object<Transformation>*> castObjects(objects.size());
for(std::size_t i = 0; i != objects.size(); ++i) for(std::size_t i = 0; i != objects.size(); ++i)
/** @todo Ensure this doesn't crash, somehow */ /** @todo Ensure this doesn't crash, somehow */
castObjects[i] = static_cast<Object<Transformation>*>(objects[i]); castObjects[i] = static_cast<Object<Transformation>*>(objects[i]);
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(castObjects), Transformation::fromMatrix(initialTransformationMatrix)); return transformationMatrices(std::move(castObjects), initialTransformationMatrix);
}
template<class Transformation> std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> Object<Transformation>::transformationMatrices(const std::vector<Object<Transformation>*>& objects, const typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType& initialTransformationMatrix) const {
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Transformation::fromMatrix(initialTransformationMatrix));
std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> transformationMatrices(transformations.size()); std::vector<typename DimensionTraits<Transformation::Dimensions, typename Transformation::Type>::MatrixType> transformationMatrices(transformations.size());
for(std::size_t i = 0; i != objects.size(); ++i) for(std::size_t i = 0; i != objects.size(); ++i)
transformationMatrices[i] = Transformation::toMatrix(transformations[i]); transformationMatrices[i] = Transformation::toMatrix(transformations[i]);
@ -317,7 +323,7 @@ template<class Transformation> typename Transformation::DataType Object<Transfor
} }
} }
template<class Transformation> void Object<Transformation>::setClean(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects) const { template<class Transformation> void Object<Transformation>::doSetClean(const std::vector<AbstractObject<Transformation::Dimensions, typename Transformation::Type>*>& objects) {
std::vector<Object<Transformation>*> castObjects(objects.size()); std::vector<Object<Transformation>*> castObjects(objects.size());
for(std::size_t i = 0; i != objects.size(); ++i) for(std::size_t i = 0; i != objects.size(); ++i)
/** @todo Ensure this doesn't crash, somehow */ /** @todo Ensure this doesn't crash, somehow */

3
src/SceneGraph/Scene.h

@ -42,7 +42,8 @@ template<class Transformation> class Scene: public Object<Transformation> {
public: public:
explicit Scene() = default; explicit Scene() = default;
bool isScene() const { return true; } private:
bool isScene() const override final { return true; }
}; };
}} }}

2
src/Shapes/ShapeGroup.cpp

@ -35,7 +35,7 @@ template<UnsignedInt dimensions> void ShapeGroup<dimensions>::setClean() {
for(std::size_t i = 0; i != this->size(); ++i) for(std::size_t i = 0; i != this->size(); ++i)
objects[i] = (*this)[i]->object(); objects[i] = (*this)[i]->object();
objects[0]->setClean(objects); SceneGraph::AbstractObject<dimensions>::setClean(objects);
} }
dirty = false; dirty = false;

Loading…
Cancel
Save