From aa49008358fbedd6607cdaad2c54d0eecfa913cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 8 Feb 2014 21:00:53 +0100 Subject: [PATCH] SceneGraph: using std::reference_wrapper instead of pointers. Currently all the functions taking vectors of objects (e.g. setClean(), transformations() and transformationMatrices()) were taking pointers, which lead to additional (and often forgotten) nullptr checks. The internals are now much more clean, as the parts where we are dealing with pointers are reduced to bare minimum. Also renamed private Object::setClean() function to Object::setCleanInternal() to avoid overload clash with the public one. The old way is now an nullptr-checked alias to the new one, is marked as deprecated and will be removed in some future release. --- src/Magnum/SceneGraph/AbstractCamera.hpp | 5 +- src/Magnum/SceneGraph/AbstractObject.h | 27 +++- src/Magnum/SceneGraph/Object.h | 40 ++++-- src/Magnum/SceneGraph/Object.hpp | 166 +++++++++++++++------- src/Magnum/SceneGraph/Test/ObjectTest.cpp | 31 ++-- src/Magnum/Shapes/ShapeGroup.cpp | 5 +- 6 files changed, 189 insertions(+), 85 deletions(-) diff --git a/src/Magnum/SceneGraph/AbstractCamera.hpp b/src/Magnum/SceneGraph/AbstractCamera.hpp index 994729c60..b3128484a 100644 --- a/src/Magnum/SceneGraph/AbstractCamera.hpp +++ b/src/Magnum/SceneGraph/AbstractCamera.hpp @@ -93,9 +93,10 @@ template void AbstractCamera::dr AbstractFeature::object().setClean(); /* Compute transformations of all objects in the group relative to the camera */ - std::vector*> objects(group.size()); + std::vector>> objects; + objects.reserve(group.size()); for(std::size_t i = 0; i != group.size(); ++i) - objects[i] = &group[i].object(); + objects.push_back(group[i].object()); std::vector::MatrixType> transformations = scene->transformationMatrices(objects, _cameraMatrix); diff --git a/src/Magnum/SceneGraph/AbstractObject.h b/src/Magnum/SceneGraph/AbstractObject.h index cc204eb36..f02872d09 100644 --- a/src/Magnum/SceneGraph/AbstractObject.h +++ b/src/Magnum/SceneGraph/AbstractObject.h @@ -29,6 +29,7 @@ * @brief Class @ref Magnum::SceneGraph::AbstractObject, alias @ref Magnum::SceneGraph::AbstractBasicObject2D, @ref Magnum::SceneGraph::AbstractBasicObject3D, typedef @ref Magnum::SceneGraph::AbstractObject2D, @ref Magnum::SceneGraph::AbstractObject3D */ +#include #include #include @@ -154,10 +155,18 @@ template class AbstractObject * @ref Object type, use typesafe @ref Object::transformationMatrices() * when possible. */ - std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { + std::vector transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const { return doTransformationMatrices(objects, initialTransformationMatrix); } + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformationMatrices(const std::vector>>&, const MatrixType&) + * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + */ + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif + /*@}*/ /** @@ -174,11 +183,19 @@ template class AbstractObject * @ref Object type, use typesafe @ref Object::setClean() when * possible. */ - static void setClean(const std::vector*>& objects) { + static void setClean(const std::vector>>& objects) { if(objects.empty()) return; - objects.front()->doSetClean(objects); + objects.front().get().doSetClean(objects); } + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief setClean(const std::vector>>&) + * @deprecated Use @ref Magnum::SceneGraph::AbstractObject::setClean(const std::vector>>&) "setClean(const std::vector>>&)" instead. + */ + static CORRADE_DEPRECATED("use setClean(const std::vector>>&) instead") void setClean(const std::vector*>& objects); + #endif + /** * @brief Whether absolute transformation is dirty * @@ -223,12 +240,12 @@ template class AbstractObject virtual MatrixType doTransformationMatrix() const = 0; virtual MatrixType doAbsoluteTransformationMatrix() const = 0; - virtual std::vector doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const = 0; + virtual std::vector doTransformationMatrices(const std::vector>>& objects, const 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; + virtual void doSetClean(const std::vector>>& objects) = 0; }; #ifndef CORRADE_GCC46_COMPATIBILITY diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 634b50597..09911ae5c 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -247,7 +247,15 @@ template class Object: public AbstractObject transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + std::vector transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformationMatrices(const std::vector>>&, const MatrixType&) + * @deprecated Use @ref Magnum::SceneGraph::Object::transformationMatrices(const std::vector>>&, const MatrixType&) "transformationMatrices(const std::vector>>&, const MatrixType&)" instead. + */ + CORRADE_DEPRECATED("use transformationMatrices(const std::vector>>&, const MatrixType&) instead") std::vector transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix = MatrixType()) const; + #endif /** * @brief Transformations of given group of objects relative to this object @@ -258,7 +266,15 @@ template class Object: public AbstractObject transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + std::vector transformations(std::vector>> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief transformations(std::vector>>, const typename Transformation::DataType&) + * @deprecated Use @ref Magnum::SceneGraph::Object::transformations(std::vector>>, const typename Transformation::DataType&) "transformations(std::vector>>, const typename Transformation::DataType&)" instead. + */ + CORRADE_DEPRECATED("use transformations(std::vector>>, const typename Transformation::DataType&) instead") std::vector transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation = typename Transformation::DataType()) const; + #endif /*@}*/ @@ -275,7 +291,15 @@ template class Object: public AbstractObject*> objects); + static void setClean(std::vector>> objects); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief setClean(std::vector>>) + * @deprecated Use @ref Magnum::SceneGraph::Object::setClean(std::vector>> "setClean(std::vector>>" instead. + */ + CORRADE_DEPRECATED("use setClean(std::vector>>) instead") static void setClean(std::vector*> objects); + #endif /** @copydoc AbstractObject::isDirty() */ bool isDirty() const { return !!(flags & Flag::Dirty); } @@ -291,7 +315,7 @@ template class Object: public AbstractObject*>), + * See also @ref setClean(std::vector>>), * which cleans given set of objects more efficiently than when calling * @ref setClean() on each object individually. * @see @ref scenegraph-caching, @ref setDirty(), @ref isDirty() @@ -317,16 +341,16 @@ template class Object: public AbstractObject doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const override final; + std::vector doTransformationMatrices(const std::vector>>& objects, const 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; + 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; bool MAGNUM_SCENEGRAPH_LOCAL doIsDirty() const override final { return isDirty(); } void MAGNUM_SCENEGRAPH_LOCAL doSetDirty() override final { setDirty(); } void MAGNUM_SCENEGRAPH_LOCAL doSetClean() override final { setClean(); } - void doSetClean(const std::vector*>& objects) override final; + void doSetClean(const std::vector>>& objects) override final; - void MAGNUM_SCENEGRAPH_LOCAL setClean(const typename Transformation::DataType& absoluteTransformation); + void MAGNUM_SCENEGRAPH_LOCAL setCleanInternal(const typename Transformation::DataType& absoluteTransformation); typedef Implementation::ObjectFlag Flag; typedef Implementation::ObjectFlags Flags; diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index d0dafa267..2f6cbcd55 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -38,9 +38,35 @@ namespace Magnum { namespace SceneGraph { +#ifdef MAGNUM_BUILD_DEPRECATED +template void AbstractObject::setClean(const std::vector*>& objects) { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + setClean(references); +} +#endif + template AbstractObject::AbstractObject() {} template AbstractObject::~AbstractObject() {} +#ifdef MAGNUM_BUILD_DEPRECATED +template auto AbstractObject::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformationMatrices(references, initialTransformationMatrix); +} +#endif + template AbstractTransformation::AbstractTransformation() {} template Object::Object(Object* parent): counter(0xFFFFu), flags(Flag::Dirty) { @@ -159,22 +185,21 @@ template void Object::setClean() { /* Compose transformation and clean object */ absoluteTransformation = Implementation::Transformation::compose(absoluteTransformation, o->transformation()); CORRADE_INTERNAL_ASSERT(o->isDirty()); - o->setClean(absoluteTransformation); + o->setCleanInternal(absoluteTransformation); CORRADE_ASSERT(!o->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); } } -template auto Object::doTransformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { - std::vector*> castObjects(objects.size()); - for(std::size_t i = 0; i != objects.size(); ++i) - /* Non-null is checked in transformations() */ - /** @todo Ensure this doesn't crash, somehow */ - castObjects[i] = static_cast*>(objects[i]); +template auto Object::doTransformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> castObjects; + castObjects.reserve(objects.size()); + /** @todo Ensure this doesn't crash, somehow */ + for(auto o: objects) castObjects.push_back(static_cast&>(o.get())); return transformationMatrices(std::move(castObjects), initialTransformationMatrix); } -template auto Object::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { +template auto Object::transformationMatrices(const std::vector>>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { std::vector transformations = this->transformations(std::move(objects), Implementation::Transformation::fromMatrix(initialTransformationMatrix)); std::vector transformationMatrices(transformations.size()); for(std::size_t i = 0; i != objects.size(); ++i) @@ -183,6 +208,19 @@ template auto Object::transformationMatric return transformationMatrices; } +#ifdef MAGNUM_BUILD_DEPRECATED +template auto Object::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformationMatrices(references, initialTransformationMatrix); +} +#endif + /* Computing absolute transformations for given list of objects @@ -197,7 +235,7 @@ Then for all joints their transformation (relative to parent joint) is computed and recursively concatenated together. Resulting transformations for joints which were originally in `object` list is then returned. */ -template std::vector Object::transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation) const { +template std::vector Object::transformations(std::vector>> objects, const typename Transformation::DataType& initialTransformation) const { CORRADE_ASSERT(objects.size() < 0xFFFFu, "SceneGraph::Object::transformations(): too large scene", std::vector{}); /* Remember object count for later */ @@ -206,16 +244,14 @@ template std::vector Ob /* Mark all original objects as joints and create initial list of joints from them */ for(std::size_t i = 0; i != objects.size(); ++i) { - CORRADE_INTERNAL_ASSERT(objects[i]); - /* Multiple occurences of one object in the array, don't overwrite it with different counter */ - if(objects[i]->counter != 0xFFFFu) continue; + if(objects[i].get().counter != 0xFFFFu) continue; - objects[i]->counter = UnsignedShort(i); - objects[i]->flags |= Flag::Joint; + objects[i].get().counter = UnsignedShort(i); + objects[i].get().flags |= Flag::Joint; } - std::vector*> jointObjects(objects); + std::vector>> jointObjects(objects); /* Scene object */ const Scene* scene = this->scene(); @@ -227,19 +263,19 @@ template std::vector Ob auto it = objects.begin(); while(!objects.empty()) { /* Already visited, remove and continue to next (duplicate occurence) */ - if((*it)->flags & Flag::Visited) { + if(it->get().flags & Flag::Visited) { it = objects.erase(it); continue; } /* Mark the object as visited */ - (*it)->flags |= Flag::Visited; + it->get().flags |= Flag::Visited; - Object* parent = (*it)->parent(); + Object* parent = it->get().parent(); /* If this is root object, remove from list */ if(!parent) { - CORRADE_ASSERT(*it == scene, "SceneGraph::Object::transformations(): the objects are not part of the same tree", std::vector{}); + CORRADE_ASSERT(&it->get() == scene, "SceneGraph::Object::transformations(): the objects are not part of the same tree", std::vector{}); it = objects.erase(it); /* Parent is an joint or already visited - remove current from list */ @@ -254,11 +290,11 @@ template std::vector Ob CORRADE_INTERNAL_ASSERT(parent->counter == 0xFFFFu); parent->counter = UnsignedShort(jointObjects.size()); parent->flags |= Flag::Joint; - jointObjects.push_back(parent); + jointObjects.push_back(*parent); } /* Else go up the hierarchy */ - } else *it = parent; + } else *it = *parent; /* Cycle if reached end */ if(it == objects.end()) it = objects.begin(); @@ -274,17 +310,17 @@ template std::vector Ob /* Copy transformation for second or next occurences from first occurence of duplicate object */ for(std::size_t i = 0; i != objectCount; ++i) { - if(jointObjects[i]->counter != i) - jointTransformations[i] = jointTransformations[jointObjects[i]->counter]; + if(jointObjects[i].get().counter != i) + jointTransformations[i] = jointTransformations[jointObjects[i].get().counter]; } /* All visited marks are now cleaned, clean joint marks and counters */ for(auto i: jointObjects) { /* All not-already cleaned objects (...duplicate occurences) should have joint mark */ - CORRADE_INTERNAL_ASSERT(i->counter == 0xFFFFu || i->flags & Flag::Joint); - i->flags &= ~Flag::Joint; - i->counter = 0xFFFFu; + CORRADE_INTERNAL_ASSERT(i.get().counter == 0xFFFFu || i.get().flags & Flag::Joint); + i.get().flags &= ~Flag::Joint; + i.get().counter = 0xFFFFu; } /* Shrink the array to contain only transformations of requested objects and return */ @@ -292,27 +328,40 @@ template std::vector Ob return jointTransformations; } -template typename Transformation::DataType Object::computeJointTransformation(const std::vector*>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const { - Object* o = jointObjects[joint]; +#ifdef MAGNUM_BUILD_DEPRECATED +template std::vector Object::transformations(std::vector*> objects, const typename Transformation::DataType& initialTransformation) const { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); + } + + return transformations(references, initialTransformation); +} +#endif + +template typename Transformation::DataType Object::computeJointTransformation(const std::vector>>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const { + std::reference_wrapper> o = jointObjects[joint]; /* Transformation already computed ("unvisited" by this function before either due to recursion or duplicate object occurences), done */ - if(!(o->flags & Flag::Visited)) return jointTransformations[joint]; + if(!(o.get().flags & Flag::Visited)) return jointTransformations[joint]; /* Initialize transformation */ - jointTransformations[joint] = o->transformation(); + jointTransformations[joint] = o.get().transformation(); /* Go up until next joint or root */ for(;;) { /* Clean visited mark */ - CORRADE_INTERNAL_ASSERT(o->flags & Flag::Visited); - o->flags &= ~Flag::Visited; + CORRADE_INTERNAL_ASSERT(o.get().flags & Flag::Visited); + o.get().flags &= ~Flag::Visited; - Object* parent = o->parent(); + Object* parent = o.get().parent(); /* Root object, compose transformation with initial, done */ if(!parent) { - CORRADE_INTERNAL_ASSERT(o->isScene()); + CORRADE_INTERNAL_ASSERT(o.get().isScene()); return (jointTransformations[joint] = Implementation::Transformation::compose(initialTransformation, jointTransformations[joint])); @@ -324,23 +373,23 @@ template typename Transformation::DataType Object::compose(parent->transformation(), jointTransformations[joint]); - o = parent; + o = *parent; } } } -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 */ - castObjects[i] = static_cast*>(objects[i]); +template void Object::doSetClean(const std::vector>>& objects) { + std::vector>> castObjects; + castObjects.reserve(objects.size()); + /** @todo Ensure this doesn't crash, somehow */ + for(auto o: objects) castObjects.push_back(static_cast&>(o.get())); setClean(std::move(castObjects)); } -template void Object::setClean(std::vector*> objects) { +template void Object::setClean(std::vector>> objects) { /* Remove all clean objects from the list */ - auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object* o) { return !o->isDirty(); }); + auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object& o) { return !o.isDirty(); }); objects.erase(firstClean, objects.end()); /* No dirty objects left, done */ @@ -349,35 +398,48 @@ template void Object::setClean(std::vector /* Add non-clean parents to the list. Mark each added object as visited, so they aren't added more than once */ for(std::size_t end = objects.size(), i = 0; i != end; ++i) { - Object* o = objects[i]; - o->flags |= Flag::Visited; + Object& o = objects[i]; + o.flags |= Flag::Visited; - Object* parent = o->parent(); + Object* parent = o.parent(); while(parent && !(parent->flags & Flag::Visited) && parent->isDirty()) { - objects.push_back(parent); + objects.push_back(*parent); parent = parent->parent(); } } /* Cleanup all marks */ - for(auto o: objects) o->flags &= ~Flag::Visited; + for(auto o: objects) o.get().flags &= ~Flag::Visited; /* Compute absolute transformations */ - Scene* scene = objects[0]->scene(); + Scene* scene = objects[0].get().scene(); CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", ); std::vector transformations(scene->transformations(objects)); /* Go through all objects and clean them */ for(std::size_t i = 0; i != objects.size(); ++i) { /* The object might be duplicated in the list, don't clean it more than once */ - if(!objects[i]->isDirty()) continue; + if(!objects[i].get().isDirty()) continue; + + objects[i].get().setCleanInternal(transformations[i]); + CORRADE_ASSERT(!objects[i].get().isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); + } +} - objects[i]->setClean(transformations[i]); - CORRADE_ASSERT(!objects[i]->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", ); +#ifdef MAGNUM_BUILD_DEPRECATED +template void Object::setClean(std::vector*> objects) { + std::vector>> references; + references.reserve(objects.size()); + for(auto o: objects) { + CORRADE_INTERNAL_ASSERT(o != nullptr); + references.push_back(*o); } + + return setClean(objects); } +#endif -template void Object::setClean(const typename Transformation::DataType& absoluteTransformation) { +template void Object::setCleanInternal(const typename Transformation::DataType& absoluteTransformation) { /* "Lazy storage" for transformation matrix and inverted transformation matrix */ CachedTransformations cached; MatrixType matrix, invertedMatrix; diff --git a/src/Magnum/SceneGraph/Test/ObjectTest.cpp b/src/Magnum/SceneGraph/Test/ObjectTest.cpp index 401f9accb..c031b3d02 100644 --- a/src/Magnum/SceneGraph/Test/ObjectTest.cpp +++ b/src/Magnum/SceneGraph/Test/ObjectTest.cpp @@ -174,22 +174,22 @@ void ObjectTest::transformations() { Matrix4 initial = Matrix4::rotationX(Deg(90.0f)).inverted(); /* Empty list */ - CORRADE_COMPARE(s.transformations(std::vector(), initial), std::vector()); + CORRADE_COMPARE(s.transformations({}, initial), std::vector()); /* Scene alone */ - CORRADE_COMPARE(s.transformations({&s}, initial), std::vector{initial}); + CORRADE_COMPARE(s.transformations({s}, initial), std::vector{initial}); /* One object */ Object3D first(&s); first.rotateZ(Deg(30.0f)); Object3D second(&first); second.scale(Vector3(0.5f)); - CORRADE_COMPARE(s.transformations({&second}, initial), std::vector{ + CORRADE_COMPARE(s.transformations({second}, initial), std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)) }); /* One object and scene */ - CORRADE_COMPARE(s.transformations({&second, &s}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, s}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial })); @@ -197,13 +197,13 @@ void ObjectTest::transformations() { /* Two objects with foreign joint */ Object3D third(&first); third.translate(Vector3::xAxis(5.0f)); - CORRADE_COMPARE(s.transformations({&second, &third}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)), })); /* Three objects with joint as one of them */ - CORRADE_COMPARE(s.transformations({&second, &third, &first}, initial), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third, first}, initial), (std::vector{ initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)), initial*Matrix4::rotationZ(Deg(30.0f)), @@ -222,7 +222,7 @@ void ObjectTest::transformationsRelative() { third.translate(Vector3::xAxis(5.0f)); /* Transformation relative to another object */ - CORRADE_COMPARE(second.transformations({&third}), std::vector{ + CORRADE_COMPARE(second.transformations({third}), std::vector{ Matrix4::scaling(Vector3(0.5f)).inverted()*Matrix4::translation(Vector3::xAxis(5.0f)) }); @@ -234,7 +234,7 @@ void ObjectTest::transformationsRelative() { orphan1.scale(Vector3::xScale(3.0f)); Object3D orphan2(&orphanParent); orphan2.translate(Vector3::zAxis(5.0f)); - CORRADE_COMPARE(orphan1.transformations({&orphan2}), std::vector{ + CORRADE_COMPARE(orphan1.transformations({orphan2}), std::vector{ Matrix4::scaling(Vector3::xScale(3.0f)).inverted()*Matrix4::translation(Vector3::zAxis(5.0f)) }); } @@ -246,7 +246,7 @@ void ObjectTest::transformationsOrphan() { /* Transformation of objects not part of the same scene */ Scene3D s; Object3D orphan; - CORRADE_COMPARE(s.transformations({&orphan}), std::vector()); + CORRADE_COMPARE(s.transformations({orphan}), std::vector()); CORRADE_COMPARE(o.str(), "SceneGraph::Object::transformations(): the objects are not part of the same tree\n"); } @@ -262,7 +262,7 @@ void ObjectTest::transformationsDuplicate() { Matrix4 firstExpected = Matrix4::rotationZ(Deg(30.0f)); Matrix4 secondExpected = Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)); Matrix4 thirdExpected = Matrix4::rotationZ(Deg(30.0f))*Matrix4::translation(Vector3::xAxis(5.0f)); - CORRADE_COMPARE(s.transformations({&second, &third, &second, &first, &third}), (std::vector{ + CORRADE_COMPARE(s.transformations({second, third, second, first, third}), (std::vector{ secondExpected, thirdExpected, secondExpected, firstExpected, thirdExpected })); } @@ -392,7 +392,7 @@ void ObjectTest::setCleanListHierarchy() { childThree->rotate(Deg(90.0f), Vector3::yAxis()); /* Clean the object and all its dirty parents (but not children) */ - Scene3D::setClean(std::vector{childTwo}); + Scene3D::setClean({*childTwo}); CORRADE_VERIFY(!scene.isDirty()); CORRADE_VERIFY(!childOne->isDirty()); CORRADE_VERIFY(!childTwo->isDirty()); @@ -406,19 +406,19 @@ void ObjectTest::setCleanListHierarchy() { /* If the object itself is already clean, it shouldn't clean it again */ childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); CORRADE_VERIFY(!childOne->isDirty()); - Scene3D::setClean(std::vector{childOne}); + Scene3D::setClean({*childOne}); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); /* If any object in the hierarchy is already clean, it shouldn't clean it again */ CORRADE_VERIFY(!childOne->isDirty()); childTwo->setDirty(); - Scene3D::setClean(std::vector{childTwo}); + Scene3D::setClean({*childTwo}); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); } void ObjectTest::setCleanListBulk() { /* Verify it doesn't crash when passed empty list */ - Object3D::setClean(std::vector()); + Object3D::setClean({}); Scene3D scene; Object3D a(&scene); @@ -429,7 +429,6 @@ void ObjectTest::setCleanListBulk() { CachingObject d(&c); d.scale(Vector3(-2.0f)); Object3D e(&scene); - std::vector cleanAll{&a, &b, &c, &d, &e}; /* All objects should be cleaned */ CORRADE_VERIFY(a.isDirty()); @@ -437,7 +436,7 @@ void ObjectTest::setCleanListBulk() { CORRADE_VERIFY(c.isDirty()); CORRADE_VERIFY(d.isDirty()); CORRADE_VERIFY(e.isDirty()); - Object3D::setClean(cleanAll); + Object3D::setClean({a, b, c, d, e}); CORRADE_VERIFY(!a.isDirty()); CORRADE_VERIFY(!b.isDirty()); CORRADE_VERIFY(!c.isDirty()); diff --git a/src/Magnum/Shapes/ShapeGroup.cpp b/src/Magnum/Shapes/ShapeGroup.cpp index 64648f9db..aebee420d 100644 --- a/src/Magnum/Shapes/ShapeGroup.cpp +++ b/src/Magnum/Shapes/ShapeGroup.cpp @@ -32,9 +32,10 @@ namespace Magnum { namespace Shapes { template void ShapeGroup::setClean() { /* Clean all objects */ if(!this->isEmpty()) { - std::vector*> objects(this->size()); + std::vector>> objects; + objects.reserve(this->size()); for(std::size_t i = 0; i != this->size(); ++i) - objects[i] = &(*this)[i].object(); + objects.push_back((*this)[i].object()); SceneGraph::AbstractObject::setClean(objects); }