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) {
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", );
/* Compute camera matrix */

73
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<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT AbstractObject: private Containers::LinkedList<AbstractFeature<dimensions, T>>
#else
#ifdef DOXYGEN_GENERATING_OUTPUT
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
{
friend class Containers::LinkedList<AbstractFeature<dimensions, T>>;
@ -99,17 +99,13 @@ template<UnsignedInt dimensions, class T = Float> 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<dimensions, T>* sceneObject() = 0;
AbstractObject<dimensions, T>* scene() { return doScene(); }
/** @overload */
virtual const AbstractObject<dimensions, T>* sceneObject() const = 0;
const AbstractObject<dimensions, T>* scene() const { return doScene(); }
/** @{ @name Object transformation */
@ -118,14 +114,18 @@ template<UnsignedInt dimensions, class T = Float> class AbstractObject
*
* @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
*
* @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
@ -133,10 +133,12 @@ template<UnsignedInt dimensions, class T = Float> 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<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.
*/
/**
* @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
*
@ -156,7 +170,7 @@ template<UnsignedInt dimensions, class T = Float> 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<UnsignedInt dimensions, class T = Float> 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<UnsignedInt dimensions, class T = Float> 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<AbstractObject<dimensions, T>*>& objects) const = 0;
void setClean() { doSetClean(); }
/*@}*/
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

99
src/SceneGraph/Object.h

@ -104,15 +104,6 @@ template<class Transformation> 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<Object<Transformation>*> objects);
/**
* @brief Constructor
* @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
* children.
*/
virtual ~Object() {}
~Object();
/**
* @{ @name Scene hierarchy
@ -135,17 +126,9 @@ template<class Transformation> 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<Transformation>* scene();
/** @overload */
const Scene<Transformation>* scene() const;
const Scene<Transformation>* scene() const; /**< @overload */
/** @brief Parent object or `nullptr`, if this is root object */
Object<Transformation>* parent() {
@ -223,11 +206,21 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
/** @{ @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());
}
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());
}
@ -238,12 +231,21 @@ template<class Transformation> 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<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
*
* 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 Transformation> 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<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:
Object<Transformation>* sceneObject() override;
const Object<Transformation>* sceneObject() const override;
Object<Transformation>* doScene() override final;
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;
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);

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<class Transformation> Object<Transformation>::~Object() = default;
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 {
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() {
Object<Transformation>* p(this);
while(p && !p->isScene()) p = p->parent();
return p;
template<class Transformation> Object<Transformation>* Object<Transformation>::doScene() {
return scene();
}
template<class Transformation> const Object<Transformation>* Object<Transformation>::sceneObject() const {
const Object<Transformation>* p(this);
while(p && !p->isScene()) p = p->parent();
return p;
template<class Transformation> const Object<Transformation>* Object<Transformation>::doScene() const {
return scene();
}
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());
for(std::size_t i = 0; i != objects.size(); ++i)
/** @todo Ensure this doesn't crash, somehow */
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());
for(std::size_t i = 0; i != objects.size(); ++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());
for(std::size_t i = 0; i != objects.size(); ++i)
/** @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:
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)
objects[i] = (*this)[i]->object();
objects[0]->setClean(objects);
SceneGraph::AbstractObject<dimensions>::setClean(objects);
}
dirty = false;

Loading…
Cancel
Save