0

我正在编写一个简单的游戏引擎,经过大量重新思考/重构后,我选择了一种基于组件的架构(严格来说不是 ECS,但它也不再基于继承)。所以我的世界中的一切都是一个实体,每个实体都有一堆组件。我游戏中的每个系统/子系统都会扫描一个实体以查找它感兴趣的一系列组件,并执行一些相关的计算。

到目前为止,一切都很好。引擎的基本架构可以在这里看到:

现在,每个可碰撞的实体都有一个碰撞组件(以及位置/移动/刚体组件),因此物理系统需要获取该组件并使用它来提供其碰撞检测算法,以便生成接触数据用于解决碰撞。

我被困在以下问题上:碰撞检测算法处理不同的几何形状:盒子、球体、平面和射线(截至目前),但我不想有一个 spherecollisioncomponent 和一个 boxcollisioncomponent,至少我不'不希望它们不相关,但我希望它们共享一些共同的基类。

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));
}

那么我怎样才能以一种优雅而健壮的方式解决这个问题呢?

4

0 回答 0