1

我制作了一个碰撞检测算法,可以检测旋转的正方形是否发生碰撞。我正在努力理解我应该做些什么来解决这些冲突。我认为第一步是计算可以将两个正方形分开的最小平移向量(MTV)。

我认为做到这一点的方法是通过计算正方形投影在正在测试的轴上的重叠,然后使用最小重叠的长度和该轴的角度来形成 MTV。

问题是我的代码不能通过比较投影来工作,而是使用此代码来检测碰撞:

double DotProduct(Vector vector0, Vector vector1)
{
    return (vector0.X * vector1.X) + (vector0.Y * vector1.Y);
}

bool TestIfPointIsInFrontOfEdge(int edgeNormalIndex, int vertexToTestIndex, Box observerBox, Box observedBox)
{
    // if (v - a) · n > 0 then vertex is in front of edge
    // v is the vertex to test
    // a is a vertex on the edge that relates to the edge normal
    // n is the edge normal

    Vector v = new Vector(observedBox.vertices[vertexToTestIndex].X, observedBox.vertices[vertexToTestIndex].Y);
    Vector a = new Vector(observerBox.vertices[edgeNormalIndex].X, observerBox.vertices[edgeNormalIndex].Y);
    Vector n = observerBox.edgeNormals[edgeNormalIndex];

    Vector vMinusA = Vector.Subtract(v, a);
    double dotProduct = DotProduct(vMinusA, n);

    //Console.WriteLine(dotProduct);

    return dotProduct > 0;
}

bool TestIfAllPointsAreInFrontOfEdge(int edgeIndex, Box observerBox, Box observedBox)
{
    for (int i = 0; i < observedBox.vertices.Length; i++)
    {
        if (!TestIfPointIsInFrontOfEdge(edgeIndex, i, observerBox, observedBox))
        {
            return false;
        }
    }

    return true;
}

bool TestIfAllPointsAreInFrontOfAnyEdge(Box observerBox, Box observedBox)
{
    for (int i = 0; i < observerBox.edgeNormals.Length; i++)
    {
        if (TestIfAllPointsAreInFrontOfEdge(i, observerBox, observedBox))
            return true;
    }

    return false;
}

bool TestBoxOverlap(Box observerBox, Box observedBox)
{
    if (TestIfAllPointsAreInFrontOfAnyEdge(observerBox, observedBox) || TestIfAllPointsAreInFrontOfAnyEdge(observedBox, observerBox))
        return false;

    return true;
}

每个 Box 包含一个由四个 PointF 对象组成的数组,这些对象代表顶点 (Box.vertices)。它们还包含一个由四个 Vector 对象组成的数组,这些对象是归一化(单位)向量,表示每个边的法线(Box.edgeNormals)。

然后我为每个盒子调用这个函数来检查是否有碰撞:

if (TestBoxOverlap(observerBox, observedBox))
{
    narrowPhaseCollisionList.Add(collision);
}

碰撞是一个包含observerBox 和observedBox 的二元数组。


那么如何计算 MTV 呢?

另外我如何将它应用到盒子上?

  • 只用 MTV 翻译一个盒子?
  • 用一半的 MTV 将每个盒子彼此分开?
  • 不知何故,根据盒子的某些属性(质量/速度),将多少 MTV 应用于每个盒子?
4

0 回答 0