• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Intersection.h

Go to the documentation of this file.
00001 // GMTL is (C) Copyright 2001-2010 by Allen Bierbaum
00002 // Distributed under the GNU Lesser General Public License 2.1 with an
00003 // addendum covering inlined code. (See accompanying files LICENSE and
00004 // LICENSE.addendum or http://www.gnu.org/copyleft/lesser.txt)
00005 
00006 #ifndef _GMTL_INTERSECTION_H_
00007 #define _GMTL_INTERSECTION_H_
00008 
00009 #include <algorithm>
00010 #include <limits>
00011 #include <gmtl/AABox.h>
00012 #include <gmtl/Point.h>
00013 #include <gmtl/Sphere.h>
00014 #include <gmtl/Vec.h>
00015 #include <gmtl/Plane.h>
00016 #include <gmtl/VecOps.h>
00017 #include <gmtl/Math.h>
00018 #include <gmtl/Ray.h>
00019 #include <gmtl/LineSeg.h>
00020 #include <gmtl/Tri.h>
00021 #include <gmtl/PlaneOps.h>
00022 
00023 namespace gmtl
00024 {
00034    template<class DATA_TYPE>
00035    bool intersect(const AABox<DATA_TYPE>& box1, const AABox<DATA_TYPE>& box2)
00036    {
00037       // Look for a separating axis on each box for each axis
00038       if (box1.getMin()[0] > box2.getMax()[0])  return false;
00039       if (box1.getMin()[1] > box2.getMax()[1])  return false;
00040       if (box1.getMin()[2] > box2.getMax()[2])  return false;
00041 
00042       if (box2.getMin()[0] > box1.getMax()[0])  return false;
00043       if (box2.getMin()[1] > box1.getMax()[1])  return false;
00044       if (box2.getMin()[2] > box1.getMax()[2])  return false;
00045 
00046       // No separating axis ... they must intersect
00047       return true;
00048    }
00049 
00059    template<class DATA_TYPE>
00060    bool intersect( const AABox<DATA_TYPE>& box, const Point<DATA_TYPE, 3>& point )
00061    {
00062       // Look for a separating axis on each box for each axis
00063       if (box.getMin()[0] > point[0])  return false;
00064       if (box.getMin()[1] > point[1])  return false;
00065       if (box.getMin()[2] > point[2])  return false;
00066 
00067       if (point[0] > box.getMax()[0])  return false;
00068       if (point[1] > box.getMax()[1])  return false;
00069       if (point[2] > box.getMax()[2])  return false;
00070 
00071       // they must intersect
00072       return true;
00073    }
00074 
00089    template<class DATA_TYPE>
00090    bool intersect( const AABox<DATA_TYPE>& box1, const Vec<DATA_TYPE, 3>& path1,
00091                    const AABox<DATA_TYPE>& box2, const Vec<DATA_TYPE, 3>& path2,
00092                    DATA_TYPE& firstContact, DATA_TYPE& secondContact )
00093    {
00094       // Algorithm taken from Gamasutra's article, "Simple Intersection Test for
00095       // Games" - http://www.gamasutra.com/features/19991018/Gomez_3.htm
00096       //
00097       // This algorithm is solved from the frame of reference of box1
00098 
00099       // Get the relative path (in normalized time)
00100       Vec<DATA_TYPE, 3> path = path2 - path1;
00101 
00102       // The first time of overlap along each axis
00103       Vec<DATA_TYPE, 3> overlap1(DATA_TYPE(0), DATA_TYPE(0), DATA_TYPE(0));
00104 
00105       // The second time of overlap along each axis
00106       Vec<DATA_TYPE, 3> overlap2(DATA_TYPE(1), DATA_TYPE(1), DATA_TYPE(1));
00107 
00108       // Check if the boxes already overlap
00109       if (gmtl::intersect(box1, box2))
00110       {
00111          firstContact = secondContact = DATA_TYPE(0);
00112          return true;
00113       }
00114 
00115       // Find the possible first and last times of overlap along each axis
00116       for (int i=0; i<3; ++i)
00117       {
00118          if ((box1.getMax()[i] < box2.getMin()[i]) && (path[i] < DATA_TYPE(0)))
00119          {
00120             overlap1[i] = (box1.getMax()[i] - box2.getMin()[i]) / path[i];
00121          }
00122          else if ((box2.getMax()[i] < box1.getMin()[i]) && (path[i] > DATA_TYPE(0)))
00123          {
00124             overlap1[i] = (box1.getMin()[i] - box2.getMax()[i]) / path[i];
00125          }
00126 
00127          if ((box2.getMax()[i] > box1.getMin()[i]) && (path[i] < DATA_TYPE(0)))
00128          {
00129             overlap2[i] = (box1.getMin()[i] - box2.getMax()[i]) / path[i];
00130          }
00131          else if ((box1.getMax()[i] > box2.getMin()[i]) && (path[i] > DATA_TYPE(0)))
00132          {
00133             overlap2[i] = (box1.getMax()[i] - box2.getMin()[i]) / path[i];
00134          }
00135       }
00136 
00137       // Calculate the first time of overlap
00138       firstContact = Math::Max(overlap1[0], overlap1[1], overlap1[2]);
00139 
00140       // Calculate the second time of overlap
00141       secondContact = Math::Min(overlap2[0], overlap2[1], overlap2[2]);
00142 
00143       // There could only have been a collision if the first overlap time
00144       // occurred before the second overlap time
00145       return firstContact <= secondContact;
00146    }
00147 
00163    template<class DATA_TYPE>
00164    bool intersectAABoxRay(const AABox<DATA_TYPE>& box,
00165                           const Ray<DATA_TYPE>& ray, DATA_TYPE& tIn,
00166                           DATA_TYPE& tOut)
00167    {
00168       tIn  = -(std::numeric_limits<DATA_TYPE>::max)();
00169       tOut = (std::numeric_limits<DATA_TYPE>::max)();
00170       DATA_TYPE t0, t1;
00171       const DATA_TYPE epsilon(0.0000001);
00172 
00173       // YZ plane.
00174       if ( gmtl::Math::abs(ray.mDir[0]) < epsilon )
00175       {
00176          // Ray parallel to plane.
00177          if ( ray.mOrigin[0] < box.mMin[0] || ray.mOrigin[0] > box.mMax[0] )
00178          {
00179             return false;
00180          }
00181       }
00182 
00183       // XZ plane.
00184       if ( gmtl::Math::abs(ray.mDir[1]) < epsilon )
00185       {
00186          // Ray parallel to plane.
00187          if ( ray.mOrigin[1] < box.mMin[1] || ray.mOrigin[1] > box.mMax[1] )
00188          {
00189             return false;
00190          }
00191       }
00192 
00193       // XY plane.
00194       if ( gmtl::Math::abs(ray.mDir[2]) < epsilon )
00195       {
00196          // Ray parallel to plane.
00197          if ( ray.mOrigin[2] < box.mMin[2] || ray.mOrigin[2] > box.mMax[2] )
00198          {
00199             return false;
00200          }
00201       }
00202 
00203       // YZ plane.
00204       t0 = (box.mMin[0] - ray.mOrigin[0]) / ray.mDir[0];
00205       t1 = (box.mMax[0] - ray.mOrigin[0]) / ray.mDir[0];
00206 
00207       if ( t0 > t1 )
00208       {
00209          std::swap(t0, t1);
00210       }
00211 
00212       if ( t0 > tIn )
00213       {
00214          tIn = t0;
00215       }
00216       if ( t1 < tOut )
00217       {
00218          tOut = t1;
00219       }
00220 
00221       if ( tIn > tOut || tOut < DATA_TYPE(0) )
00222       {
00223          return false;
00224       }
00225 
00226       // XZ plane.
00227       t0 = (box.mMin[1] - ray.mOrigin[1]) / ray.mDir[1];
00228       t1 = (box.mMax[1] - ray.mOrigin[1]) / ray.mDir[1];
00229 
00230       if ( t0 > t1 )
00231       {
00232          std::swap(t0, t1);
00233       }
00234 
00235       if ( t0 > tIn )
00236       {
00237          tIn = t0;
00238       }
00239       if ( t1 < tOut )
00240       {
00241          tOut = t1;
00242       }
00243 
00244       if ( tIn > tOut || tOut < DATA_TYPE(0) )
00245       {
00246          return false;
00247       }
00248 
00249       // XY plane.
00250       t0 = (box.mMin[2] - ray.mOrigin[2]) / ray.mDir[2];
00251       t1 = (box.mMax[2] - ray.mOrigin[2]) / ray.mDir[2];
00252 
00253       if ( t0 > t1 )
00254       {
00255          std::swap(t0, t1);
00256       }
00257 
00258       if ( t0 > tIn )
00259       {
00260          tIn = t0;
00261       }
00262       if ( t1 < tOut )
00263       {
00264          tOut = t1;
00265       }
00266 
00267       if ( tIn > tOut || tOut < DATA_TYPE(0) )
00268       {
00269          return false;
00270       }
00271 
00272       return true;
00273    }
00274 
00283    template<class DATA_TYPE>
00284    bool intersect(const AABox<DATA_TYPE>& box, const LineSeg<DATA_TYPE>& seg,
00285                   unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
00286    {
00287       numHits = 0;
00288       bool result = intersectAABoxRay(box, seg, tIn, tOut);
00289       if (tIn < 0.0 && tOut > 1.0)
00290       {
00291      return false;
00292       }
00293       if ( result )
00294       {
00295          // If tIn is less than 0, then the origin of the line segment is
00296          // inside the bounding box (not on an edge)but the endpoint is
00297          // outside.
00298          if ( tIn < DATA_TYPE(0) )
00299          {
00300             numHits = 1;
00301             tIn = tOut;
00302          }
00303          // If tIn is less than 0, then the origin of the line segment is
00304          // outside the bounding box but the endpoint is inside (not on an
00305          // edge).
00306          else if ( tOut > DATA_TYPE(1) )
00307          {
00308             numHits = 1;
00309             tOut = tIn;
00310          }
00311          // Otherwise, the line segement intersects the bounding box in two
00312          // places. tIn and tOut reflect those points of intersection.
00313          else
00314          {
00315             numHits = 2;
00316          }
00317       }
00318 
00319       return result;
00320    }
00321 
00330    template<class DATA_TYPE>
00331    bool intersect(const LineSeg<DATA_TYPE>& seg, const AABox<DATA_TYPE>& box,
00332                   unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
00333    {
00334       return intersect(box, seg, numHits, tIn, tOut);
00335    }
00336 
00345    template<class DATA_TYPE>
00346    bool intersect(const AABox<DATA_TYPE>& box, const Ray<DATA_TYPE>& ray,
00347                   unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
00348    {
00349       numHits = 0;
00350 
00351       bool result = intersectAABoxRay(box, ray, tIn, tOut);
00352 
00353       if ( result )
00354       {
00355          // Ray is inside the box.
00356          if ( tIn < DATA_TYPE(0) )
00357          {
00358             tIn = tOut;
00359             numHits = 1;
00360          }
00361          else
00362          {
00363             numHits = 2;
00364          }
00365       }
00366 
00367       return result;
00368    }
00369 
00378    template<class DATA_TYPE>
00379    bool intersect(const Ray<DATA_TYPE>& ray, const AABox<DATA_TYPE>& box,
00380                   unsigned int& numHits, DATA_TYPE& tIn, DATA_TYPE& tOut)
00381    {
00382       return intersect(box, ray, numHits, tIn, tOut);
00383    }
00384 
00399    template<class DATA_TYPE>
00400    bool intersect(const Sphere<DATA_TYPE>& sph1, const Vec<DATA_TYPE, 3>& path1,
00401                   const Sphere<DATA_TYPE>& sph2, const Vec<DATA_TYPE, 3>& path2,
00402                   DATA_TYPE& firstContact, DATA_TYPE& secondContact)
00403    {
00404       // Algorithm taken from Gamasutra's article, "Simple Intersection Test for
00405       // Games" - http://www.gamasutra.com/features/19991018/Gomez_2.htm
00406       //
00407       // This algorithm is solved from the frame of reference of sph1
00408 
00409       // Get the relative path (in normalized time)
00410       const Vec<DATA_TYPE, 3> path = path2 - path1;
00411 
00412       // Get the vector from sph1's starting point to sph2's starting point
00413       const Vec<DATA_TYPE, 3> start_offset = sph2.getCenter() - sph1.getCenter();
00414 
00415       // Compute the sum of the radii
00416       const DATA_TYPE radius_sum = sph1.getRadius() + sph2.getRadius();
00417 
00418       // u*u coefficient
00419       const DATA_TYPE a = dot(path, path);
00420 
00421       // u coefficient
00422       const DATA_TYPE b = DATA_TYPE(2) * dot(path, start_offset);
00423 
00424       // constant term
00425       const DATA_TYPE c = dot(start_offset, start_offset) - radius_sum * radius_sum;
00426 
00427       // Check if they're already overlapping
00428       if (dot(start_offset, start_offset) <= radius_sum * radius_sum)
00429       {
00430          firstContact = secondContact = DATA_TYPE(0);
00431          return true;
00432       }
00433 
00434       // Find the first and last points of intersection
00435       if (Math::quadraticFormula(firstContact, secondContact, a, b, c))
00436       {
00437          // Swap first and second contacts if necessary
00438          if (firstContact > secondContact)
00439          {
00440             std::swap(firstContact, secondContact);
00441             return true;
00442          }
00443       }
00444 
00445       return false;
00446    }
00447 
00457    template<class DATA_TYPE>
00458    bool intersect(const AABox<DATA_TYPE>& box, const Sphere<DATA_TYPE>& sph)
00459    {
00460       DATA_TYPE dist_sqr = DATA_TYPE(0);
00461 
00462       // Compute the square of the distance from the sphere to the box
00463       for (int i=0; i<3; ++i)
00464       {
00465          if (sph.getCenter()[i] < box.getMin()[i])
00466          {
00467             DATA_TYPE s = sph.getCenter()[i] - box.getMin()[i];
00468             dist_sqr += s*s;
00469          }
00470          else if (sph.getCenter()[i] > box.getMax()[i])
00471          {
00472             DATA_TYPE s = sph.getCenter()[i] - box.getMax()[i];
00473             dist_sqr += s*s;
00474          }
00475       }
00476 
00477       return dist_sqr <= (sph.getRadius()*sph.getRadius());
00478    }
00479 
00489    template<class DATA_TYPE>
00490    bool intersect(const Sphere<DATA_TYPE>& sph, const AABox<DATA_TYPE>& box)
00491    {
00492       return gmtl::intersect(box, sph);
00493    }
00494 
00501    template<class DATA_TYPE>
00502    bool intersect( const Sphere<DATA_TYPE>& sphere, const Point<DATA_TYPE, 3>& point )
00503    {
00504       gmtl::Vec<DATA_TYPE, 3> offset = point - sphere.getCenter();
00505       DATA_TYPE dist = lengthSquared( offset ) - sphere.getRadius() * sphere.getRadius();
00506 
00507       // point is inside the sphere when true
00508       return  dist <= 0;
00509    }
00510 
00521    template<typename T>
00522    inline bool intersect( const Sphere<T>& sphere, const Ray<T>& ray, int& numhits, T& t0, T& t1 )
00523    {
00524       numhits = -1;
00525 
00526       // set up quadratic Q(t) = a*t^2 + 2*b*t + c
00527       const Vec<T, 3> offset = ray.getOrigin() - sphere.getCenter();
00528       const T a = lengthSquared( ray.getDir() );
00529       const T b = dot( offset, ray.getDir() );
00530       const T c = lengthSquared( offset ) - sphere.getRadius() * sphere.getRadius();
00531 
00532 
00533 
00534       // no intersection if Q(t) has no real roots
00535       const T discriminant = b * b - a * c;
00536       if (discriminant < 0.0f)
00537       {
00538          numhits = 0;
00539          return false;
00540       }
00541       else if (discriminant > 0.0f)
00542       {
00543          T root = Math::sqrt( discriminant );
00544          T invA = T(1) / a;
00545          t0 = (-b - root) * invA;
00546          t1 = (-b + root) * invA;
00547 
00548          // assert: t0 < t1 since A > 0
00549 
00550          if (t0 >= T(0))
00551          {
00552             numhits = 2;
00553             return true;
00554          }
00555          else if (t1 >= T(0))
00556          {
00557             numhits = 1;
00558             t0 = t1;
00559             return true;
00560          }
00561          else
00562          {
00563             numhits = 0;
00564             return false;
00565          }
00566       }
00567       else
00568       {
00569          t0 = -b / a;
00570          if (t0 >= T(0))
00571          {
00572             numhits = 1;
00573             return true;
00574          }
00575          else
00576          {
00577             numhits = 0;
00578             return false;
00579          }
00580       }
00581    }
00582 
00589    template<typename T>
00590    inline bool intersect( const Sphere<T>& sphere, const LineSeg<T>& lineseg, int& numhits, T& t0, T& t1 )
00591    {
00592       if (intersect( sphere, Ray<T>( lineseg ), numhits, t0, t1 ))
00593       {
00594          // throw out hits that are past 1 in segspace (off the end of the lineseg)
00595          while (0 < numhits && 1.0f < t0)
00596          {
00597             --numhits;
00598             t0 = t1;
00599          }
00600          if (2 == numhits && 1.0f < t1)
00601          {
00602             --numhits;
00603          }
00604          return 0 < numhits;
00605       }
00606       else
00607       {
00608          return false;
00609       }
00610    }
00611 
00622    template<typename T>
00623    inline bool intersectVolume( const Sphere<T>& sphere, const LineSeg<T>& ray, int& numhits, T& t0, T& t1 )
00624    {
00625       bool result = intersect( sphere, ray, numhits, t0, t1 );
00626       if (result && numhits == 2)
00627       {
00628          return true;
00629       }
00630       // todo: make this faster (find an early out) since 1 or 0 hits is the common case.
00631       // volume test has some additional checks before we can throw it out because
00632       // one of both points may be inside the volume, so we want to return hits for those as well...
00633       else // 1 or 0 hits.
00634       {
00635          const T rsq = sphere.getRadius() * sphere.getRadius();
00636          const Vec<T, 3> dist = ray.getOrigin() - sphere.getCenter();
00637          const T a = lengthSquared( dist ) - rsq;
00638          const T b = lengthSquared( gmtl::Vec<T,3>(dist + ray.getDir()) ) - rsq;
00639 
00640          bool inside1 = a <= T( 0 );
00641          bool inside2 = b <= T( 0 );
00642 
00643          // one point is inside
00644          if (numhits == 1 && inside1 && !inside2)
00645          {
00646             t1 = t0;
00647             t0 = T(0);
00648             numhits = 2;
00649             return true;
00650          }
00651          else if (numhits == 1 && !inside1 && inside2)
00652          {
00653             t1 = T(1);
00654             numhits = 2;
00655             return true;
00656          }
00657          // maybe both points are inside?
00658          else if (inside1 && inside2) // 0 hits.
00659          {
00660             t0 = T(0);
00661             t1 = T(1);
00662             numhits = 2;
00663             return true;
00664          }
00665       }
00666       return result;
00667    }
00668 
00679    template<typename T>
00680    inline bool intersectVolume( const Sphere<T>& sphere, const Ray<T>& ray, int& numhits, T& t0, T& t1 )
00681    {
00682       bool result = intersect( sphere, ray, numhits, t0, t1 );
00683       if (result && numhits == 2)
00684       {
00685          return true;
00686       }
00687       else
00688       {
00689          const T rsq = sphere.getRadius() * sphere.getRadius();
00690          const Vec<T, 3> dist = ray.getOrigin() - sphere.getCenter();
00691          const T a = lengthSquared( dist ) - rsq;
00692 
00693          bool inside = a <= T( 0 );
00694 
00695          // start point is inside
00696          if (inside)
00697          {
00698             t1 = t0;
00699             t0 = T(0);
00700             numhits = 2;
00701             return true;
00702          }
00703       }
00704       return result;
00705    }
00706 
00718    template<class DATA_TYPE>
00719    bool intersect( const Plane<DATA_TYPE>& plane, const Ray<DATA_TYPE>& ray, DATA_TYPE& t )
00720    {
00721       const DATA_TYPE eps(0.00001f);
00722 
00723       // t = -(n·P + d)
00724       Vec<DATA_TYPE, 3> N( plane.getNormal() );
00725       DATA_TYPE denom( dot(N,ray.getDir()) );
00726       if(gmtl::Math::abs(denom) < eps)    // Ray parallel to plane
00727       {
00728          t = 0;
00729          if(distance(plane, ray.mOrigin) < eps)     // Test for ray on plane
00730          { return true; }
00731          else
00732          { return false; }
00733       }
00734       t = dot( N, Vec<DATA_TYPE,3>(N * plane.getOffset() - ray.getOrigin()) ) / denom;
00735 
00736       return (DATA_TYPE)0 <= t;
00737    }
00738 
00749    template<class DATA_TYPE>
00750    bool intersect( const Plane<DATA_TYPE>& plane, const LineSeg<DATA_TYPE>& seg, DATA_TYPE& t )
00751    {
00752       bool res(intersect(plane, static_cast<Ray<DATA_TYPE> >(seg), t));
00753       return res && t <= (DATA_TYPE)1.0;
00754    }
00755 
00768    template<class DATA_TYPE>
00769    bool intersect( const Tri<DATA_TYPE>& tri, const Ray<DATA_TYPE>& ray,
00770                         float& u, float& v, float& t )
00771    {
00772       const float EPSILON = (DATA_TYPE)0.00001f;
00773       Vec<DATA_TYPE, 3> edge1, edge2, tvec, pvec, qvec;
00774       float det,inv_det;
00775 
00776       /* find vectors for two edges sharing vert0 */
00777       edge1 = tri[1] - tri[0];
00778       edge2 = tri[2] - tri[0];
00779 
00780       /* begin calculating determinant - also used to calculate U parameter */
00781       gmtl::cross( pvec, ray.getDir(), edge2 );
00782 
00783       /* if determinant is near zero, ray lies in plane of triangle */
00784       det = gmtl::dot( edge1, pvec );
00785 
00786       if (det < EPSILON)
00787          return false;
00788 
00789       /* calculate distance from vert0 to ray origin */
00790       tvec = ray.getOrigin() - tri[0];
00791 
00792       /* calculate U parameter and test bounds */
00793       u = gmtl::dot( tvec, pvec );
00794       if (u < 0.0 || u > det)
00795          return false;
00796 
00797       /* prepare to test V parameter */
00798       gmtl::cross( qvec, tvec, edge1 );
00799 
00800       /* calculate V parameter and test bounds */
00801       v = gmtl::dot( ray.getDir(), qvec );
00802       if (v < 0.0 || u + v > det)
00803          return false;
00804 
00805       /* calculate t, scale parameters, ray intersects triangle */
00806       t = gmtl::dot( edge2, qvec );
00807       inv_det = ((DATA_TYPE)1.0) / det;
00808       t *= inv_det;
00809       u *= inv_det;
00810       v *= inv_det;
00811 
00812       // test if t is within the ray boundary (when t >= 0)
00813       return t >= (DATA_TYPE)0;
00814    }
00815 
00832    template<class DATA_TYPE>
00833    bool intersectDoubleSided(const Tri<DATA_TYPE>& tri, const Ray<DATA_TYPE>& ray,
00834                              DATA_TYPE& u, DATA_TYPE& v, DATA_TYPE& t)
00835    {
00836       const DATA_TYPE EPSILON = (DATA_TYPE)0.00001f;
00837       Vec<DATA_TYPE, 3> edge1, edge2, tvec, pvec, qvec;
00838       DATA_TYPE det, inv_det;
00839 
00840       // Find vectors for two edges sharing vert0.
00841       edge1 = tri[1] - tri[0];
00842       edge2 = tri[2] - tri[0];
00843 
00844       // Begin calculating determinant - also used to calculate U parameter.
00845       gmtl::cross(pvec, ray.getDir(), edge2);
00846 
00847       // If determinant is near zero, ray lies in plane of triangle.
00848       det = gmtl::dot( edge1, pvec );
00849 
00850       if ( det < EPSILON && det > -EPSILON )
00851       {
00852          return false;
00853       }
00854 
00855       // calculate distance from vert0 to ray origin>
00856       tvec = ray.getOrigin() - tri[0];
00857 
00858       // Calc inverse deteriminant.
00859       inv_det = ((DATA_TYPE)1.0) / det; 
00860 
00861       // Calculate U parameter and test bounds.
00862       u =  inv_det * gmtl::dot(tvec, pvec);
00863       if ( u < 0.0 || u > 1.0 )
00864       {
00865          return false;
00866       }
00867 
00868       // Prepare to test V parameter.
00869       gmtl::cross(qvec, tvec, edge1);
00870 
00871       // Calculate V parameter and test bounds.
00872       v = inv_det * gmtl::dot(ray.getDir(), qvec);
00873       if (v < 0.0 || u + v > 1.0)
00874       {
00875          return false;
00876       }
00877 
00878       // Calculate t, scale parameters, ray intersects triangle.
00879       t = inv_det * gmtl::dot(edge2, qvec);
00880 
00881       // Test if t is within the ray boundary (when t >= 0).
00882       return t >= (DATA_TYPE)0;
00883    }
00884 
00897    template<class DATA_TYPE>
00898    bool intersect( const Tri<DATA_TYPE>& tri, const LineSeg<DATA_TYPE>& lineseg,
00899                    DATA_TYPE& u, DATA_TYPE& v, DATA_TYPE& t )
00900    {
00901       const DATA_TYPE eps = (DATA_TYPE)0.0001010101;
00902       DATA_TYPE l = length( lineseg.getDir() );
00903       if (eps < l)
00904       {
00905          Ray<DATA_TYPE> temp( lineseg.getOrigin(), lineseg.getDir() );
00906          bool result = intersect( tri, temp, u, v, t );
00907          return result && t <= (DATA_TYPE)1.0;
00908       }
00909       else
00910       {  return false; }
00911    }
00912 }
00913 
00914 
00915 
00916 #endif

Generated on Sun Sep 19 2010 14:35:14 for GenericMathTemplateLibrary by  doxygen 1.7.1