分离轴定理问题

时间:2013-01-11 02:02:19

标签: c# xna 2d game-physics

我目前正在尝试为轴对齐和定向边界框添加重叠测试器,但是当OBB的角度介于-10和+10之间时,解决方案似乎只能正常工作。当角度接近+90度时,碰撞区域似乎首先移动到OBB的右半部分,然后变得不存在。在90到270之间我无法获得重叠,然后当它绕过一个完整的360时,该区域再次准确地记录。

关于这个问题的任何启示都会很棒。我使用正X来增加CCW 0度。

干杯。

编辑:做了一点研究并意识到将矢量投影到另一个上需要的不仅仅是一个点积。可以任何人给我一个正确版本的检查轴方法下面非常漂亮请:)

编辑2:实际上我认为只是一个点积,因为投影的矢量是单位长度。

public static bool overlapAABB_OBB(AABB a, OBB o)
    {
        float rads = MathHelper.ToRadians(-o.angle);
        T = Vector2.Subtract(o.position, a.position);
        Ax.X = 1;
        Ax.Y = 0;
        Ay.X = 0;
        Ay.Y = 1;
        Ox.X = (float)Math.Cos(rads);
        Ox.Y = (float)Math.Sin(rads);
        Oy.X = -Ox.Y;
        Oy.Y = Ox.X;
        if (checkAX(a, o) &&
           checkAY(a, o) &&
           checkOX(a, o) &&
           checkOY(a, o))
            return true;
        else
            return false;
    }

    private static bool checkAX(AABB a, OBB o)
    {
        float TAx = Vector2.Dot(T, Ax);
        float WoOxAx = Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ax);
        float HoOyAx = Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ax);
        if (TAx > a.halfWidth + WoOxAx + HoOyAx)
            return false;
        else
            return true;
    }

    private static bool checkAY(AABB a, OBB o)
    {
        float TAy = Vector2.Dot(T, Ay);
        float WoOxAy = Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ay);
        float HoOyAy = Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ay);
        if (TAy > a.halfHeight + WoOxAy + HoOyAy)
            return false;
        else
            return true;
    }

    private static bool checkOX(AABB a, OBB o)
    {
        float TOx = Vector2.Dot(T, Ox);
        float WaAxOx = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Ox);
        float HaAyOx = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Ox);
        if (TOx > o.halfHeight + WaAxOx + HaAyOx)
            return false;
        else
            return true;
    }

    private static bool checkOY(AABB a, OBB o)
    {
        float TOy = Vector2.Dot(T, Oy);
        float WaAxOy = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Oy);
        float HaAyOy = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Oy);
        if (TOy > o.halfHeight + WaAxOy + HaAyOy)
            return false;
        else
            return true;
    }

2 个答案:

答案 0 :(得分:1)

我在GameDev.stackexchange上发布了这个问题,并从rraallvv收到了这个答案,该答案解决了这个问题。

当两个矢量之间的角度大于90º时,

点积为负,为了使代码正常工作,您需要获取点积的绝对值。

//...
private static bool checkAX(AABB a, OBB o)
{
    float TAx    = Math.Abs( Vector2.Dot(T, Ax) );
    float WoOxAx = Math.Abs( Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ax) );
    float HoOyAx = Math.Abs( Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ax) );
    if (TAx > a.halfWidth + WoOxAx + HoOyAx)
        return false;
    else
        return true;
}
//...

这也适用于checkAYcheckOXcheckOY

答案 1 :(得分:0)

除了Mazk1985提供的修复外,checkOX()函数还有一个拼写错误。 o.halfHeight应为o.halfWidth,如下所示:

private static bool checkOX(AABB a, OBB o)
{
    float TOx = Vector2.Dot(T, Ox);
    float WaAxOx = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Ox);
    float HaAyOx = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Ox);
    if (TOx > o.halfWidth + WaAxOx + HaAyOx)
        return false;
    else
        return true;
}