Ray tracing box intersections

18.3k views Asked by At

So I'm back with another ray tracing question. My code renders spheres all fine and dandy, but cubes aren't really working. I'm using this code to test for intersections: http://pastebin.com/qgm6vpdx (It's a recursive function, t is the distance to the intersection point) The bounding box is defined as:

Cube* c1 = new Cube;      
c1->Corner1 = Vec3(100, 100, 100);      
c1->Corner2 = Vec3(200, 200, 200);

I've confirmed that the camera is not inside the cube. Now, the only problem is that the entire screen shows up as green (the color designated to the cube)

I don't think I'm doing the cube intersections right, can anyone proof read my code?

2

There are 2 answers

0
arx On BEST ANSWER

You could make the code a lot shorter and more readable. For example, change int tNear = -2147000000 to int tNear = INT_MIN and change

if(t1 > t2)
{
    float temp1 = t1;
    t1 = t2;
    t2 = temp1;
}

to

if(t1 > t2)
{
    // std::swap is built-in
    swap(t1, t2);
}

or better

// Define 'order' yourself
order(t1, t2);

and change

if(t1 > tNear)
{
   tNear = t1;
}

to

// std::max is built in
tNear = max(tNear, t1);

Then one section of your code becomes:

if ((ray.dir.x == 0) && (ray.start.x < Min.x) && (ray.start.x > Max.x))
{
    //parallel
    return false;
}
else
{
    float t1 = (Min.x - ray.start.x) / ray.dir.x;
    float t2 = (Max.x - ray.start.x) / ray.dir.x;
    order(t1, t2);
    tNear = max(tNear, t1);
    tFar = max(tFar, t1);
    if ((tNear > tFar) || (tFar < 0))
        return false;
}

And this reveals one problem. tNear and tFar define an interval of t values within which the line intersects the cube. Each coordinate you test (x, y and z) further constrains the interval. However the code tFar = max(tFar, t1) is expanding the interval. Change it to tFar = min(tFar, t1).

More fundamentally, this limits you to axis-aligned cuboids, though this code might be useful later as a quick hit-test for more complex shapes. Anyway, once this is working you might like to make it more general.

You can define any convex polygon as a set of infinite planes with the normals facing outwards. A point is inside the polygon if it is "inside" all of the planes.

A plane splits space into two halves. Define the half to which the normal points as "outside" and the other half as "inside". Then a point is outside a plane if the plane equation at that point is positive, inside the plane if the value is negative and on the plane if the value is zero.

To ray-trace this you determine the ray/plane intersections and choose the nearest one. To determine if that point is within the face (remember, the plane is infinite) you check if the point is inside all the other planes. If not, test the next nearest intersection, and so on.

Once this is working it is quite easy to extend it to general intersections and differences of shapes (e.g. a cube with a hemispherical indent in one of the faces).

1
Tavian Barnes On

One of the best algorithms for calculating ray-box intersections is the slab method. I outlined my optimized implementation of it here, as well.