1

現在、軸が整列し、方向が設定されたバウンディング ボックスのオーバーラップ テスターを追加しようとしていますが、OBB の角度が -10 から +10 の間の場合にのみ、ソリューションが正確に機能するようです。角度が +90 度に近づくと、衝突領域は最初に OBB の右半分に移動し、その後存在しなくなるように見えます。90 度から 270 度の間ではオーバーラップを取得できませんでしたが、完全に 360 度になると、領域は再び正確に登録されます。

このテーマに関する光は素晴らしいでしょう。正の X を使用して 0 度を CCW に増やしています。

乾杯。

編集: もう少し調査を行い、ベクトルを別のベクトルに射影するにはドット積以上のものが必要であることに気付きました。以下のチェック軸メソッドのいずれかの正しいバージョンを教えてください:)

EDIT 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 からこの回答を受け取りました。

2 つのベクトル間の角度が 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これは、 、checkOX、およびにも適用されます。checkOY

于 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 に答える