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 {
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);
}
@ -44,11 +44,11 @@ template<UnsignedInt dimensions> const ShapeGroup<dimensions>* AbstractShape<dim
}
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 {
return Implementation::collides(abstractTransformedShape(), other->abstractTransformedShape());
template<UnsignedInt dimensions> bool AbstractShape<dimensions>::collides(const AbstractShape<dimensions>& other) const {
return Implementation::collides(abstractTransformedShape(), other.abstractTransformedShape());
}
template<UnsignedInt dimensions> void AbstractShape<dimensions>::markDirty() {

12
src/Shapes/AbstractShape.h

@ -37,8 +37,8 @@
namespace Magnum { namespace Shapes {
namespace Implementation {
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const Shapes::AbstractShape<dimensions>* shape) {
return shape->abstractTransformedShape();
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>& getAbstractShape(const Shapes::AbstractShape<dimensions>& shape) {
return shape.abstractTransformedShape();
}
}
@ -50,7 +50,7 @@ brief introduction.
@see AbstractShape2D, AbstractShape3D
*/
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:
enum: UnsignedInt {
@ -79,7 +79,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: publi
* @param object Object holding this feature
* @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
@ -99,14 +99,14 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT AbstractShape: publi
*
* Default implementation returns false.
*/
bool collides(const AbstractShape<dimensions>* other) const;
bool collides(const AbstractShape<dimensions>& other) const;
protected:
/** Marks also the group as dirty */
void markDirty() override;
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 */

6
src/Shapes/Composition.cpp

@ -132,7 +132,7 @@ template<UnsignedInt dimensions> Composition<dimensions> Composition<dimensions>
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 */
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
exists), do it directly, recurse instead. */
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);
/* 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
collision on the left child. */
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);
}

19
src/Shapes/Composition.h

@ -42,11 +42,11 @@ namespace Magnum { namespace Shapes {
namespace Implementation {
template<class> struct ShapeHelper;
template<UnsignedInt dimensions> inline AbstractShape<dimensions>* getAbstractShape(Composition<dimensions>& group, std::size_t i) {
return group._shapes[i];
template<UnsignedInt dimensions> inline AbstractShape<dimensions>& getAbstractShape(Composition<dimensions>& group, std::size_t i) {
return *group._shapes[i];
}
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>* getAbstractShape(const Composition<dimensions>& group, std::size_t i) {
return group._shapes[i];
template<UnsignedInt dimensions> inline const AbstractShape<dimensions>& getAbstractShape(const Composition<dimensions>& group, std::size_t 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.
*/
template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
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 Implementation::AbstractShape<dimensions>& Implementation::getAbstractShape<>(Composition<dimensions>&, std::size_t);
friend const Implementation::AbstractShape<dimensions>& Implementation::getAbstractShape<>(const Composition<dimensions>&, std::size_t);
friend struct Implementation::ShapeHelper<Composition<dimensions>>;
public:
@ -142,8 +142,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
#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 {
#endif
Implementation::Shape<T> a(other);
return collides(&a);
return collides(Implementation::Shape<T>(other));
}
private:
@ -152,11 +151,11 @@ template<UnsignedInt dimensions> class MAGNUM_SHAPES_EXPORT Composition {
CompositionOperation operation;
};
bool collides(const Implementation::AbstractShape<dimensions>* a) const {
bool collides(const Implementation::AbstractShape<dimensions>& a) const {
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&) {
return 1;

16
src/Shapes/Implementation/CollisionDispatch.cpp

@ -35,13 +35,13 @@
namespace Magnum { namespace Shapes { namespace Implementation {
template<> bool collides(const AbstractShape<2>* const a, const AbstractShape<2>* const b) {
if(a->type() < b->type()) return collides(b, a);
template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) {
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) \
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, Line, Line2D)
_c(Sphere, Sphere2D, LineSegment, LineSegment2D)
@ -57,13 +57,13 @@ template<> bool collides(const AbstractShape<2>* const a, const AbstractShape<2>
return false;
}
template<> bool collides(const AbstractShape<3>* const a, const AbstractShape<3>* const b) {
if(a->type() < b->type()) return collides(b, a);
template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) {
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) \
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, Line, Line3D)
_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
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
Shapes::ShapeGroup3D shapes;
Object3D* object;
Object3D object;
auto shape = new Shapes::Shape<Shapes::Sphere3D>(object, {{}, 0.75f}, &shapes);
Shapes::AbstractShape3D* firstCollision = shapes.firstCollision(shape);
@ -75,17 +75,17 @@ template<class T> class Shape: public AbstractShape<T::Dimensions> {
* @param shape Shape
* @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);
}
/** @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));
}
/** @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 */
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;
private:
const Implementation::AbstractShape<T::Dimensions>* abstractTransformedShape() const override {
return &_transformedShape;
const Implementation::AbstractShape<T::Dimensions>& abstractTransformedShape() const override {
return _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) {
Implementation::ShapeHelper<T>::set(*this, shape);
this->object()->setDirty();
this->object().setDirty();
return *this;
}
template<class T> inline const T& Shape<T>::transformedShape() {
this->object()->setClean();
this->object().setClean();
return _transformedShape.shape;
}

8
src/Shapes/ShapeGroup.cpp

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

16
src/Shapes/Test/ShapeTest.cpp

@ -60,11 +60,11 @@ void ShapeTest::clean() {
ShapeGroup3D shapes;
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));
Object3D b(&scene);
new Shapes::Shape<Shapes::Point3D>(&b, &shapes);
new Shapes::Shape<Shapes::Point3D>(b, &shapes);
/* Everything is dirty at the beginning */
CORRADE_VERIFY(shapes.isDirty());
@ -100,13 +100,13 @@ void ShapeTest::firstCollision() {
ShapeGroup3D shapes;
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);
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);
new Shape<Shapes::Composition3D>(&c, &shapes);
Shape<Shapes::Composition3D> cShape(c, &shapes);
/* No collisions initially */
CORRADE_VERIFY(!shapes.firstCollision(aShape));
@ -118,8 +118,8 @@ void ShapeTest::firstCollision() {
/* Collision */
CORRADE_VERIFY(shapes.isDirty());
CORRADE_VERIFY(shapes.firstCollision(aShape) == bShape);
CORRADE_VERIFY(shapes.firstCollision(bShape) == aShape);
CORRADE_VERIFY(shapes.firstCollision(aShape) == &bShape);
CORRADE_VERIFY(shapes.firstCollision(bShape) == &aShape);
CORRADE_VERIFY(!shapes.isDirty());
}
@ -129,7 +129,7 @@ void ShapeTest::shapeGroup() {
/* Verify construction */
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);
/* Verify the original shape is updated */

Loading…
Cancel
Save