1
\$\begingroup\$

I'm embarrassed I can't find this, but I'm wanting to detect intersection with a 3D line segment (not an infinite ray) with a 3D AABB, the AABB being defined as two Vec3f's which represent the Min and Max extents. So the AABB can be arbitrarily-sized. I also need the surface normal of the AABB, if there was a hit.

From looking at similar algorithms I at least know it seems good to calculate the inverse direction of the line beforehand, at least, if you're needing to check against multiple AABBs per frame.

I have

struct AABB
{
    VEC3F min;
    VEC3F max;
};

// a and b representing start/end points of the line segment
// returns true if intersects, also fills out "normal" if true
bool LineIntersectsAABB(const VEC3F& a, const VEC3F& b,
    const VEC3F& inv_dir, const AABB& aabb,
    VEC3F* normal);

The implementations I've found either do not find the hit normal, and/or they're intended for boxes/cubes where the three dimensions of the box are always equal length, which doesn't work for me. Implementations seem to vary greatly, which is confusing for me (since I'm still trying to learn it), and, considering that I need the hit normal, I'd imagine that that may rule out certain implementations.

\$\endgroup\$
  • \$\begingroup\$ "they're intended for boxes/cubes where the three dimensions of the box are always equal length, which doesn't work for me" There's a linear transformation mapping your AABB to a cube, and your line segment to a corresponding line segment. So you can apply that transformation, use the method you found to solve that reduced case, then invert the transformation to map it to a solution for your original configuration. \$\endgroup\$ – DMGregory Oct 18 at 2:56
0
\$\begingroup\$

but I'm wanting to detect intersection with a 3D line segment (not an infinite ray) with a 3D AABB

Most of these ray intersection algorithms return the hit distance. All you need to do is check that the hit distance is less than the length of your line segment.

For your normal calculation, find the plane on the cube which contains the intersection point closest to the ray, where the ray still intersects the cube.

  1. Use a ray intersection algorithm, ray_box_intersection(ray, box, &out_distance)
  2. If there is an intersection, check that the distance is < the length of the line segment, otherwise exit
  3. To get the normal, take the ray plane intersection of each plane in the box.
  4. Ray plane intersection distance = ((plane_offset - ray_origin) * plane_normal)/(ray_direction * plane_normal), where if the distance < 0, there is no intersection (the intersection is behind us), and if the ray_direction * plane_normal == 0, the ray is travelling parallel to the plane, and there will be no intersection.
  5. If this ray_plane_intersection(ray, plane, &out_distance) returns true, we will still need to test if the point was inside the box. If the test is true, remember this plane's normal and the distance.
  6. Repeat 6 for every plane around the box, keeping the plane with the smallest distance, and keeping its normal
  7. You now have the normal.

In my code don't treat the intersection code as a black box, and I typically modify this answer for best AABB 3d box intersection tester, and check which of the t1 t2 ... t6 values ended up being used for the final output t ray distance value in addition to giving the distance. Each of these t's correspond to a side of the AABB, which tells you which normal you use.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.