Browse Source

Reducing pointer chasings, part 3d: less pointer passing in Shapes.

Mostly just adapted to SceneGraph changes, functions not expecting
nullptr are now taking/returning reference.
pull/277/head
Vladimír Vondruš 13 years ago
parent
commit
f669dd7c23
  1. 8
      src/Shapes/AbstractShape.cpp
  2. 12
      src/Shapes/AbstractShape.h
  3. 6
      src/Shapes/Composition.cpp
  4. 19
      src/Shapes/Composition.h
  5. 16
      src/Shapes/Implementation/CollisionDispatch.cpp
  6. 2
      src/Shapes/Implementation/CollisionDispatch.h
  7. 16
      src/Shapes/Shape.h
  8. 8
      src/Shapes/ShapeGroup.cpp
  9. 2
      src/Shapes/ShapeGroup.h
  10. 16
      src/Shapes/Test/ShapeTest.cpp

8
src/Shapes/AbstractShape.cpp

@ -31,7 +31,7 @@
namespace Magnum { namespace Shapes { namespace Magnum { namespace Shapes {
template<UnsignedInt dimensions> AbstractShape<dimensions>::AbstractShape(SceneGraph::AbstractObject<dimensions, Float>* object, ShapeGroup<dimensions>* group): SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float>(object, group) { template<UnsignedInt dimensions> AbstractShape<dimensions>::AbstractShape(SceneGraph::AbstractObject<dimensions, Float>& object, ShapeGroup<dimensions>* group): SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float>(object, group) {
SceneGraph::AbstractFeature<dimensions, Float>::setCachedTransformations(SceneGraph::CachedTransformation::Absolute); SceneGraph::AbstractFeature<dimensions, Float>::setCachedTransformations(SceneGraph::CachedTransformation::Absolute);
} }
@ -44,11 +44,11 @@ template<UnsignedInt dimensions> const ShapeGroup<dimensions>* AbstractShape<dim
} }
template<UnsignedInt dimensions> auto AbstractShape<dimensions>::type() const -> Type { template<UnsignedInt dimensions> auto AbstractShape<dimensions>::type() const -> Type {
return abstractTransformedShape()->type(); return abstractTransformedShape().type();
} }
template<UnsignedInt dimensions> bool AbstractShape<dimensions>::collides(const AbstractShape<dimensions>* other) const { template<UnsignedInt dimensions> bool AbstractShape<dimensions>::collides(const AbstractShape<dimensions>& other) const {
return Implementation::collides(abstractTransformedShape(), other->abstractTransformedShape()); return Implementation::collides(abstractTransformedShape(), other.abstractTransformedShape());
} }
template<UnsignedInt dimensions> void AbstractShape<dimensions>::markDirty() { template<UnsignedInt dimensions> void AbstractShape<dimensions>::markDirty() {

12
src/Shapes/AbstractShape.h

@ -37,8 +37,8 @@
namespace Magnum { namespace Shapes { namespace Magnum { namespace Shapes {
namespace Implementation { namespace Implementation {
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const Shapes::AbstractShape<dimensions>* shape) { template<UnsignedInt dimensions> inline const AbstractShape<dimensions>& getAbstractShape(const Shapes::AbstractShape<dimensions>& shape) {
return shape->abstractTransformedShape(); return shape.abstractTransformedShape();
} }
} }
@ -50,7 +50,7 @@ brief introduction.
@see AbstractShape2D, AbstractShape3D @see AbstractShape2D, AbstractShape3D
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: public SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float> { template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: public SceneGraph::AbstractGroupedFeature<dimensions, AbstractShape<dimensions>, Float> {
friend const Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(const AbstractShape<dimensions>*); friend const Implementation::AbstractShape<dimensions>& Implementation::getAbstractShape<>(const AbstractShape<dimensions>&);
public: public:
enum: UnsignedInt { enum: UnsignedInt {
@ -79,7 +79,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: publi
* @param object Object holding this feature * @param object Object holding this feature
* @param group Group this shape belongs to * @param group Group this shape belongs to
*/ */
explicit AbstractShape(SceneGraph::AbstractObject<dimensions, Float>* object, ShapeGroup<dimensions>* group = nullptr); explicit AbstractShape(SceneGraph::AbstractObject<dimensions, Float>& object, ShapeGroup<dimensions>* group = nullptr);
/** /**
* @brief Shape group containing this shape * @brief Shape group containing this shape
@ -99,14 +99,14 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: publi
* *
* Default implementation returns false. * Default implementation returns false.
*/ */
bool collides(const AbstractShape<dimensions>* other) const; bool collides(const AbstractShape<dimensions>& other) const;
protected: protected:
/** Marks also the group as dirty */ /** Marks also the group as dirty */
void markDirty() override; void markDirty() override;
private: private:
virtual const Implementation::AbstractShape<dimensions> MAGNUM_SHAPES_LOCAL * abstractTransformedShape() const = 0; virtual const Implementation::AbstractShape<dimensions> MAGNUM_SHAPES_LOCAL & abstractTransformedShape() const = 0;
}; };
/** @brief Base class for two-dimensional object shapes */ /** @brief Base class for two-dimensional object shapes */

6
src/Shapes/Composition.cpp

@ -132,7 +132,7 @@ template<UnsignedInt dimensions> Composition<dimensions> Composition<dimensions>
return out; return out;
} }
template<UnsignedInt dimensions> bool Composition<dimensions>::collides(const Implementation::AbstractShape<dimensions>* const a, const std::size_t node, const std::size_t shapeBegin, const std::size_t shapeEnd) const { template<UnsignedInt dimensions> bool Composition<dimensions>::collides(const Implementation::AbstractShape<dimensions>& a, const std::size_t node, const std::size_t shapeBegin, const std::size_t shapeEnd) const {
/* Empty group */ /* Empty group */
if(shapeBegin == shapeEnd) return false; if(shapeBegin == shapeEnd) return false;
@ -141,7 +141,7 @@ template<UnsignedInt dimensions> bool Composition<dimensions>::collides(const Im
/* Collision on the left child. If the node is leaf one (no left child /* Collision on the left child. If the node is leaf one (no left child
exists), do it directly, recurse instead. */ exists), do it directly, recurse instead. */
const bool collidesLeft = (_nodes[node].rightNode == 0 || _nodes[node].rightNode == 2) ? const bool collidesLeft = (_nodes[node].rightNode == 0 || _nodes[node].rightNode == 2) ?
Implementation::collides(a, _shapes[shapeBegin]) : Implementation::collides(a, *_shapes[shapeBegin]) :
collides(a, node+1, shapeBegin, shapeBegin+_nodes[node].rightShape); collides(a, node+1, shapeBegin, shapeBegin+_nodes[node].rightShape);
/* NOT operation */ /* NOT operation */
@ -155,7 +155,7 @@ template<UnsignedInt dimensions> bool Composition<dimensions>::collides(const Im
/* Now the collision result depends only on the right child. Similar to /* Now the collision result depends only on the right child. Similar to
collision on the left child. */ collision on the left child. */
return (_nodes[node].rightNode < 2) ? return (_nodes[node].rightNode < 2) ?
Implementation::collides(a, _shapes[shapeBegin+_nodes[node].rightShape]) : Implementation::collides(a, *_shapes[shapeBegin+_nodes[node].rightShape]) :
collides(a, node+_nodes[node].rightNode-1, shapeBegin+_nodes[node].rightShape, shapeEnd); collides(a, node+_nodes[node].rightNode-1, shapeBegin+_nodes[node].rightShape, shapeEnd);
} }

19
src/Shapes/Composition.h

@ -42,11 +42,11 @@ namespace Magnum { namespace Shapes {
namespace Implementation { namespace Implementation {
template<class> struct ShapeHelper; template<class> struct ShapeHelper;
template<UnsignedInt dimensions> inline AbstractShape<dimensions>* getAbstractShape(Composition<dimensions>& group, std::size_t i) { template<UnsignedInt dimensions> inline AbstractShape<dimensions>& getAbstractShape(Composition<dimensions>& group, std::size_t i) {
return group._shapes[i]; return *group._shapes[i];
} }
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const Composition<dimensions>& group, std::size_t i) { template<UnsignedInt dimensions> inline const AbstractShape<dimensions>& getAbstractShape(const Composition<dimensions>& group, std::size_t i) {
return group._shapes[i]; return *group._shapes[i];
} }
} }
@ -63,8 +63,8 @@ enum class CompositionOperation: UnsignedByte {
Result of logical operations on shapes. See @ref shapes for brief introduction. Result of logical operations on shapes. See @ref shapes for brief introduction.
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition { template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
friend Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(Composition<dimensions>&, std::size_t); friend Implementation::AbstractShape<dimensions>& Implementation::getAbstractShape<>(Composition<dimensions>&, std::size_t);
friend const Implementation::AbstractShape<dimensions>* Implementation::getAbstractShape<>(const Composition<dimensions>&, std::size_t); friend const Implementation::AbstractShape<dimensions>& Implementation::getAbstractShape<>(const Composition<dimensions>&, std::size_t);
friend struct Implementation::ShapeHelper<Composition<dimensions>>; friend struct Implementation::ShapeHelper<Composition<dimensions>>;
public: public:
@ -142,8 +142,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
#else #else
template<class T> auto operator%(const T& other) const -> typename std::enable_if<std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<dimensions>::Type>::value, bool>::type { template<class T> auto operator%(const T& other) const -> typename std::enable_if<std::is_same<decltype(Implementation::TypeOf<T>::type()), typename Implementation::ShapeDimensionTraits<dimensions>::Type>::value, bool>::type {
#endif #endif
Implementation::Shape<T> a(other); return collides(Implementation::Shape<T>(other));
return collides(&a);
} }
private: private:
@ -152,11 +151,11 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
CompositionOperation operation; CompositionOperation operation;
}; };
bool collides(const Implementation::AbstractShape<dimensions>* a) const { bool collides(const Implementation::AbstractShape<dimensions>& a) const {
return collides(a, 0, 0, _shapeCount); return collides(a, 0, 0, _shapeCount);
} }
bool collides(const Implementation::AbstractShape<dimensions>* a, std::size_t node, std::size_t shapeBegin, std::size_t shapeEnd) const; bool collides(const Implementation::AbstractShape<dimensions>& a, std::size_t node, std::size_t shapeBegin, std::size_t shapeEnd) const;
template<class T> constexpr static std::size_t shapeCount(const T&) { template<class T> constexpr static std::size_t shapeCount(const T&) {
return 1; return 1;

16
src/Shapes/Implementation/CollisionDispatch.cpp

@ -35,13 +35,13 @@
namespace Magnum { namespace Shapes { namespace Implementation { namespace Magnum { namespace Shapes { namespace Implementation {
template<> bool collides(const AbstractShape<2>* const a, const AbstractShape<2>* const b) { template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) {
if(a->type() < b->type()) return collides(b, a); if(a.type() < b.type()) return collides(b, a);
switch(UnsignedInt(a->type())*UnsignedInt(b->type())) { switch(UnsignedInt(a.type())*UnsignedInt(b.type())) {
#define _c(aType, aClass, bType, bClass) \ #define _c(aType, aClass, bType, bClass) \
case UnsignedInt(ShapeDimensionTraits<2>::Type::aType)*UnsignedInt(ShapeDimensionTraits<2>::Type::bType): \ case UnsignedInt(ShapeDimensionTraits<2>::Type::aType)*UnsignedInt(ShapeDimensionTraits<2>::Type::bType): \
return static_cast<const Shape<aClass>*>(a)->shape % static_cast<const Shape<bClass>*>(b)->shape; return static_cast<const Shape<aClass>&>(a).shape % static_cast<const Shape<bClass>&>(b).shape;
_c(Sphere, Sphere2D, Point, Point2D) _c(Sphere, Sphere2D, Point, Point2D)
_c(Sphere, Sphere2D, Line, Line2D) _c(Sphere, Sphere2D, Line, Line2D)
_c(Sphere, Sphere2D, LineSegment, LineSegment2D) _c(Sphere, Sphere2D, LineSegment, LineSegment2D)
@ -57,13 +57,13 @@ template<> bool collides(const AbstractShape<2>* const a, const AbstractShape<2>
return false; return false;
} }
template<> bool collides(const AbstractShape<3>* const a, const AbstractShape<3>* const b) { template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) {
if(a->type() < b->type()) return collides(b, a); if(a.type() < b.type()) return collides(b, a);
switch(UnsignedInt(a->type())*UnsignedInt(b->type())) { switch(UnsignedInt(a.type())*UnsignedInt(b.type())) {
#define _c(aType, aClass, bType, bClass) \ #define _c(aType, aClass, bType, bClass) \
case UnsignedInt(ShapeDimensionTraits<3>::Type::aType)*UnsignedInt(ShapeDimensionTraits<3>::Type::bType): \ case UnsignedInt(ShapeDimensionTraits<3>::Type::aType)*UnsignedInt(ShapeDimensionTraits<3>::Type::bType): \
return static_cast<const Shape<aClass>*>(a)->shape % static_cast<const Shape<bClass>*>(b)->shape; return static_cast<const Shape<aClass>&>(a).shape % static_cast<const Shape<bClass>&>(b).shape;
_c(Sphere, Sphere3D, Point, Point3D) _c(Sphere, Sphere3D, Point, Point3D)
_c(Sphere, Sphere3D, Line, Line3D) _c(Sphere, Sphere3D, Line, Line3D)
_c(Sphere, Sphere3D, LineSegment, LineSegment3D) _c(Sphere, Sphere3D, LineSegment, LineSegment3D)

2
src/Shapes/Implementation/CollisionDispatch.h

@ -39,7 +39,7 @@ multiply the two numbers together and switch() on the result. Because of
multiplying two prime numbers, there is no ambiguity (the result is unique for multiplying two prime numbers, there is no ambiguity (the result is unique for
each combination). each combination).
*/ */
template<UnsignedInt dimensions> bool collides(const AbstractShape<dimensions>* a, const AbstractShape<dimensions>* b); template<UnsignedInt dimensions> bool collides(const AbstractShape<dimensions>& a, const AbstractShape<dimensions>& b);
}}} }}}

16
src/Shapes/Shape.h

@ -56,7 +56,7 @@ islands.
@code @code
Shapes::ShapeGroup3D shapes; Shapes::ShapeGroup3D shapes;
Object3D* object; Object3D object;
auto shape = new Shapes::Shape<Shapes::Sphere3D>(object, {{}, 0.75f}, &shapes); auto shape = new Shapes::Shape<Shapes::Sphere3D>(object, {{}, 0.75f}, &shapes);
Shapes::AbstractShape3D* firstCollision = shapes.firstCollision(shape); Shapes::AbstractShape3D* firstCollision = shapes.firstCollision(shape);
@ -75,17 +75,17 @@ template<class T> class Shape: public AbstractShape<T::Dimensions> {
* @param shape Shape * @param shape Shape
* @param group Group this shape belongs to * @param group Group this shape belongs to
*/ */
explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>* object, const T& shape, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) { explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>& object, const T& shape, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) {
Implementation::ShapeHelper<T>::set(*this, shape); Implementation::ShapeHelper<T>::set(*this, shape);
} }
/** @overload */ /** @overload */
explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>* object, T&& shape, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) { explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>& object, T&& shape, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) {
Implementation::ShapeHelper<T>::set(*this, std::move(shape)); Implementation::ShapeHelper<T>::set(*this, std::move(shape));
} }
/** @overload */ /** @overload */
explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>* object, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) {} explicit Shape(SceneGraph::AbstractObject<T::Dimensions, Float>& object, ShapeGroup<T::Dimensions>* group = nullptr): AbstractShape<T::Dimensions>(object, group) {}
/** @brief Shape */ /** @brief Shape */
const T& shape() const { return _shape.shape; } const T& shape() const { return _shape.shape; }
@ -110,8 +110,8 @@ template<class T> class Shape: public AbstractShape<T::Dimensions> {
void clean(const typename DimensionTraits<T::Dimensions, Float>::MatrixType& absoluteTransformationMatrix) override; void clean(const typename DimensionTraits<T::Dimensions, Float>::MatrixType& absoluteTransformationMatrix) override;
private: private:
const Implementation::AbstractShape<T::Dimensions>* abstractTransformedShape() const override { const Implementation::AbstractShape<T::Dimensions>& abstractTransformedShape() const override {
return &_transformedShape; return _transformedShape;
} }
Implementation::Shape<T> _shape, _transformedShape; Implementation::Shape<T> _shape, _transformedShape;
@ -119,12 +119,12 @@ template<class T> class Shape: public AbstractShape<T::Dimensions> {
template<class T> inline Shape<T>& Shape<T>::setShape(const T& shape) { template<class T> inline Shape<T>& Shape<T>::setShape(const T& shape) {
Implementation::ShapeHelper<T>::set(*this, shape); Implementation::ShapeHelper<T>::set(*this, shape);
this->object()->setDirty(); this->object().setDirty();
return *this; return *this;
} }
template<class T> inline const T& Shape<T>::transformedShape() { template<class T> inline const T& Shape<T>::transformedShape() {
this->object()->setClean(); this->object().setClean();
return _transformedShape.shape; return _transformedShape.shape;
} }

8
src/Shapes/ShapeGroup.cpp

@ -33,7 +33,7 @@ template<UnsignedInt dimensions> void ShapeGroup<dimensions>::setClean() {
if(!this->isEmpty()) { if(!this->isEmpty()) {
std::vector<SceneGraph::AbstractObject<dimensions, Float>*> objects(this->size()); std::vector<SceneGraph::AbstractObject<dimensions, Float>*> objects(this->size());
for(std::size_t i = 0; i != this->size(); ++i) for(std::size_t i = 0; i != this->size(); ++i)
objects[i] = (*this)[i]->object(); objects[i] = &(*this)[i].object();
SceneGraph::AbstractObject<dimensions, Float>::setClean(objects); SceneGraph::AbstractObject<dimensions, Float>::setClean(objects);
} }
@ -41,11 +41,11 @@ template<UnsignedInt dimensions> void ShapeGroup<dimensions>::setClean() {
dirty = false; dirty = false;
} }
template<UnsignedInt dimensions> AbstractShape<dimensions>* ShapeGroup<dimensions>::firstCollision(const AbstractShape<dimensions>* shape) { template<UnsignedInt dimensions> AbstractShape<dimensions>* ShapeGroup<dimensions>::firstCollision(const AbstractShape<dimensions>& shape) {
setClean(); setClean();
for(std::size_t i = 0; i != this->size(); ++i) for(std::size_t i = 0; i != this->size(); ++i)
if((*this)[i] != shape && (*this)[i]->collides(shape)) if(&(*this)[i] != &shape && (*this)[i].collides(shape))
return (*this)[i]; return &(*this)[i];
return nullptr; return nullptr;
} }

2
src/Shapes/ShapeGroup.h

@ -86,7 +86,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT ShapeGroup: public S
* collisions, returns `nullptr`. Calls setClean() before the * collisions, returns `nullptr`. Calls setClean() before the
* operation. * operation.
*/ */
AbstractShape<dimensions>* firstCollision(const AbstractShape<dimensions>* shape); AbstractShape<dimensions>* firstCollision(const AbstractShape<dimensions>& shape);
private: private:
bool dirty; bool dirty;

16
src/Shapes/Test/ShapeTest.cpp

@ -60,11 +60,11 @@ void ShapeTest::clean() {
ShapeGroup3D shapes; ShapeGroup3D shapes;
Object3D a(&scene); Object3D a(&scene);
auto shape = new Shapes::Shape<Shapes::Point3D>(&a, {{1.0f, -2.0f, 3.0f}}, &shapes); auto shape = new Shapes::Shape<Shapes::Point3D>(a, {{1.0f, -2.0f, 3.0f}}, &shapes);
a.scale(Vector3(-2.0f)); a.scale(Vector3(-2.0f));
Object3D b(&scene); Object3D b(&scene);
new Shapes::Shape<Shapes::Point3D>(&b, &shapes); new Shapes::Shape<Shapes::Point3D>(b, &shapes);
/* Everything is dirty at the beginning */ /* Everything is dirty at the beginning */
CORRADE_VERIFY(shapes.isDirty()); CORRADE_VERIFY(shapes.isDirty());
@ -100,13 +100,13 @@ void ShapeTest::firstCollision() {
ShapeGroup3D shapes; ShapeGroup3D shapes;
Object3D a(&scene); Object3D a(&scene);
auto aShape = new Shape<Shapes::Sphere3D>(&a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes); Shape<Shapes::Sphere3D> aShape(a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes);
Object3D b(&scene); Object3D b(&scene);
auto bShape = new Shape<Shapes::Point3D>(&b, {{3.0f, -2.0f, 3.0f}}, &shapes); Shape<Shapes::Point3D> bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes);
Object3D c(&scene); Object3D c(&scene);
new Shape<Shapes::Composition3D>(&c, &shapes); Shape<Shapes::Composition3D> cShape(c, &shapes);
/* No collisions initially */ /* No collisions initially */
CORRADE_VERIFY(!shapes.firstCollision(aShape)); CORRADE_VERIFY(!shapes.firstCollision(aShape));
@ -118,8 +118,8 @@ void ShapeTest::firstCollision() {
/* Collision */ /* Collision */
CORRADE_VERIFY(shapes.isDirty()); CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(shapes.firstCollision(aShape) == bShape); CORRADE_VERIFY(shapes.firstCollision(aShape) == &bShape);
CORRADE_VERIFY(shapes.firstCollision(bShape) == aShape); CORRADE_VERIFY(shapes.firstCollision(bShape) == &aShape);
CORRADE_VERIFY(!shapes.isDirty()); CORRADE_VERIFY(!shapes.isDirty());
} }
@ -129,7 +129,7 @@ void ShapeTest::shapeGroup() {
/* Verify construction */ /* Verify construction */
Object2D a(&scene); Object2D a(&scene);
auto shape = new Shape<Shapes::Composition2D>(&a, Shapes::Sphere2D({}, 0.5f) || Shapes::Point2D({0.25f, -1.0f})); auto shape = new Shape<Shapes::Composition2D>(a, Shapes::Sphere2D({}, 0.5f) || Shapes::Point2D({0.25f, -1.0f}));
CORRADE_COMPARE(shape->transformedShape().size(), 2); CORRADE_COMPARE(shape->transformedShape().size(), 2);
/* Verify the original shape is updated */ /* Verify the original shape is updated */

Loading…
Cancel
Save