【问题标题】:Separating axis theorem implementation works not exact分离轴定理的实现并不精确
【发布时间】:2015-11-22 15:28:00
【问题描述】:
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 返回真。或者两个物体可以相互接触,因此 SAT 在实际碰撞时刻“迟到”。

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

有什么想法吗?

example 1

example 2

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

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

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

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

    i &lt; 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];
    

    第二个循环也是如此。

    【讨论】:

    • 抱歉,这只是发布的代码中的问题。在我的原始代码中,我做对了,但仍然出现此错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多