Browse Source

SceneGraph: Using linked list from Corrade instead of std::set.

Resulting (debug) executables are ~100 kB smaller, all operations
which were previously logarithmic are now done in constant time and
the whole implementation is a lot simpler.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
58abfdeeee
  1. 8
      src/SceneGraph/Camera.cpp
  2. 42
      src/SceneGraph/Object.cpp
  3. 30
      src/SceneGraph/Object.h
  4. 11
      src/SceneGraph/Test/ObjectTest.cpp
  5. 4
      src/SceneGraph/Test/SceneTest.cpp

8
src/SceneGraph/Camera.cpp

@ -72,13 +72,13 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> void Camera<MatrixType, VectorType, ObjectType, SceneType, CameraType>::drawChildren(ObjectType* object, const MatrixType& transformationMatrix) {
for(typename set<ObjectType*>::const_iterator it = object->children().begin(); it != object->children().end(); ++it) {
for(ObjectType* i = object->firstChild(); i; i = i->nextSibling()) {
/* Transformation matrix for the object */
MatrixType matrix = transformationMatrix*(*it)->transformation();
MatrixType matrix = transformationMatrix*i->transformation();
/* Draw the object and its children */
(*it)->draw(matrix, static_cast<CameraType*>(this));
drawChildren(*it, matrix);
i->draw(matrix, static_cast<CameraType*>(this));
drawChildren(i, matrix);
}
}

42
src/SceneGraph/Object.cpp

@ -27,28 +27,23 @@ namespace Magnum { namespace SceneGraph {
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> ObjectType* Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>::setParent(ObjectType* parent) {
/* Skip if nothing to do or this is scene */
if(_parent == parent || isScene()) return static_cast<ObjectType*>(this);
if(this->parent() == parent || isScene()) return static_cast<ObjectType*>(this);
/* Add the object to children list of new parent */
if(parent != nullptr) {
/* Only Fry can be his own grandfather */
ObjectType* p = parent;
while(p != nullptr) {
/** @todo Assert for this */
if(p == this) return static_cast<ObjectType*>(this);
p = p->parent();
}
parent->_children.insert(static_cast<ObjectType*>(this));
/* Only Fry can be his own grandfather */
ObjectType* p = parent;
while(p) {
/** @todo Assert for this */
if(p == this) return static_cast<ObjectType*>(this);
p = p->parent();
}
/* Remove the object from old parent children list */
if(_parent != nullptr)
_parent->_children.erase(static_cast<ObjectType*>(this));
if(this->parent())
this->parent()->cut(static_cast<ObjectType*>(this));
/* Set new parent */
_parent = parent;
/* Add the object to list of new parent */
if(parent)
parent->insert(static_cast<ObjectType*>(this));
setDirty();
return static_cast<ObjectType*>(this);
@ -82,15 +77,6 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
return t;
}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>::~Object() {
/* Remove the object from parent's children */
setParent(nullptr);
/* Delete all children */
while(!_children.empty())
delete *_children.begin();
}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> SceneType* Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>::scene() {
/* Goes up the family tree until it finds object which is parent of itself
(that's the scene) */
@ -120,8 +106,8 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
dirty = true;
/* Make all children dirty */
for(typename set<ObjectType*>::iterator it = _children.begin(); it != _children.end(); ++it)
(*it)->setDirty();
for(ObjectType* i = firstChild(); i; i = i->nextSibling())
i->setDirty();
}
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> void Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>::setClean() {

30
src/SceneGraph/Object.h

@ -19,7 +19,7 @@
* @brief Class Magnum::SceneGraph::Object
*/
#include <set>
#include <Containers/DoubleLinkedList.h>
#include "Magnum.h"
@ -43,7 +43,7 @@ namespace Magnum { namespace SceneGraph {
* @todo Transform transformation when changing parent, so the object stays in
* place.
*/
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> class SCENEGRAPH_EXPORT Object {
template<class MatrixType, class VectorType, class ObjectType, class SceneType, class CameraType> class SCENEGRAPH_EXPORT Object: public Corrade::Containers::DoubleLinkedList<ObjectType>, public Corrade::Containers::DoubleLinkedListItem<ObjectType, ObjectType> {
#ifndef DOXYGEN_GENERATING_OUTPUT
Object(const Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>& other) = delete;
Object(Object<MatrixType, VectorType, ObjectType, SceneType, CameraType>&& other) = delete;
@ -58,7 +58,7 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
*
* Sets all transformations to their default values.
*/
inline Object(ObjectType* parent = nullptr): _parent(nullptr), dirty(true) {
inline Object(ObjectType* parent = nullptr): dirty(true) {
setParent(parent);
}
@ -68,7 +68,7 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
* Removes itself from parent's children list and destroys all own
* children.
*/
virtual ~Object();
virtual inline ~Object() {}
/** @{ @name Scene hierarchy */
@ -81,11 +81,23 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
*/
SceneType* scene();
/** @brief Parent object */
inline ObjectType* parent() { return _parent; }
/** @brief Parent object or `nullptr`, if this is root object */
inline ObjectType* parent() { return Corrade::Containers::DoubleLinkedListItem<ObjectType, ObjectType>::list(); }
/** @brief Child objects */
inline const std::set<ObjectType*>& children() { return _children; }
/** @brief Previous sibling object or `nullptr`, if this is first object */
inline ObjectType* previousSibling() { return Corrade::Containers::DoubleLinkedListItem<ObjectType, ObjectType>::previous(); }
/** @brief Next sibling object or `nullptr`, if this is last object */
inline ObjectType* nextSibling() { return Corrade::Containers::DoubleLinkedListItem<ObjectType, ObjectType>::next(); }
/** @brief Whether this object has children */
inline bool hasChildren() const { return !Corrade::Containers::DoubleLinkedList<ObjectType>::isEmpty(); }
/** @brief First child object or `nullptr`, if this object has no children */
inline ObjectType* firstChild() { return Corrade::Containers::DoubleLinkedList<ObjectType>::first(); }
/** @brief Last child object or `nullptr`, if this object has no children */
inline ObjectType* lastChild() { return Corrade::Containers::DoubleLinkedList<ObjectType>::last(); }
/** @brief Set parent object */
ObjectType* setParent(ObjectType* parent);
@ -230,8 +242,6 @@ template<class MatrixType, class VectorType, class ObjectType, class SceneType,
/*@}*/
private:
ObjectType* _parent;
std::set<ObjectType*> _children;
MatrixType _transformation;
bool dirty;
};

11
src/SceneGraph/Test/ObjectTest.cpp

@ -41,7 +41,10 @@ void ObjectTest::parenting() {
Object3D* childTwo = new Object3D(&root);
CORRADE_VERIFY(childOne->parent() == &root);
CORRADE_COMPARE(root.children().size(), 2);
CORRADE_VERIFY(childTwo->parent() == &root);
CORRADE_VERIFY(root.firstChild() == childOne);
CORRADE_VERIFY(root.lastChild() == childTwo);
CORRADE_VERIFY(root.firstChild()->nextSibling() == root.lastChild());
/* A object cannot be parent of itself */
childOne->setParent(childOne);
@ -53,12 +56,12 @@ void ObjectTest::parenting() {
/* Reparent to another */
childTwo->setParent(childOne);
CORRADE_VERIFY(root.children().size() == 1 && *root.children().begin() == childOne);
CORRADE_VERIFY(childOne->children().size() == 1 && *childOne->children().begin() == childTwo);
CORRADE_VERIFY(root.firstChild() == childOne && root.firstChild()->nextSibling() == nullptr);
CORRADE_VERIFY(childOne->firstChild() == childTwo && childOne->firstChild()->nextSibling() == nullptr);
/* Delete child */
delete childTwo;
CORRADE_VERIFY(childOne->children().empty());
CORRADE_VERIFY(!childOne->hasChildren());
}
void ObjectTest::transformation() {

4
src/SceneGraph/Test/SceneTest.cpp

@ -43,8 +43,8 @@ void SceneTest::parent() {
Object3D object;
scenePointer->setParent(&object);
CORRADE_VERIFY(scene.parent() == nullptr);
CORRADE_VERIFY(scene.children().empty());
CORRADE_VERIFY(object.children().empty());
CORRADE_VERIFY(!scene.hasChildren());
CORRADE_VERIFY(!object.hasChildren());
}
}}}

Loading…
Cancel
Save