1

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

关于这个主题的任何光线都会很棒。我使用正 X 表示 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;
    }
4

2 回答 2

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

于 2013-01-11T16:54:19.667 回答
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;
}
于 2016-05-17T02:57:44.763 回答