Optimizing intersect finding code

The bottleneck of many raytracers is intersect finding code.
Usually it look like a
Object * Intersect ( Ray& ray, double& t )
{
 Object * ClosestObj = NULL;
 double ClosestDist = INFINITY;

 for ( int i = 0; i < SolidsCount; i++ ) // check every object
    if ( Solid [i] -> Intersect ( ray, t ) ) // if intersect then check distance
       if ( t < ClosestDist )
       {
       ClosestDist = t;
       ClosestObj = Solid [i];
       }
 t = ClosestDist;
 return ClosestObj;
}

But this code check all objects in scene, also objects, which is too far from the ray direction.
Let's try to find better way.
Ray divide space to subspaces where ray can be and where cant be.
When ray direction is >0.0 then bounding box of object is righter from ray origin, otherwise - lefter.
I use heuristic to check it.

Code1:
Object * Intersect ( Ray& ray, double& t )
{
 Object * ClosestObj = NULL;
 double ClosestDist = INFINITY;
 int sx, sy, sz, ok;

 sx=(r.dir.x<=0.0);sy=(r.dir.y<=0.0);sz=(r.dir.z<=0.0); //signs of direction
 for ( int i = 0; i < SolidsCount; i++ ) // check every object
    {
     ok=(sx)? (Solid [i] ->min.x<=r.org.x): (Solid [i] ->max.x>=r.org.x);
     if (!ok) continue;
     ok=(sy)? (Solid [i] ->min.y<=r.org.y): (Solid [i] ->max.y>=r.org.y);
     if (!ok) continue;
     ok=(sz)? (Solid [i] ->min.z<=r.org.z): (Solid [i] ->max.z>=r.org.z);
     if (!ok) continue;
     if ( Solid [i] -> Intersect ( ray, t ) ) // if intersect then check distance
       if ( t < ClosestDist )
       {
       ClosestDist = t;
       ClosestObj = Solid [i];
       }
    }
 t = ClosestDist;
 return ClosestObj;
}

Works faster, but not too fast - usually 25% speedup.
This code checks also objects lefter or righter from far ray intersection point with all-objects-bounding-box.
Let's optimize further.

Code2:
Object * Intersect ( Ray& ray, double& t )
{
 Object * ClosestObj = NULL;
 double ClosestDist = INFINITY, mx, my, mz;
 int sx, sy, sz, ok;

 sx=(r.dir.x<=0.0);sy=(r.dir.y<=0.0);sz=(r.dir.z<=0.0); //signs of direction
 mx=r.dir.x; my=r.dir.y; mz=r.dir.z;
 if (sx) mx=-mx;
 if (sy) my=-my;
 if (sz) mz=-mz;
 if (mx>my && mx>mz) // x direction increasing faster
  {
   mx=(sx)? gbb.max.x : gbb.min.x; t=(mx-r.org.x)/r.dir.x; //gbb - global bounding box - min and max points of scene
   my=r.org.y + r.dir.y*t; mz=r.org.z + r.dir.z*t;
  }
  else if (my>mx && my>mz) // y direction increasing faster
     {
      my=(sy)? gbb.max.y : gbb.min.y; t=(my-r.org.y)/r.dir.y;
      mx=r.org.x + r.dir.x*t; mz=r.org.z + r.dir.z*t;
     }
    else // z direction increasing faster
       {
        mz=(sz)? gbb.max.z : gbb.min.z; t=(mz-r.org.z)/r.dir.z;
        my=r.org.y + r.dir.y*t; mx=r.org.x + r.dir.x*t;
       }
 for ( int i = 0; i < SolidsCount; i++ ) // check every object
    {
     ok=(sx)? (Solid [i] ->min.x<=r.org.x): (Solid [i] ->max.x>=r.org.x);
     if (!ok) continue;
     ok=(sy)? (Solid [i] ->min.y<=r.org.y): (Solid [i] ->max.y>=r.org.y);
     if (!ok) continue;
     ok=(sz)? (Solid [i] ->min.z<=r.org.z): (Solid [i] ->max.z>=r.org.z);
     if (!ok) continue;
     ok=(!sx)? (Solid [i] ->min.x>=mx): (Solid [i] ->max.x<=mx);
     if (!ok) continue;
     ok=(!sy)? (Solid [i] ->min.y>=my): (Solid [i] ->max.y<=my);
     if (!ok) continue;
     ok=(!sz)? (Solid [i] ->min.z>=mz): (Solid [i] ->max.z<=mz);
     if (!ok) continue;
     if ( Solid [i] -> Intersect ( ray, t ) ) // if intersect then check distance
       if ( t < ClosestDist )
       {
       ClosestDist = t;
       ClosestObj = Solid [i];
       }
    }
 t = ClosestDist;
 return ClosestObj;
}

We can use these algorithms with octrees, bsp or with other scene traversal.
---------------------------------------
Be optimized!
tigra
mail me
icq 429048706

Hosted by uCoz