Browse Source

SceneGraph: allow duplicate occurences in Object::transformations().

Fixes common case where one Object has multiple Drawable features
attached (one for regular mesh and one e.g. debug renderer).
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
59a3a7029d
  1. 26
      src/SceneGraph/Object.hpp
  2. 19
      src/SceneGraph/Test/ObjectTest.cpp

26
src/SceneGraph/Object.hpp

@ -169,7 +169,10 @@ template<class Transformation> std::vector<typename Transformation::DataType> 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]->counter == 0xFFFFu);
/* Multiple occurences of one object in the array, don't overwrite it
with different counter */
if(objects[i]->counter != 0xFFFFu) continue;
objects[i]->counter = i;
objects[i]->flags |= Flag::Joint;
}
@ -184,8 +187,13 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
/* Mark all objects up the hierarchy as visited */
auto it = objects.begin();
while(!objects.empty()) {
/* Already visited, remove and continue to next (duplicate occurence) */
if((*it)->flags & Flag::Visited) {
it = objects.erase(it);
continue;
}
/* Mark the object as visited */
CORRADE_INTERNAL_ASSERT(!((*it)->flags & Flag::Visited));
(*it)->flags |= Flag::Visited;
Object<Transformation>* parent = (*it)->parent();
@ -224,9 +232,18 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
for(std::size_t i = 0; i != jointTransformations.size(); ++i)
computeJointTransformation(jointObjects, jointTransformations, i, initialTransformation);
/* 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];
}
/* All visited marks are now cleaned, clean joint marks and counters */
for(auto i: jointObjects) {
CORRADE_INTERNAL_ASSERT(i->flags & Flag::Joint);
/* 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;
}
@ -239,7 +256,8 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
template<class Transformation> typename Transformation::DataType Object<Transformation>::computeJointTransformation(const std::vector<Object<Transformation>*>& jointObjects, std::vector<typename Transformation::DataType>& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const {
Object<Transformation>* o = jointObjects[joint];
/* Transformation already computed ("unvisited" by this function before), done */
/* 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];
/* Initialize transformation */

19
src/SceneGraph/Test/ObjectTest.cpp

@ -32,6 +32,7 @@ class ObjectTest: public Corrade::TestSuite::Tester {
void transformations();
void transformationsRelative();
void transformationsOrphan();
void transformationsDuplicate();
void setClean();
void bulkSetClean();
};
@ -60,6 +61,7 @@ ObjectTest::ObjectTest() {
&ObjectTest::transformations,
&ObjectTest::transformationsRelative,
&ObjectTest::transformationsOrphan,
&ObjectTest::transformationsDuplicate,
&ObjectTest::setClean,
&ObjectTest::bulkSetClean);
}
@ -210,6 +212,23 @@ void ObjectTest::transformationsOrphan() {
CORRADE_COMPARE(o.str(), "SceneGraph::Object::transformations(): the objects are not part of the same tree\n");
}
void ObjectTest::transformationsDuplicate() {
Scene3D s;
Object3D first(&s);
first.rotateZ(deg(30.0f));
Object3D second(&first);
second.scale(Vector3(0.5f));
Object3D third(&first);
third.translate(Vector3::xAxis(5.0f));
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<Matrix4>{
secondExpected, thirdExpected, secondExpected, firstExpected, thirdExpected
}));
}
void ObjectTest::setClean() {
Scene3D scene;

Loading…
Cancel
Save