mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
473 lines
19 KiB
473 lines
19 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
#include <sstream> |
|
#include <Corrade/TestSuite/Tester.h> |
|
|
|
#include "Magnum/SceneGraph/MatrixTransformation3D.h" |
|
#include "Magnum/SceneGraph/Scene.h" |
|
|
|
namespace Magnum { namespace SceneGraph { namespace Test { |
|
|
|
class ObjectTest: public TestSuite::Tester { |
|
public: |
|
ObjectTest(); |
|
|
|
void parenting(); |
|
void scene(); |
|
void setParentKeepTransformation(); |
|
void absoluteTransformation(); |
|
void transformations(); |
|
void transformationsRelative(); |
|
void transformationsOrphan(); |
|
void transformationsDuplicate(); |
|
void setClean(); |
|
void setCleanListHierarchy(); |
|
void setCleanListBulk(); |
|
}; |
|
|
|
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D; |
|
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D; |
|
|
|
class CachingObject: public Object3D, AbstractFeature3D { |
|
public: |
|
CachingObject(Object3D* parent = nullptr): Object3D(parent), AbstractFeature3D(*this) { |
|
setCachedTransformations(CachedTransformation::Absolute); |
|
} |
|
|
|
Matrix4 cleanedAbsoluteTransformation; |
|
|
|
protected: |
|
void clean(const Matrix4& absoluteTransformation) override { |
|
cleanedAbsoluteTransformation = absoluteTransformation; |
|
} |
|
}; |
|
|
|
ObjectTest::ObjectTest() { |
|
addTests<ObjectTest>({&ObjectTest::parenting, |
|
&ObjectTest::scene, |
|
&ObjectTest::setParentKeepTransformation, |
|
&ObjectTest::absoluteTransformation, |
|
&ObjectTest::transformations, |
|
&ObjectTest::transformationsRelative, |
|
&ObjectTest::transformationsOrphan, |
|
&ObjectTest::transformationsDuplicate, |
|
&ObjectTest::setClean, |
|
&ObjectTest::setCleanListHierarchy, |
|
&ObjectTest::setCleanListBulk}); |
|
} |
|
|
|
void ObjectTest::parenting() { |
|
Object3D root; |
|
|
|
Object3D* childOne = new Object3D(&root); |
|
Object3D* childTwo = new Object3D(&root); |
|
|
|
CORRADE_VERIFY(childOne->parent() == &root); |
|
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); |
|
CORRADE_VERIFY(childOne->parent() == &root); |
|
|
|
/* In fact, cyclic dependencies are not allowed at all */ |
|
root.setParent(childTwo); |
|
CORRADE_VERIFY(root.parent() == nullptr); |
|
|
|
/* Reparent to another */ |
|
childTwo->setParent(childOne); |
|
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->hasChildren()); |
|
} |
|
|
|
void ObjectTest::scene() { |
|
Scene3D scene; |
|
CORRADE_VERIFY(scene.scene() == &scene); |
|
|
|
Object3D* childOne = new Object3D(&scene); |
|
Object3D* childTwo = new Object3D(childOne); |
|
|
|
Object3D orphan; |
|
Object3D* childOfOrphan = new Object3D(&orphan); |
|
|
|
CORRADE_VERIFY(childTwo->scene() == &scene); |
|
CORRADE_VERIFY(childOfOrphan->scene() == nullptr); |
|
} |
|
|
|
void ObjectTest::setParentKeepTransformation() { |
|
Object3D root; |
|
root.rotateZ(Deg(35.0f)); |
|
|
|
Object3D* childOne = new Object3D(&root); |
|
Object3D* childTwo = new Object3D(&root); |
|
|
|
childOne->translate(Vector3::xAxis(2.0f)); |
|
childTwo->rotateY(Deg(90.0f)); |
|
|
|
/* Old parent and new parent must share the same scene */ |
|
std::ostringstream o; |
|
Error::setOutput(&o); |
|
Scene3D scene; |
|
childOne->setParentKeepTransformation(&scene); |
|
CORRADE_COMPARE(o.str(), "SceneGraph::Object::setParentKeepTransformation(): both parents must be in the same scene\n"); |
|
CORRADE_COMPARE(childOne->parent(), &root); |
|
|
|
/* Reparent to another and keep absolute transformation */ |
|
auto transformation = childOne->absoluteTransformation(); |
|
childOne->setParentKeepTransformation(childTwo); |
|
CORRADE_VERIFY(childOne->parent() == childTwo); |
|
CORRADE_COMPARE(childOne->absoluteTransformation(), transformation); |
|
} |
|
|
|
void ObjectTest::absoluteTransformation() { |
|
Scene3D s; |
|
|
|
/* Proper transformation composition */ |
|
Object3D o(&s); |
|
o.translate(Vector3::xAxis(2.0f)); |
|
CORRADE_COMPARE(o.transformation(), Matrix4::translation(Vector3::xAxis(2.0f))); |
|
CORRADE_COMPARE(o.transformation(), o.transformationMatrix()); |
|
Object3D o2(&o); |
|
o2.rotateY(Deg(90.0f)); |
|
CORRADE_COMPARE(o2.absoluteTransformation(), |
|
Matrix4::translation(Vector3::xAxis(2.0f))*Matrix4::rotationY(Deg(90.0f))); |
|
CORRADE_COMPARE(o2.absoluteTransformation(), o2.absoluteTransformationMatrix()); |
|
|
|
/* Transformation of root object */ |
|
Object3D o3; |
|
o3.translate({1.0f, 2.0f, 3.0f}); |
|
CORRADE_COMPARE(o3.absoluteTransformation(), Matrix4::translation({1.0f, 2.0f, 3.0f})); |
|
} |
|
|
|
void ObjectTest::transformations() { |
|
Scene3D s; |
|
|
|
Matrix4 initial = Matrix4::rotationX(Deg(90.0f)).inverted(); |
|
|
|
/* Empty list */ |
|
#ifndef MAGNUM_BUILD_DEPRECATED |
|
CORRADE_COMPARE(s.transformations({}, initial), std::vector<Matrix4>()); |
|
#else |
|
CORRADE_COMPARE(s.transformations(std::vector<std::reference_wrapper<Object3D>>{}, initial), std::vector<Matrix4>()); |
|
#endif |
|
|
|
/* Scene alone */ |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::reference_wrapper<Object3D>(s)}, initial), std::vector<Matrix4>{initial}); |
|
|
|
/* One object */ |
|
Object3D first(&s); |
|
first.rotateZ(Deg(30.0f)); |
|
Object3D second(&first); |
|
second.scale(Vector3(0.5f)); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(second)}, initial), std::vector<Matrix4>{ |
|
initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)) |
|
}); |
|
|
|
/* One object and scene */ |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(second), std::reference_wrapper<Object3D>(s)}, initial), (std::vector<Matrix4>{ |
|
initial*Matrix4::rotationZ(Deg(30.0f))*Matrix4::scaling(Vector3(0.5f)), |
|
initial |
|
})); |
|
|
|
/* Two objects with foreign joint */ |
|
Object3D third(&first); |
|
third.translate(Vector3::xAxis(5.0f)); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(second), std::ref(third)}, initial), (std::vector<Matrix4>{ |
|
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 */ |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(second), std::ref(third), std::ref(first)}, initial), (std::vector<Matrix4>{ |
|
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)), |
|
})); |
|
} |
|
|
|
void ObjectTest::transformationsRelative() { |
|
CORRADE_EXPECT_FAIL("Transformations not relative to scene are not yet implemented."); |
|
|
|
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)); |
|
|
|
/* Transformation relative to another object */ |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(second.transformations({std::ref(third)}), std::vector<Matrix4>{ |
|
Matrix4::scaling(Vector3(0.5f)).inverted()*Matrix4::translation(Vector3::xAxis(5.0f)) |
|
}); |
|
|
|
/* Transformation relative to another object, not part of any scene (but should work) */ |
|
Object3D orphanParent1; |
|
orphanParent1.rotate(Deg(31.0f), Vector3(1.0f).normalized()); |
|
Object3D orphanParent(&orphanParent1); |
|
Object3D orphan1(&orphanParent); |
|
orphan1.scale(Vector3::xScale(3.0f)); |
|
Object3D orphan2(&orphanParent); |
|
orphan2.translate(Vector3::zAxis(5.0f)); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(orphan1.transformations({std::ref(orphan2)}), std::vector<Matrix4>{ |
|
Matrix4::scaling(Vector3::xScale(3.0f)).inverted()*Matrix4::translation(Vector3::zAxis(5.0f)) |
|
}); |
|
} |
|
|
|
void ObjectTest::transformationsOrphan() { |
|
std::ostringstream o; |
|
Error::setOutput(&o); |
|
|
|
/* Transformation of objects not part of the same scene */ |
|
Scene3D s; |
|
Object3D orphan; |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(orphan)}), std::vector<Matrix4>()); |
|
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)); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
CORRADE_COMPARE(s.transformations({std::ref(second), std::ref(third), std::ref(second), std::ref(first), std::ref(third)}), (std::vector<Matrix4>{ |
|
secondExpected, thirdExpected, secondExpected, firstExpected, thirdExpected |
|
})); |
|
} |
|
|
|
void ObjectTest::setClean() { |
|
Scene3D scene; |
|
|
|
class CachingFeature: public AbstractFeature3D { |
|
public: |
|
CachingFeature(AbstractObject3D& object): AbstractFeature3D(object) { |
|
setCachedTransformations(CachedTransformation::Absolute); |
|
} |
|
|
|
Matrix4 cleanedAbsoluteTransformation; |
|
|
|
void clean(const Matrix4& absoluteTransformation) override { |
|
cleanedAbsoluteTransformation = absoluteTransformation; |
|
} |
|
}; |
|
|
|
class CachingInvertedFeature: public AbstractFeature3D { |
|
public: |
|
CachingInvertedFeature(AbstractObject3D& object): AbstractFeature3D(object) { |
|
setCachedTransformations(CachedTransformation::InvertedAbsolute); |
|
} |
|
|
|
Matrix4 cleanedInvertedAbsoluteTransformation; |
|
|
|
void cleanInverted(const Matrix4& invertedAbsoluteTransformation) override { |
|
cleanedInvertedAbsoluteTransformation = invertedAbsoluteTransformation; |
|
} |
|
}; |
|
|
|
CachingObject* childOne = new CachingObject(&scene); |
|
childOne->scale(Vector3(2.0f)); |
|
|
|
CachingObject* childTwo = new CachingObject(childOne); |
|
childTwo->translate(Vector3::xAxis(1.0f)); |
|
CachingFeature* childTwoFeature = new CachingFeature(*childTwo); |
|
CachingInvertedFeature* childTwoFeature2 = new CachingInvertedFeature(*childTwo); |
|
|
|
CachingObject* childThree = new CachingObject(childTwo); |
|
childThree->rotate(Deg(90.0f), Vector3::yAxis()); |
|
|
|
/* Object is dirty at the beginning */ |
|
CORRADE_VERIFY(scene.isDirty()); |
|
CORRADE_VERIFY(childOne->isDirty()); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
|
|
/* Clean the object and all its dirty parents (but not children) */ |
|
childTwo->setClean(); |
|
CORRADE_VERIFY(!scene.isDirty()); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
CORRADE_VERIFY(!childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
|
|
/* Verify the right matrices were passed */ |
|
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, childOne->absoluteTransformationMatrix()); |
|
CORRADE_COMPARE(childTwo->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); |
|
CORRADE_COMPARE(childTwoFeature->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); |
|
CORRADE_COMPARE(childTwoFeature2->cleanedInvertedAbsoluteTransformation, childTwo->absoluteTransformationMatrix().inverted()); |
|
|
|
/* Mark object and all its children as dirty (but not parents) */ |
|
childTwo->setDirty(); |
|
CORRADE_VERIFY(!scene.isDirty()); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
|
|
/* If the object itself is already clean, it shouldn't clean it again */ |
|
childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
childOne->setClean(); |
|
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()); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
childTwo->setClean(); |
|
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); |
|
|
|
/* Remove object from tree => make it and its children dirty */ |
|
childThree->setClean(); |
|
childTwo->setParent(nullptr); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
|
|
/* Add object to tree => make it and its children dirty, don't touch parents */ |
|
childTwo->setParent(&scene); |
|
CORRADE_VERIFY(!scene.isDirty()); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
|
|
/* Set object transformation => make it and its children dirty (but not parents) */ |
|
childThree->setClean(); |
|
childTwo->setTransformation(Matrix4::translation(Vector3::xAxis(1.0f))); |
|
CORRADE_VERIFY(!scene.isDirty()); |
|
CORRADE_VERIFY(childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
} |
|
|
|
void ObjectTest::setCleanListHierarchy() { |
|
Scene3D scene; |
|
|
|
class CachingFeature: public AbstractFeature3D { |
|
public: |
|
CachingFeature(AbstractObject3D& object): AbstractFeature3D(object) { |
|
setCachedTransformations(CachedTransformation::Absolute); |
|
} |
|
|
|
Matrix4 cleanedAbsoluteTransformation; |
|
|
|
void clean(const Matrix4& absoluteTransformation) override { |
|
cleanedAbsoluteTransformation = absoluteTransformation; |
|
} |
|
}; |
|
|
|
CachingObject* childOne = new CachingObject(&scene); |
|
childOne->scale(Vector3(2.0f)); |
|
|
|
CachingObject* childTwo = new CachingObject(childOne); |
|
childTwo->translate(Vector3::xAxis(1.0f)); |
|
CachingFeature* childTwoFeature = new CachingFeature(*childTwo); |
|
|
|
CachingObject* childThree = new CachingObject(childTwo); |
|
childThree->rotate(Deg(90.0f), Vector3::yAxis()); |
|
|
|
/* Clean the object and all its dirty parents (but not children) */ |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
Scene3D::setClean({std::reference_wrapper<Object3D>(*childTwo)}); |
|
CORRADE_VERIFY(!scene.isDirty()); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
CORRADE_VERIFY(!childTwo->isDirty()); |
|
CORRADE_VERIFY(childThree->isDirty()); |
|
|
|
/* Verify the right matrices were passed */ |
|
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, childOne->absoluteTransformationMatrix()); |
|
CORRADE_COMPARE(childTwo->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); |
|
CORRADE_COMPARE(childTwoFeature->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); |
|
|
|
/* If the object itself is already clean, it shouldn't clean it again */ |
|
childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); |
|
CORRADE_VERIFY(!childOne->isDirty()); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
Scene3D::setClean({std::reference_wrapper<Object3D>(*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(); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
Scene3D::setClean({std::reference_wrapper<Object3D>(*childTwo)}); |
|
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); |
|
} |
|
|
|
void ObjectTest::setCleanListBulk() { |
|
/* Verify it doesn't crash when passed empty list */ |
|
#ifndef MAGNUM_BUILD_DEPRECATED |
|
Object3D::setClean({}); |
|
#else |
|
Object3D::setClean(std::vector<std::reference_wrapper<Object3D>>{}); |
|
#endif |
|
|
|
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); |
|
|
|
/* 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()); |
|
/* GCC 4.4 has explicit constructor for std::reference_wrapper. WHY ON EARTH. WHY. */ |
|
Object3D::setClean({std::ref(a), std::ref(b), std::ref(c), std::reference_wrapper<Object3D>(d), std::ref(e)}); |
|
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))); |
|
} |
|
|
|
}}} |
|
|
|
CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::ObjectTest)
|
|
|