2

In an arbitrary physics engine for a game, there exists a "Shape" superclass and its derived subclasses such as "AABB" or "Triangle". Collision detection methods between each pair is unique, for example the AABB-Sphere test will obviously be different from the Triangle-AABB test. If I have two collections of shapes as such and I wish to check some collisions between them:

// somewhere in the program
Shape* shape_a;
Shape* shape_b;

....

if (shape_a->intersects(shape_b)) {
    // do something
}

How can specific collision checks (e.g. AABB-ABBB, or AABB-Sphere) be performed? For example, if shape_a points to a derived Triangle object, and shape_b performs to a derived AABB object, how can the intersects function correctly compare a Triangle and AABB object? My current implementation is as follows but it does not compile as an include loop is created (likely due to bad OOP practice).

Shape.h

#include "AABB.h"
#include "triangle.h"

class Shape {
public:
    virtual bool intersects(Shape* shape) = 0;
    virtual bool intersects(AABB aabb) = 0;
    virtual bool intersects(Triangle tri) = 0;
}

AABB.h

#include "shape.h"

class AABB : public Shape {
    // overriden functions
    bool intersects(Shape* shape);
    bool intersects(AABB aabb); // aabb-aabb
    bool intersects(Triangle tri); // aabb-tri
}

triangle.h

#include "shape.h"

class Triangle : public Shape {
    // overriden functions
    bool intersects(Shape* shape);
    bool intersects(AABB aabb); // tri-aabb
    bool intersects(Triangle tri); // tri-tri
}

The implementation for an intersects(Shape* shape) function looks like:

// in AABB.cpp
bool intersects(Shape* shape) {
     return shape.intersects(*this); // where *this is an AABB object
}

And of course, I want to avoid code duplication: the tri-aabb test is the same as the aabb-tri test. Perhaps I am writing code that is fundamentally flawed and is bad OOP practice. In any case, I'd appreciate any help with this problem!

John181522
  • 23
  • 4
  • you can do bool `intersects(AABB *aabb);` ie pass in pointers not the full class. Now you can forward declare AABB just saying `class AABB;` https://stackoverflow.com/questions/4757565/what-are-forward-declarations-in-c – pm100 Jul 19 '17 at 23:38
  • My gut reaction is that the knowledge of the shape should be hidden inside the shape so that there isn't an N^2/2 explosion of shape specific methods. Intersection is such a basic unit of game programming that it would not surprise me that there would be a pattern for it. – EvilTeach Jul 19 '17 at 23:45
  • ah actually that works @pm100 – John181522 Jul 19 '17 at 23:56

1 Answers1

0

To avoid the include loop you can just forward-declare the AABB and Triangle classes in shape.h:

class AABB;
class Triangle;

To avoid duplicating code based on parameter order you can have a separate function with a canonical order for each overloading pair, and call it with the different orders from the member functions:

bool intersects( AABB *, Triangle * );

AABB::intersects( Triangle *t ) { return intersects( this, t ); }
Triangle::intersects( AABB *b ) { return intersects( b, this ); }
Alex
  • 780
  • 4
  • 12