如何找到旋转方块的最小平移矢量?

时间:2018-07-03 17:41:29

标签: c# collision-detection separating-axis-theorem

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

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

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

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对象的数组,这四个Vector对象是标准化的(单位)矢量,代表每个边缘的法线(Box.edgeNormals)。

然后我为每个框调用此函数以检查是否存在碰撞:

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

collision是一个包含观察者框和观察者框的两元素数组。


那么我该如何计算MTV?

我该如何将其应用到盒子上?

  • 只用MTV翻译一个盒子吗?
  • 用一半的MTV将每个盒子彼此隔开吗?
  • 以某种方式权衡根据盒子的某些属性(质量/速度)将多少MTV应用于每个盒子?

0 个答案:

没有答案