I need some help with swept AABB collision

I trying to implement Swept AABB Collision from here. It works fine for diagonal movement, but dosn`t apply for horizontal or vertical movement, no collision time or normal was given. My code

public struct AABBox
    {
        public Vector2 Pos;
        public Vector2 Size;

        public Vector2 Vel;

        public AABBox(Vector2 pos, Vector2 size, Vector2 vel)
        {
            Pos = pos;
            Size = size;
            Vel = vel;
        }

        public bool Collide(AABBox other)
        {
            if (Pos.X + Size.X >= other.Pos.X && other.Pos.X + other.Size.X >= Pos.X &&
                Pos.Y + Size.Y >= other.Pos.Y && other.Pos.Y + other.Size.Y >= Pos.Y)
            {
                return true;
            }

            return false;
        }

        public bool SweptAABB(AABBox other, out float collisionTime, out Vector2 normal)
        {
            normal = new Vector2();
            collisionTime = 1f;

            Vector2 vEntry = new Vector2();
            Vector2 vEnd = new Vector2();

            if (Vel.X > 0f)
            {
                vEntry.X = other.Pos.X - (Pos.X + Size.X);
                vEnd.X = (other.Pos.X + other.Size.X) - Pos.X;
            }
            else
            {
                vEntry.X = (other.Pos.X + other.Size.X) - Pos.X;
                vEnd.X = other.Pos.X - (Pos.X + Size.X);
            }

            if (Vel.Y > 0f)
            {
                vEntry.Y = other.Pos.Y - (Pos.Y + Size.Y);
                vEnd.Y = (other.Pos.Y + other.Size.Y) - Pos.Y;
            }
            else
            {
                vEntry.Y = (other.Pos.Y + other.Size.Y) - Pos.Y;
                vEnd.Y = other.Pos.Y - (Pos.Y + Size.Y);
            }

            Vector2 tEntry = new Vector2();
            Vector2 tEnd = new Vector2();

            tEntry.X = vEntry.X / Vel.X;
            tEnd.X = vEnd.X / Vel.X;

            tEntry.Y = vEntry.Y / Vel.Y;
            tEnd.Y = vEnd.Y / Vel.Y;

            float entryTime = MathHelper.Max(tEntry.X, tEntry.Y);
            float endTime = MathHelper.Min(tEnd.X, tEnd.Y);

            // Check if no collision occures
            if (entryTime > endTime || (tEntry.X < 0.0f && tEntry.Y < 0.0f) || tEntry.X > 1f || tEntry.Y > 1f)
            {
                // normal here is 0,0
                return false;
            }
            else
            {
                if (tEntry.X > tEntry.Y)
                {
                    if (vEntry.X < 0f)
                    {
                        normal.X = 1f;
                    }
                    else
                    {
                        normal.X = -1f;
                    }
                }
                else
                {
                    if (vEntry.Y < 0f)
                    {
                        normal.Y = 1f;
                    }
                    else
                    {
                        normal.Y = -1f;
                    }
                }

                collisionTime = entryTime;

                return true;
            }

        }

        public AABBox GetBroadPhaseBox()
        {
            float x = Vel.X > 0 ? Pos.X : Pos.X + Vel.X;
            float y = Vel.Y > 0 ? Pos.Y : Pos.Y + Vel.Y;
            float w = Vel.X > 0 ? Vel.X + Size.X : Size.X - Vel.X;
            float h = Vel.Y > 0 ? Vel.Y + Size.Y : Size.Y - Vel.X;

            AABBox box = new AABBox(new Vector2(x, y), new Vector2(w, h), new Vector2());

            return box;
        }
    }

Can someone explain what is wrong or what i need to do?

For horizontal movement Vel.Y will be 0 leading to divisions by zero here:

The sample code you linked to handles that case, but you don’t.

1 Like

In c# this gives you infinity and -infinity. This values also sets in linked example. I try to check for 0 and set same values, but this gives the same result: no collision detection on single axes movement)

I am dump as f… Thx markus for replay, this thing starts working after i use infinity (last time i use max float values).

public struct AABBox
    {
        public Vector2 Pos;
        public Vector2 Size;

        public Vector2 Vel;

        public AABBox(Vector2 pos, Vector2 size, Vector2 vel)
        {
            Pos = pos;
            Size = size;
            Vel = vel;
        }

        public bool Collide(AABBox other)
        {
            if (Pos.X + Size.X >= other.Pos.X && other.Pos.X + other.Size.X >= Pos.X &&
                Pos.Y + Size.Y >= other.Pos.Y && other.Pos.Y + other.Size.Y >= Pos.Y)
            {
                return true;
            }

            return false;
        }

        public bool SweptAABB(AABBox other, out float collisionTime, out Vector2 normal)
        {
            normal = new Vector2();
            collisionTime = 1f;

            Vector2 vEntry = new Vector2();
            Vector2 vEnd = new Vector2();

            if (Vel.X > 0f)
            {
                vEntry.X = other.Pos.X - (Pos.X + Size.X);
                vEnd.X = (other.Pos.X + other.Size.X) - Pos.X;
            }
            else
            {
                vEntry.X = (other.Pos.X + other.Size.X) - Pos.X;
                vEnd.X = other.Pos.X - (Pos.X + Size.X);
            }

            if (Vel.Y > 0f)
            {
                vEntry.Y = other.Pos.Y - (Pos.Y + Size.Y);
                vEnd.Y = (other.Pos.Y + other.Size.Y) - Pos.Y;
            }
            else
            {
                vEntry.Y = (other.Pos.Y + other.Size.Y) - Pos.Y;
                vEnd.Y = other.Pos.Y - (Pos.Y + Size.Y);
            }

            Vector2 tEntry = new Vector2();
            Vector2 tEnd = new Vector2();

            if (Vel.X == 0f)
            {
                tEntry.X = (float)double.NegativeInfinity;
                tEnd.X = (float)double.PositiveInfinity;
            }
            else
            {
                tEntry.X = vEntry.X / Vel.X;
                tEnd.X = vEnd.X / Vel.X;
            }

            if (Vel.Y == 0f)
            {
                tEntry.Y  = (float)double.NegativeInfinity;
                tEnd.Y = (float)double.PositiveInfinity;
            }
            else
            {
                tEntry.Y = vEntry.Y / Vel.Y;
                tEnd.Y = vEnd.Y / Vel.Y;
            }

            float entryTime = MathHelper.Max(tEntry.X, tEntry.Y);
            float endTime = MathHelper.Min(tEnd.X, tEnd.Y);

            // Check if no collision occures
            if (entryTime > endTime || (tEntry.X < 0.0f && tEntry.Y < 0.0f) || tEntry.X > 1f || tEntry.Y > 1f)
            {
                // normal here is 0,0
                return false;
            }
            else
            {
                if (tEntry.X > tEntry.Y)
                {
                    if (vEntry.X < 0f)
                    {
                        normal.X = 1f;
                    }
                    else
                    {
                        normal.X = -1f;
                    }
                }
                else
                {
                    if (vEntry.Y < 0f)
                    {
                        normal.Y = 1f;
                    }
                    else
                    {
                        normal.Y = -1f;
                    }
                }

                collisionTime = entryTime;

                return true;
            }

        }

        public AABBox GetBroadPhaseBox()
        {
            float x = Vel.X > 0 ? Pos.X : Pos.X + Vel.X;
            float y = Vel.Y > 0 ? Pos.Y : Pos.Y + Vel.Y;
            float w = Vel.X > 0 ? Vel.X + Size.X : Size.X - Vel.X;
            float h = Vel.Y > 0 ? Vel.Y + Size.Y : Size.Y - Vel.X;

            AABBox box = new AABBox(new Vector2(x, y), new Vector2(w, h), new Vector2());

            return box;
        }
    }