Ejemplo n.º 1
0
Archivo: AABB.cpp Proyecto: sdp0et/gtp
bool AABB::intersects( const Ray& ray, Vector& pt )
{
  // Rays starting and ending in an octree node must be considered
  // to hit the node.
  // if the start point OR the end point is in the AABB, then it's a hit.
  if( containsIn( ray.startPos ) || containsIn( ray.getEndPoint() ) )
  {
    //generateDebugLines( Vector(0,1,0) ) ;//green is RAY STARTED INSIDE
    return true ; 
  }
  
  Vector tmins, tmaxes ;

  // These are red in the profiler.
  tmins = (min - ray.startPos) / ray.direction ;
  tmaxes = (max - ray.startPos) / ray.direction ;
  
  Vector* sols[2] = { &tmins, &tmaxes } ;
  int solS=0, solI=0 ;
  
  real smallestT = HUGE ; // smallest valid t ("so far"). put at inf so first time everything smaller than it.
  Vector closestRaypoint ; // smallest rayPoint (associated with "smallest t so far")

  for( int s = 0 ; s < 2 ; s++ )
  {
    Vector& candSols = *sols[s] ;
    
    // i walks xyz
    for( int i = 0 ; i < 3 ; i++ )
    {
      real& t = candSols.e[i] ; // candidate t
      
      // validity:  0 <= t <= length
      if( BetweenIn( t, 0, ray.length ) )
      {
        Vector raypoint = ray.at( t ) ;

        // AND ON FACE
        // o1 and o2 are the indices of the OTHER faces,
        // if i==0, o1=1, o2=2
        int o1 = ( i + 1 ) % 3 ; // if( i==0 ) o1=1, o2=2; 
        int o2 = ( i + 2 ) % 3 ; // else if( i == 1) o1=2, o2=0;

        if( InRect( raypoint.e[ o1 ],raypoint.e[ o2 ], 
          min.e[o1], min.e[o2],
          max.e[o1], max.e[o2] ) )
        {
          // this one wins, if it's smallest so far
          if( t < smallestT )
          {
            smallestT = t ;
            closestRaypoint = raypoint ;
            // record what face it was
            solS = s ;
            solI = i ;
          }
        }
      }
    }
  }

  // now here, it's possible smallestT was unassigned,
  // which means it'll still be HUGE
  if( smallestT == HUGE )
  {
    // no solution
    ///generateDebugLines( Vector(.2,.2,.2) ) ;//total miss
    return false ;
  }
  else
  {
    // there was an intersection.
    ///generateDebugLines( Vector(1,0,0) ) ;//red means it was a hit
    pt = closestRaypoint ;
    return true ;
  }
}
Ejemplo n.º 2
0
Archivo: AABB.cpp Proyecto: sdp0et/gtp
bool AABB::intersects( const Ray& ray )
{
  // VERY IMPORTANT CHECK: If the ray starts inside
  // the box, then it's a hit.  This was important for octrees.
  if( containsIn( ray.startPos ) || containsIn( ray.getEndPoint() ) )
    return true ; 

  #define TECH 0
  #if TECH==0
  // the algorithm says, find 3 t's,
  Vector t ;

  // LARGEST t is the only only we need to test if it's on the face.
  for( int i = 0 ; i < 3 ; i++ )
  {
    if( ray.direction.e[i] > 0 ) // CULL BACK FACE
      t.e[i] = ( min.e[i] - ray.startPos.e[i] ) / ray.direction.e[i] ;
    else
      t.e[i] = ( max.e[i] - ray.startPos.e[i] ) / ray.direction.e[i] ;
  }

  int mi = t.maxIndex() ;
  if( BetweenIn( t.e[mi], 0, ray.length ) )
  {
    Vector pt = ray.at( t.e[mi] ) ;

    // check it's in the box in other 2 dimensions
    int o1 = ( mi + 1 ) % 3 ; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc.
    int o2 = ( mi + 2 ) % 3 ;

    return BetweenIn( pt.e[o1], min.e[o1], max.e[o1] ) &&
           BetweenIn( pt.e[o2], min.e[o2], max.e[o2] ) ;
  }

  return false ;
  #elif TECH==1

  // This culls the back faces first, and gives you the answer with the largest valid t
  for( int i = 0 ; i < 3 ; i++ )
  {
    int o1 = ( i + 1 ) % 3 ; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc.
    int o2 = ( i + 2 ) % 3 ;

    // min.x (NX) is possible, PX won't be hit. (unless you're inside the box.)
    if( ray.direction.e[i] > 0 ) // CULL BACK FACE
    {
      real t = ( min.e[i] - ray.startPos.e[i] ) / ray.direction.e[i] ;

      // 1. CHECK VALID T
      if( BetweenIn( t, 0, ray.length ) )
      {
        // 2. CHECK IN BOX
        Vector pt = ray.at( t ) ;
        if( BetweenIn( pt.e[o1], min.e[o1], max.e[o1] ) && BetweenIn( pt.e[o2], min.e[o2], max.e[o2] ) )
          return true ;  // it's valid in the box
      }
    }
    else if( ray.direction.e[i] < 0 ) // max.x (PX) is possible
    {
      real t = ( max.e[i] - ray.startPos.e[i] ) / ray.direction.e[i] ;
      if( BetweenIn( t, 0, ray.length ) ) // valid t
      {
        Vector pt = ray.at( t ) ;
        if( BetweenIn( pt.e[o1], min.e[o1], max.e[o1] ) && BetweenIn( pt.e[o2], min.e[o2], max.e[o2] ) )
          return true ;  // it's valid in the box
      }
    }
  }

  return false ; // no hit.
  #elif TECH==2
  // This solves ALL 6 solutions and finds the shortest t.
  // Rays starting and ending in an octree node must be considered
  // to hit the node.
  // if the start point OR the end point is in the AABB, then it's a hit.
  
  
  // These are red in the profiler.
  Vector tmins = (min - ray.startPos) / ray.direction ;
  Vector tmaxes = (max - ray.startPos) / ray.direction ;
  
  Vector* sols[2] = { &tmins, &tmaxes } ;
  
  for( int s = 0 ; s < 2 ; s++ )
  {
    Vector& candSols = *sols[s] ;
    
    // i walks xyz
    for( int i = 0 ; i < 3 ; i++ )
    {
      real& t = candSols.e[i] ; // candidate t
      
      // validity:  0 <= t <= length
      if( BetweenIn( t, 0, ray.length ) )
      {
        Vector raypoint = ray.at( t ) ;

        // AND ON FACE
        // o1 and o2 are the indices of the OTHER faces,
        // if i==0, o1=1, o2=2
        int o1 = ( i + 1 ) % 3 ; // if( i==0 ) o1=1, o2=2; 
        int o2 = ( i + 2 ) % 3 ; // else if( i == 1) o1=2, o2=0;

        if( InRect( raypoint.e[ o1 ],raypoint.e[ o2 ], 
          min.e[o1], min.e[o2],
          max.e[o1], max.e[o2] ) )
        {
          // the box got hit, any side
          return true ;
        }
      }
    }
  }

  // No hit
  return false ;

  #endif
}