Game Development Community

dev|Pro Game Development Curriculum

Line Segment - Box Intersection

by Tim Gift · 12/14/2000 (6:26 pm) · 5 comments

I thought I would start up our code resource section by posting this function to calculate the intersection between a line segment and a box. One of those handy things :) I wrote this one up while working on some collision code.

The function works by treating the problem as a set of 3 one dimensional line segment tests and finds the intersection closest to the start point (if any). In the case of an intersection it returns true and sets the time parameter to the intersection time along the vector (end - start). (Think of the segment as a parametric line equation.) If you want the actually intersection point, it's simply calculated as start + (end - start) * time.

The original function used different structures, so I made a few quick changes to avoid including any extraneous code. Hopefully without introducing any bugs...
typedef float F32;

struct Point
{
    F32 x,y,z;
};

struct Box
{
    Point min,max;
};

bool intersect(const Point &start, const Point &end,
      const &box, F32 *time)
{
   F32 st,et,fst = 0,fet = 1;
   F32 const *bmin = &box.min.x;
   F32 const *bmax = &box.max.x;
   F32 const *si = &start.x;
   F32 const *ei = &end.x;

   for (int i = 0; i < 3; i++) {
      if (*si < *ei) {
         if (*si > *bmax || *ei < *bmin)
            return false;
         F32 di = *ei - *si;
         st = (*si < *bmin)? (*bmin - *si) / di: 0;
         et = (*ei > *bmax)? (*bmax - *si) / di: 1;
      }
      else {
         if (*ei > *bmax || *si < *bmin)
            return false;
         F32 di = *ei - *si;
         st = (*si > *bmax)? (*bmax - *si) / di: 0;
         et = (*ei < *bmin)? (*bmin - *si) / di: 1;
      }

      if (st > fst) fst = st;
      if (et < fet) fet = et;
      if (fet < fst)
         return false;
      bmin++; bmax++;
      si++; ei++;
   }

   *time = fst;
   return true;
}
When testing a line in world space against an arbitrarily transformed box I usually convert the line into the box's space. The code might look like this:
F32 time;
    Matrix const &objMat = object->getInverseTransform();
    Point start = objMat * line.start;
    Point end = objMat * line.end;
    if (intersect(start,end,object->getBoundingBox(),&time)) {
        Point objPoint = line.start + time *
           (line.end - line.start);
        collisionPoint = object->getTransform() * objPoint;
    }

#1
12/16/2000 (4:39 pm)
interesting
#2
04/02/2001 (6:56 pm)
I should have thought of that :(

Fortunately, I don't have to try and program my own engine like I thought I was gonig to have to.
#3
09/07/2001 (9:09 pm)
Pretty nice idea
#4
11/25/2002 (10:14 pm)
Great code.
#5
10/16/2017 (2:43 am)
Hi could someone explain the question mark which is followed by the colon i.e. in this segment:

st = (*si < *bmin)? (*bmin - *si) / di: 0;
et = (*ei > *bmax)? (*bmax - *si) / di: 1;

In case anyone has the same question:
(https://stackoverflow.com/questions/795286/what-does-do-in-c)