在游戏的任意物理引擎中,存在“Shape”超类及其派生的子类,例如“AABB”或“Triangle”。每对之间的碰撞检测方法是唯一的,例如AABB-Sphere测试显然不同于Triangle-AABB测试。如果我有两个形状集合,我希望检查它们之间的一些碰撞:
// somewhere in the program
Shape* shape_a;
Shape* shape_b;
....
if (shape_a->intersects(shape_b)) {
// do something
}
如何执行特定的碰撞检查(例如AABB-ABBB或AABB-Sphere)?例如,如果shape_a指向派生的Triangle对象,并且shape_b执行派生的AABB对象,那么相交函数如何正确地比较Triangle和AABB对象?我当前的实现如下,但它不会编译,因为创建了一个包含循环(可能是由于糟糕的OOP实践)。
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
}
交叉(Shape * shape)函数的实现如下所示:
// in AABB.cpp
bool intersects(Shape* shape) {
return shape.intersects(*this); // where *this is an AABB object
}
当然,我想避免代码重复:tri-aabb测试与aabb-tri测试相同。也许我正在编写基本上有缺陷的代码并且是糟糕的OOP实践。在任何情况下,我都很感激这个问题的任何帮助!
答案 0 :(得分:0)
要避免include
循环,您只需在shape.h中向前声明AABB
和Triangle
类:
class AABB;
class Triangle;
为避免基于参数顺序重复代码,您可以为每个重载对设置一个具有规范顺序的单独函数,并使用成员函数中的不同顺序调用它:
bool intersects( AABB *, Triangle * );
AABB::intersects( Triangle *t ) { return intersects( this, t ); }
Triangle::intersects( AABB *b ) { return intersects( b, this ); }