分离轴定理问题

本文关键字:问题 定理 分离 | 更新日期: 2023-09-27 17:51:14

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

在这个问题上有任何启示就太好了。我使用正X来增加0度的CCW。

欢呼。

编辑:我做了更多的研究,意识到将一个向量投影到另一个向量上需要的不仅仅是点积。谁能给我一个正确的检查轴方法的一个版本,非常非常,请:)

编辑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;
    }

分离轴定理问题

我在GameDev上发布了这个问题。从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;
}
//...

这也适用于checkAY, checkOXcheckOY

除了Mazk1985提供的修复之外,checkOX()函数中还有一个错字。. halfheight应该是。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;
}