Browse Source

SceneGraph: function for bulk cleaning of objects.

pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
aa05235c65
  1. 14
      src/SceneGraph/AbstractObject.h
  2. 11
      src/SceneGraph/Object.h
  3. 28
      src/SceneGraph/Object.hpp
  4. 63
      src/SceneGraph/Test/ObjectTest.cpp
  5. 1
      src/SceneGraph/Test/ObjectTest.h

14
src/SceneGraph/AbstractObject.h

@ -151,10 +151,24 @@ template<std::uint8_t dimensions, class T = GLfloat> class AbstractObject
* on all object features which have caching enabled and recursively
* calls setClean() on every parent which is not already clean. If the
* object is already clean, the function does nothing.
*
* See also setClean(const std::vector& objects), which cleans given
* set of objects more efficiently than when calling setClean() on
* 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;
/*@}*/
};

11
src/SceneGraph/Object.h

@ -78,6 +78,15 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
#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
@ -213,6 +222,8 @@ template<class Transformation> class Object: public AbstractObject<Transformatio
typename Transformation::DataType 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;
void setClean(const typename Transformation::DataType& absoluteTransformation);
typedef Implementation::ObjectFlag Flag;

28
src/SceneGraph/Object.hpp

@ -21,6 +21,7 @@
#include "Object.h"
#include <algorithm>
#include <stack>
#include "Scene.h"
@ -253,6 +254,33 @@ 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 {
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]);
setClean(std::move(castObjects));
}
template<class Transformation> void Object<Transformation>::setClean(std::vector<Object<Transformation>*> objects) {
/* Remove all clean objects from the list */
auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object<Transformation>* o) { return !o->isDirty(); });
objects.erase(firstClean, objects.end());
/* No dirty objects left, done */
if(objects.empty()) return;
/* Compute absolute transformations */
Scene<Transformation>* scene = objects[0]->scene();
CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", );
std::vector<typename Transformation::DataType> transformations(scene->transformations(objects));
/* Go through all objects and clean them */
for(std::size_t i = 0; i != objects.size(); ++i)
objects[i]->setClean(transformations[i]);
}
template<class Transformation> void Object<Transformation>::setClean(const typename Transformation::DataType& absoluteTransformation) {
/* "Lazy storage" for transformation matrix and inverted transformation matrix */
typedef typename AbstractFeature<Transformation::Dimensions, typename Transformation::Type>::CachedTransformation CachedTransformation;

63
src/SceneGraph/Test/ObjectTest.cpp

@ -30,12 +30,27 @@ namespace Magnum { namespace SceneGraph { namespace Test {
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D<GLfloat>> Object3D;
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D<GLfloat>> Scene3D;
class CachingObject: public Object3D, AbstractFeature<3, GLfloat> {
public:
inline CachingObject(Object3D* parent = nullptr): Object3D(parent), AbstractFeature<3, GLfloat>(this) {
setCachedTransformations(CachedTransformation::Absolute);
}
Matrix4 cleanedAbsoluteTransformation;
protected:
void clean(const Matrix4& absoluteTransformation) override {
cleanedAbsoluteTransformation = absoluteTransformation;
}
};
ObjectTest::ObjectTest() {
addTests(&ObjectTest::parenting,
&ObjectTest::scene,
&ObjectTest::absoluteTransformation,
&ObjectTest::transformations,
&ObjectTest::setClean);
&ObjectTest::setClean,
&ObjectTest::bulkSetClean);
}
void ObjectTest::parenting() {
@ -197,20 +212,6 @@ void ObjectTest::setClean() {
}
};
class CachingObject: public Object3D, AbstractFeature<3, GLfloat> {
public:
inline CachingObject(Object3D* parent = nullptr): Object3D(parent), AbstractFeature<3, GLfloat>(this) {
setCachedTransformations(CachedTransformation::Absolute);
}
Matrix4 cleanedAbsoluteTransformation;
protected:
void clean(const Matrix4& absoluteTransformation) override {
cleanedAbsoluteTransformation = absoluteTransformation;
}
};
CachingObject* childOne = new CachingObject(&scene);
childOne->scale(Vector3(2.0f));
@ -277,4 +278,36 @@ void ObjectTest::setClean() {
CORRADE_VERIFY(childThree->isDirty());
}
void ObjectTest::bulkSetClean() {
/* Verify it doesn't crash when passed empty list */
Object3D::setClean(vector<Object3D*>());
Scene3D scene;
Object3D a(&scene);
Object3D b(&scene);
b.setClean();
Object3D c(&scene);
c.translate(Vector3::zAxis(3.0f));
CachingObject d(&c);
d.scale(Vector3(-2.0f));
Object3D e(&scene);
vector<Object3D*> cleanAll{&a, &b, &c, &d, &e};
/* All objects should be cleaned */
CORRADE_VERIFY(a.isDirty());
CORRADE_VERIFY(!b.isDirty());
CORRADE_VERIFY(c.isDirty());
CORRADE_VERIFY(d.isDirty());
CORRADE_VERIFY(e.isDirty());
Object3D::setClean(cleanAll);
CORRADE_VERIFY(!a.isDirty());
CORRADE_VERIFY(!b.isDirty());
CORRADE_VERIFY(!c.isDirty());
CORRADE_VERIFY(!d.isDirty());
CORRADE_VERIFY(!e.isDirty());
/* Verify that right transformation was passed */
CORRADE_COMPARE(d.cleanedAbsoluteTransformation, Matrix4::translation(Vector3::zAxis(3.0f))*Matrix4::scaling(Vector3(-2.0f)));
}
}}}

1
src/SceneGraph/Test/ObjectTest.h

@ -28,6 +28,7 @@ class ObjectTest: public Corrade::TestSuite::Tester<ObjectTest> {
void absoluteTransformation();
void transformations();
void setClean();
void bulkSetClean();
};
}}}

Loading…
Cancel
Save