我正在编写一个简单的游戏引擎,经过大量的重新思考/重构,我选择了一种基于组件的体系结构(严格来说不是ECS,但它也不是基于继承的)。因此,我世界中的所有事物都是一个实体,每个实体都有很多组件。我游戏中的每个系统/子系统都会在实体中扫描其感兴趣的一系列组件,并执行一些相关的计算。
到目前为止,一切都很好。可以看到引擎的基本架构here:
现在,每个可与之碰撞的实体都有一个碰撞组件(以及位置/运动/刚体组件),因此物理系统需要获取该组件并将其用于碰撞检测算法,以便生成接触用于解决冲突的数据。
我遇到了以下问题:碰撞检测算法处理不同的几何形状:盒子,球体,平面和射线(到目前为止),但我不想至少有一个球体碰撞组件和一个盒子碰撞组件我不希望它们无关,但我希望它们共享一些通用的基类。
class Sphere
{
public:
Sphere(float radius);
~Sphere();
float GetRadius() { return mRadius; }
private:
float mRadius;
};
class Box : public BoundingVolume
{
public:
Box(const XMFLOAT3 &halfSize);
~Box();
XMFLOAT3 const &GetHalfSize() const { return mHalfSize; }
private:
XMFLOAT3 mHalfSize;
};
很明显,每个组件都有一个不同的接口(盒子具有一半大小,球体具有半径等),并且不同的碰撞检测功能对它们中的每一个(盒子,盒子,盒子球体,球体球)的处理方式都非常不同。 )。
void CollisionSystem::BoxAndBoxCollision(const Box &box1, const Box &box2)
{
// contact data
XMFLOAT3 contactPoint;
XMFLOAT3 contactNormal;
float minOverlap = 100.0f;
// get axes for SAT test
std::vector<XMFLOAT3> axes = GetSATAxes(box1, box2);
int axisIndex = 0;
int index = 0;
for (XMFLOAT3 axis : axes)
{
if (XMVectorGetX(XMVector3Length(XMLoadFloat3(&axis))) < 0.01f)
{
index++;
continue;
}
float overlap = PerformSAT(axis, box1, box2);
if (overlap < 0) // found separating axis - early out
return;
if (overlap < minOverlap)
{
minOverlap = overlap;
axisIndex = index;
}
index++;
}
// other collision detection/generation code.....
// store contact
mContacts.push_back(new Contact(box1->GetRigidBody(), box2->GetRigidBody(), contactPoint, contactNormal, minOverlap, coefficientOfRestitution));
}
那么我该如何以一种优雅而强大的方式解决这个问题?