# IntersectMovingAABBAABB weird behavior

I'm using the IntersectMovingAABBAABB implementation from the book Realtime Collision Detection and I'm having a little bit of an issue. When I have two AABBs next to each other (not touching), A being stationnary and B moving up or down, I'm getting a result saying there's a collision. Obviously this is wrong.

 _______     _______
|       |   |       |
|   A   |   |   B   |  B moving up/down
|_______|   |_______|


I've rechecked my code multiple times to make sure I had the same thing as in the book. Stepping through the code, I realized that the check for v[i] < 0 and v[i] > 0 will never be true for either X or Z axis when moving straight up or down. Therefor, no checks for intersections on these axis will be done. I find that quite weird, and I was wondering if I was missing something, or if this code is simply bad.

Here's my implementation for reference:

public static bool IntersectMovingAABBAABB(AABB a, AABB b, Vector3 va, Vector3 vb, out float first, out float last, out BlockFace face)
{
face = BlockFace.None;
if (TestAABB(a, b))
{
first = last = 0;
return true;
}

Vector3 v = vb - va;
float current;

first = 0;
last = 1;

for (int i = 0; i < 3; i++)
{
if (v[i] < 0)
{
if (b.Max[i] < a.Min[i]) return false;
if (a.Max[i] < b.Min[i]) if ((first = Math.Max(current= (a.Max[i] - b.Min[i]) / v[i], first)) == current) face = (BlockFace)(1 << (i));
if (b.Max[i] > a.Min[i]) last = Math.Min((a.Min[i] - b.Max[i]) / v[i], last);
}

if (v[i] > 0)
{
if (a.Max[i] < b.Min[i]) return false;
if (b.Max[i] < a.Min[i]) if ((first = Math.Max(current = (a.Min[i] - b.Max[i]) / v[i], first)) == current) face = (BlockFace)(1 << (i + 3));
if (a.Max[i] > b.Min[i]) last = Math.Min((a.Max[i] - b.Min[i]) / v[i], last);
}

if (first > last) return false;
}

return true;
}


Realtime collision detection is a great book, but that code is clearly wrong. If the relative velocity was zero, it would always return true, which is clearly incorrect. I believe the first test in each of the if (v[i] ...) blocks needs to be done if the velocity is <= 0 and >= 0 respectively. Note that you can't just change those tests though, because you could then end up dividing by zero. There may be a more elegant way, but I think this should work:

    if (v[i] < 0)
{
if (b.Max[i] < a.Min[i]) return false;
if (a.Max[i] < b.Min[i]) if ((first = Math.Max(current= (a.Max[i] - b.Min[i]) / v[i], first)) == current) face = (BlockFace)(1 << (i));
if (b.Max[i] > a.Min[i]) last = Math.Min((a.Min[i] - b.Max[i]) / v[i], last);
}
else if (v[i] > 0)
{
if (a.Max[i] < b.Min[i]) return false;
if (b.Max[i] < a.Min[i]) if ((first = Math.Max(current = (a.Min[i] - b.Max[i]) / v[i], first)) == current) face = (BlockFace)(1 << (i + 3));
if (a.Max[i] > b.Min[i]) last = Math.Min((a.Max[i] - b.Min[i]) / v[i], last);
}
else
{
if (b.Max[i] < a.Min[i] || a.Max[i] < b.Min[i]) return false;
}

• Amazing! Thanks a lot! I find it kind of weird that such a good book wouldn't have a working implementation. I checked the errata, nothing there! Jul 16, 2017 at 18:09