分离轴定理的实现并不精确

时间:2015-11-22 15:28:01

标签: c++ algorithm

bool SAT(body& b1, body& b2)
{
    for (int i = 0; i < b1.edges.size(); i++)
    {
        vec2& v1 = b1.edges[i];
        vec2& v2 = i < b1.edges.size() ? b1.edges[i + 1] : b1.edges[0];

        vec2 edge = v2 - v1;

        vec2 axis = edge.left();

        axis.normalize();

        vec2 proj1 = proj(b1, axis);
        vec2 proj2 = proj(b2, axis);

        float dist = interval_dist(proj1.x, proj1.y, proj2.x, proj2.y);

        if (dist > 0) return false;
    }

    for (int i = 0; i < b2.edges.size(); i++)
    {
        vec2& v1 = b2.edges[i];
        vec2& v2 = i < b2.edges.size() ? b2.edges[i + 1] : b2.edges[0];

        vec2 edge = v2 - v1;

        vec2 axis = edge.left();

        axis.normalize();

        vec2 proj1 = proj(b1, axis);
        vec2 proj2 = proj(b2, axis);

        float dist = interval_dist(proj1.x, proj1.y, proj2.x, proj2.y);

        if (dist > 0) return false;
    }


    return true;
}


float interval_dist(float minA, float maxA, float minB, float maxB)
{
    if (minA < minB) 
    {
        return minB - maxA;
    }
    else {
        return minA - maxB;
    }
}

vec2 proj(body& b, vec2& axis)
{
    float min = dot(b.edges[0], axis);
    float max = min;

    for (int i = 1; i < b.edges.size(); i++)
    {
        float dt = dot(b.edges[i], axis);

        if (dt < min)min = dt;

        if (dt > max)max = dt;
    }

    return vec2(min, max);
}

vec2::vec2 left()
{
    return vec2(-y, x);
}

我得到的结果可能与我在屏幕上看到的结果有很大不同。两个身体可能相距很远(虽然不是很多),但SAT返回true。或者两个身体可以相互进入,因此SAT对于实际的碰撞时刻来说是“迟到的”。

实体中的所有顶点都以逆时针方式的顺序定义,并转换为世界空间。

任何想法?

example 1

example 2

在检查SAT是否返回true之后立即在调试模式下截取屏幕截图。

1 个答案:

答案 0 :(得分:0)

SAT中,这似乎没有达到预期效果:

vec2& v2 = i < b1.edges.size() ? b1.edges[i + 1] : b1.edges[0];

i < b1.edges.size()将永远为真,因为i永远不会达到b1.edges.size()。相反,您可能希望与b1.edges.size() - 1进行比较:

vec2& v2 = i < b1.edges.size() - 1 ? b1.edges[i + 1] : b1.edges[0];

在第二个循环中也是如此。