00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_INTERSECTION_3
00025 #define __VCGLIB_INTERSECTION_3
00026
00027 #include <vcg/math/base.h>
00028 #include <vcg/space/point3.h>
00029 #include <vcg/space/line3.h>
00030 #include <vcg/space/ray3.h>
00031 #include <vcg/space/plane3.h>
00032 #include <vcg/space/segment3.h>
00033 #include <vcg/space/sphere3.h>
00034 #include <vcg/space/triangle3.h>
00035 #include <vcg/space/intersection/triangle_triangle3.h>
00036
00037
00038
00039
00040 namespace vcg {
00047
00048 template<class T>
00049 inline bool IntersectionLineSphere( const Sphere3<T> & sp, const Line3<T> & li, Point3<T> & p0,Point3<T> & p1 ){
00050
00051
00052
00053 Point3<T> neworig=li.Origin()-sp.Center();
00054
00055 T t1 = li.Direction().X()*li.Direction().X();
00056 T t2 = li.Direction().Y()*li.Direction().Y();
00057 T t3 = li.Direction().Z()*li.Direction().Z();
00058 T t6 = neworig.Y()*li.Direction().Y();
00059 T t7 = neworig.X()*li.Direction().X();
00060 T t8 = neworig.Z()*li.Direction().Z();
00061 T t15 = sp.Radius()*sp.Radius();
00062 T t17 = neworig.Z()*neworig.Z();
00063 T t19 = neworig.Y()*neworig.Y();
00064 T t21 = neworig.X()*neworig.X();
00065 T t28 = T(2.0*t7*t6+2.0*t6*t8+2.0*t7*t8+t1*t15-t1*t17-t1*t19-t2*t21+t2*t15-t2*t17-t3*t21+t3*t15-t3*t19);
00066 if(t28<0) return false;
00067 T t29 = sqrt(t28);
00068 T val0 = 1/(t1+t2+t3)*(-t6-t7-t8+t29);
00069 T val1 = 1/(t1+t2+t3)*(-t6-t7-t8-t29);
00070
00071 p0=li.P(val0);
00072 p1=li.P(val1);
00073 return true;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 template < class SCALAR_TYPE >
00086 inline int IntersectionSegmentSphere(const Sphere3<SCALAR_TYPE>& sphere, const Segment3<SCALAR_TYPE>& segment, Point3<SCALAR_TYPE> & t0, Point3<SCALAR_TYPE> & t1)
00087 {
00088 typedef SCALAR_TYPE ScalarType;
00089 typedef typename vcg::Point3< ScalarType > Point3t;
00090
00091 Point3t s = segment.P0() - sphere.Center();
00092 Point3t r = segment.P1() - segment.P0();
00093
00094 ScalarType rho2 = sphere.Radius()*sphere.Radius();
00095
00096 ScalarType sr = s*r;
00097 ScalarType r_squared_norm = r.SquaredNorm();
00098 ScalarType s_squared_norm = s.SquaredNorm();
00099 ScalarType sigma = sr*sr - r_squared_norm*(s_squared_norm-rho2);
00100
00101 if (sigma<ScalarType(0.0))
00102 return 0;
00103
00104 ScalarType sqrt_sigma = ScalarType(sqrt( ScalarType(sigma) ));
00105 ScalarType lambda1 = (-sr - sqrt_sigma)/r_squared_norm;
00106 ScalarType lambda2 = (-sr + sqrt_sigma)/r_squared_norm;
00107
00108 int solution_count = 0;
00109 if (ScalarType(0.0)<=lambda1 && lambda1<=ScalarType(1.0))
00110 {
00111 ScalarType t_enter = std::max< ScalarType >(lambda1, ScalarType(0.0));
00112 t0 = segment.P0() + r*t_enter;
00113 solution_count++;
00114 }
00115
00116 if (ScalarType(0.0)<=lambda2 && lambda2<=ScalarType(1.0))
00117 {
00118 Point3t *pt = (solution_count>0) ? &t1 : &t0;
00119 ScalarType t_exit = std::min< ScalarType >(lambda2, ScalarType(1.0));
00120 *pt = segment.P0() + r*t_exit;
00121 solution_count++;
00122 }
00123 return solution_count;
00124 };
00125
00126
00136 template < class SCALAR_TYPE, class TRIANGLETYPE >
00137 bool IntersectionSphereTriangle(const vcg::Sphere3 < SCALAR_TYPE > & sphere ,
00138 TRIANGLETYPE triangle,
00139 vcg::Point3 < SCALAR_TYPE > & witness ,
00140 std::pair< SCALAR_TYPE, SCALAR_TYPE > * res=NULL)
00141 {
00142 typedef SCALAR_TYPE ScalarType;
00143 typedef typename vcg::Point3< ScalarType > Point3t;
00144
00145 bool penetration_detected = false;
00146
00147 ScalarType radius = sphere.Radius();
00148 Point3t center = sphere.Center();
00149 Point3t p0 = triangle.P(0)-center;
00150 Point3t p1 = triangle.P(1)-center;
00151 Point3t p2 = triangle.P(2)-center;
00152
00153 Point3t p10 = p1-p0;
00154 Point3t p21 = p2-p1;
00155 Point3t p20 = p2-p0;
00156
00157 ScalarType delta0_p01 = p10.dot(p1);
00158 ScalarType delta1_p01 = -p10.dot(p0);
00159 ScalarType delta0_p02 = p20.dot(p2);
00160 ScalarType delta2_p02 = -p20.dot(p0);
00161 ScalarType delta1_p12 = p21.dot(p2);
00162 ScalarType delta2_p12 = -p21.dot(p1);
00163
00164
00165 if (delta1_p01<=ScalarType(0.0) && delta2_p02<=ScalarType(0.0)) { witness = p0; }
00166 else if (delta0_p01<=ScalarType(0.0) && delta2_p12<=ScalarType(0.0)) { witness = p1; }
00167 else if (delta0_p02<=ScalarType(0.0) && delta1_p12<=ScalarType(0.0)) { witness = p2; }
00168 else
00169 {
00170 ScalarType temp = p10.dot(p2);
00171 ScalarType delta0_p012 = delta0_p01*delta1_p12 + delta2_p12*temp;
00172 ScalarType delta1_p012 = delta1_p01*delta0_p02 - delta2_p02*temp;
00173 ScalarType delta2_p012 = delta2_p02*delta0_p01 - delta1_p01*(p20.dot(p1));
00174
00175
00176 if (delta0_p012<=ScalarType(0.0))
00177 {
00178 ScalarType denominator = delta1_p12+delta2_p12;
00179 ScalarType mu1 = delta1_p12/denominator;
00180 ScalarType mu2 = delta2_p12/denominator;
00181 witness = (p1*mu1 + p2*mu2);
00182 }
00183 else if (delta1_p012<=ScalarType(0.0))
00184 {
00185 ScalarType denominator = delta0_p02+delta2_p02;
00186 ScalarType mu0 = delta0_p02/denominator;
00187 ScalarType mu2 = delta2_p02/denominator;
00188 witness = (p0*mu0 + p2*mu2);
00189 }
00190 else if (delta2_p012<=ScalarType(0.0))
00191 {
00192 ScalarType denominator = delta0_p01+delta1_p01;
00193 ScalarType mu0 = delta0_p01/denominator;
00194 ScalarType mu1 = delta1_p01/denominator;
00195 witness = (p0*mu0 + p1*mu1);
00196 }
00197 else
00198 {
00199
00200 ScalarType denominator = delta0_p012 + delta1_p012 + delta2_p012;
00201 ScalarType lambda0 = delta0_p012/denominator;
00202 ScalarType lambda1 = delta1_p012/denominator;
00203 ScalarType lambda2 = delta2_p012/denominator;
00204 witness = p0*lambda0 + p1*lambda1 + p2*lambda2;
00205 }
00206 }
00207
00208 if (res!=NULL)
00209 {
00210 ScalarType witness_norm = witness.Norm();
00211 res->first = std::max< ScalarType >( witness_norm-radius, ScalarType(0.0) );
00212 res->second = std::max< ScalarType >( radius-witness_norm, ScalarType(0.0) );
00213 }
00214 penetration_detected = (witness.SquaredNorm() <= (radius*radius));
00215 witness += center;
00216 return penetration_detected;
00217 };
00218
00220 template<class T>
00221 inline bool IntersectionPlaneLine( const Plane3<T> & pl, const Line3<T> & li, Point3<T> & po){
00222 const T epsilon = T(1e-8);
00223
00224 T k = pl.Direction().dot(li.Direction());
00225 if( (k > -epsilon) && (k < epsilon))
00226 return false;
00227 T r = (pl.Offset() - pl.Direction().dot(li.Origin()))/k;
00228 po = li.Origin() + li.Direction()*r;
00229 return true;
00230 }
00232 template<class T>
00233 inline bool IntersectionLinePlane(const Line3<T> & li, const Plane3<T> & pl, Point3<T> & po){
00234
00235 return IntersectionPlaneLine(pl,li,po);
00236 }
00237
00239 template<class T>
00240 inline bool IntersectionPlaneSegment( const Plane3<T> & pl, const Segment3<T> & s, Point3<T> & p0){
00241 T p1_proj = s.P1()*pl.Direction()-pl.Offset();
00242 T p0_proj = s.P0()*pl.Direction()-pl.Offset();
00243 if ( (p1_proj>0)-(p0_proj<0)) return false;
00244
00245 if(p0_proj == p1_proj) return false;
00246
00247
00248 if(p0_proj < p1_proj)
00249 p0 = s.P0() + (s.P1()-s.P0()) * fabs(p0_proj/(p1_proj-p0_proj));
00250 if(p0_proj > p1_proj)
00251 p0 = s.P1() + (s.P0()-s.P1()) * fabs(p1_proj/(p0_proj-p1_proj));
00252
00253 return true;
00254 }
00255
00257 template<class ScalarType>
00258 inline bool IntersectionPlaneSegmentEpsilon(const Plane3<ScalarType> & pl,
00259 const Segment3<ScalarType> & sg,
00260 Point3<ScalarType> & po,
00261 const ScalarType epsilon = ScalarType(1e-8)){
00262
00263 typedef ScalarType T;
00264 T k = pl.Direction().dot((sg.P1()-sg.P0()));
00265 if( (k > -epsilon) && (k < epsilon))
00266 return false;
00267 T r = (pl.Offset() - pl.Direction().dot(sg.P0()))/k;
00268 if( (r<0) || (r > 1.0))
00269 return false;
00270 po = sg.P0()*(1-r)+sg.P1() * r;
00271 return true;
00272 }
00273
00275
00276
00277
00278 template<typename TRIANGLETYPE>
00279 inline bool IntersectionPlaneTriangle( const Plane3<typename TRIANGLETYPE::ScalarType> & pl,
00280 const TRIANGLETYPE & tr,
00281 Segment3<typename TRIANGLETYPE::ScalarType> & sg)
00282 {
00283 typedef typename TRIANGLETYPE::ScalarType T;
00284 if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(1)),sg.P0()))
00285 {
00286 if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(2)),sg.P1()))
00287 return true;
00288 else
00289 {
00290 if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(1),tr.cP(2)),sg.P1()))
00291 return true;
00292 else assert(0);
00293 return true;
00294 }
00295 }
00296 else
00297 {
00298 if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(1),tr.cP(2)),sg.P0()))
00299 {
00300 if(IntersectionPlaneSegment(pl,Segment3<T>(tr.cP(0),tr.cP(2)),sg.P1()))return true;
00301 assert(0);
00302 return true;
00303 }
00304 }
00305 return false;
00306 }
00307
00309 template<typename TRIANGLETYPE>
00310 inline bool IntersectionTriangleTriangle(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1){
00311 return NoDivTriTriIsect(t0.cP(0),t0.cP(1),t0.cP(2),
00312 t1.cP(0),t1.cP(1),t1.cP(2));
00313 }
00314
00315 template<class T>
00316 inline bool IntersectionTriangleTriangle(Point3<T> V0,Point3<T> V1,Point3<T> V2,
00317 Point3<T> U0,Point3<T> U1,Point3<T> U2){
00318 return NoDivTriTriIsect(V0,V1,V2,U0,U1,U2);
00319 }
00320 #if 0
00321 template<class T>
00322 inline bool Intersection(Point3<T> V0,Point3<T> V1,Point3<T> V2,
00323 Point3<T> U0,Point3<T> U1,Point3<T> U2,int *coplanar,
00324 Point3<T> &isectpt1,Point3<T> &isectpt2){
00325
00326 return tri_tri_intersect_with_isectline(V0,V1,V2,U0,U1,U2,
00327 coplanar,isectpt1,isectpt2);
00328 }
00329
00330 template<typename TRIANGLETYPE,typename SEGMENTTYPE >
00331 inline bool Intersection(const TRIANGLETYPE & t0,const TRIANGLETYPE & t1,bool &coplanar,
00332 SEGMENTTYPE & sg){
00333 Point3<typename SEGMENTTYPE::PointType> ip0,ip1;
00334 return tri_tri_intersect_with_isectline(t0.P0(0),t0.P0(1),t0.P0(2),
00335 t1.P0(0),t1.P0(1),t1.P0(2),
00336 coplanar,sg.P0(),sg.P1()
00337 );
00338 }
00339
00340 #endif
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 template<class T>
00359 bool IntersectionLineTriangle( const Line3<T> & line, const Point3<T> & vert0,
00360 const Point3<T> & vert1, const Point3<T> & vert2,
00361 T & t ,T & u, T & v)
00362 {
00363 #define EPSIL 0.000001
00364
00365 vcg::Point3<T> edge1, edge2, tvec, pvec, qvec;
00366 T det,inv_det;
00367
00368
00369 edge1 = vert1 - vert0;
00370 edge2 = vert2 - vert0;
00371
00372
00373 pvec = line.Direction() ^ edge2;
00374
00375
00376 det = edge1 * pvec;
00377
00378
00379 tvec = line.Origin() - vert0;
00380 inv_det = 1.0 / det;
00381
00382 qvec = tvec ^ edge1;
00383
00384 if (det > EPSIL)
00385 {
00386 u = tvec * pvec ;
00387 if ( u < 0.0 || u > det)
00388 return 0;
00389
00390
00391 v = line.Direction() * qvec;
00392 if ( v < 0.0 || u + v > det)
00393 return 0;
00394
00395 }
00396 else if(det < -EPSIL)
00397 {
00398
00399 u = tvec * pvec ;
00400 if ( u > 0.0 || u < det)
00401 return 0;
00402
00403
00404 v = line.Direction() * qvec ;
00405 if ( v > 0.0 || u + v < det)
00406 return 0;
00407 }
00408 else return 0;
00409
00410 t = edge2 * qvec * inv_det;
00411 ( u) *= inv_det;
00412 ( v) *= inv_det;
00413
00414 return 1;
00415 }
00416
00417 template<class T>
00418 bool IntersectionRayTriangle( const Ray3<T> & ray, const Point3<T> & vert0,
00419 const Point3<T> & vert1, const Point3<T> & vert2,
00420 T & t ,T & u, T & v)
00421 {
00422 Line3<T> line(ray.Origin(), ray.Direction());
00423 if (IntersectionLineTriangle(line, vert0, vert1, vert2, t, u, v))
00424 {
00425 if (t < 0) return 0;
00426 else return 1;
00427 }else return 0;
00428 }
00429
00430
00431 template<class T>
00432 bool IntersectionLineBox( const Box3<T> & box, const Line3<T> & r, Point3<T> & coord )
00433 {
00434 const int NUMDIM = 3;
00435 const int RIGHT = 0;
00436 const int LEFT = 1;
00437 const int MIDDLE = 2;
00438
00439 int inside = 1;
00440 char quadrant[NUMDIM];
00441 int i;
00442 int whichPlane;
00443 Point3<T> maxT,candidatePlane;
00444
00445
00446
00447 for (i=0; i<NUMDIM; i++)
00448 {
00449 if(r.Origin()[i] < box.min[i])
00450 {
00451 quadrant[i] = LEFT;
00452 candidatePlane[i] = box.min[i];
00453 inside = 0;
00454 }
00455 else if (r.Origin()[i] > box.max[i])
00456 {
00457 quadrant[i] = RIGHT;
00458 candidatePlane[i] = box.max[i];
00459 inside = 0;
00460 }
00461 else
00462 {
00463 quadrant[i] = MIDDLE;
00464 }
00465 }
00466
00467
00468 if(inside){
00469 coord = r.Origin();
00470 return true;
00471 }
00472
00473
00474 for (i = 0; i < NUMDIM; i++)
00475 {
00476 if (quadrant[i] != MIDDLE && r.Direction()[i] !=0.)
00477 maxT[i] = (candidatePlane[i]-r.Origin()[i]) / r.Direction()[i];
00478 else
00479 maxT[i] = -1.;
00480 }
00481
00482
00483 whichPlane = 0;
00484 for (i = 1; i < NUMDIM; i++)
00485 if (maxT[whichPlane] < maxT[i])
00486 whichPlane = i;
00487
00488
00489 if (maxT[whichPlane] < 0.) return false;
00490 for (i = 0; i < NUMDIM; i++)
00491 if (whichPlane != i)
00492 {
00493 coord[i] = r.Origin()[i] + maxT[whichPlane] *r.Direction()[i];
00494 if (coord[i] < box.min[i] || coord[i] > box.max[i])
00495 return false;
00496 }
00497 else
00498 {
00499 coord[i] = candidatePlane[i];
00500 }
00501 return true;
00502 }
00503
00504
00505 template<class T>
00506 bool IntersectionRayBox( const Box3<T> & box, const Ray3<T> & r, Point3<T> & coord )
00507 {
00508 Line3<T> l;
00509 l.SetOrigin(r.Origin());
00510 l.SetDirection(r.Direction());
00511 return(IntersectionLineBox<T>(box,l,coord));
00512 }
00513
00514
00515 template<class ScalarType>
00516 bool IntersectionSegmentBox( const Box3<ScalarType> & box,
00517 const Segment3<ScalarType> & s,
00518 Point3<ScalarType> & coord )
00519 {
00520
00521 Box3<ScalarType> test;
00522 test.Add(s.P0());
00523 test.Add(s.P1());
00524 if (!test.Collide(box))
00525 return false;
00526 else
00527 {
00528 Line3<ScalarType> l;
00529 Point3<ScalarType> dir=s.P1()-s.P0();
00530 dir.Normalize();
00531 l.SetOrigin(s.P0());
00532 l.SetDirection(dir);
00533 if(IntersectionLineBox<ScalarType>(box,l,coord))
00534 return (test.IsIn(coord));
00535 return false;
00536 }
00537 }
00538
00539
00540 template<class ScalarType>
00541 int IntersectionSegmentBox( const Box3<ScalarType> & box,
00542 const Segment3<ScalarType> & s,
00543 Point3<ScalarType> & coord0,
00544 Point3<ScalarType> & coord1 )
00545 {
00546 int num=0;
00547 Segment3<ScalarType> test= s;
00548 if (IntersectionSegmentBox(box,test,coord0 ))
00549 {
00550 num++;
00551 Point3<ScalarType> swap=test.P0();
00552 test.P0()=test.P1();
00553 test.P1()=swap;
00554 if (IntersectionSegmentBox(box,test,coord1 ))
00555 num++;
00556 }
00557 return num;
00558 }
00559
00570 template<class ScalarType>
00571 bool IntersectionSegmentTriangle( const vcg::Segment3<ScalarType> & seg,
00572 const Point3<ScalarType> & vert0,
00573 const Point3<ScalarType> & vert1, const
00574 Point3<ScalarType> & vert2,
00575 ScalarType & a ,ScalarType & b)
00576 {
00577
00578 vcg::Box3<ScalarType> bb0,bb1;
00579 bb0.Add(seg.P0());
00580 bb0.Add(seg.P1());
00581 bb1.Add(vert0);
00582 bb1.Add(vert1);
00583 bb1.Add(vert2);
00584 Point3<ScalarType> inter;
00585 if (!bb0.Collide(bb1))
00586 return false;
00587 if (!vcg::IntersectionSegmentBox(bb1,seg,inter))
00588 return false;
00589
00590
00591 vcg::Line3<ScalarType> line;
00592 vcg::Point3<ScalarType> dir;
00593 ScalarType length=seg.Length();
00594 dir=(seg.P1()-seg.P0());
00595 dir.Normalize();
00596 line.Set(seg.P0(),dir);
00597 ScalarType orig_dist;
00598 if(IntersectionLineTriangle<ScalarType>(line,vert0,vert1,vert2,orig_dist,a,b))
00599 return (orig_dist>=0 && orig_dist<=length);
00600 return false;
00601 }
00606 template<class TriangleType>
00607 bool IntersectionSegmentTriangle( const vcg::Segment3<typename TriangleType::ScalarType> & seg,
00608 const TriangleType &t,
00609 typename TriangleType::ScalarType & a ,typename TriangleType::ScalarType & b)
00610 {
00611 return IntersectionSegmentTriangle(seg,t.cP(0),t.cP(1),t.cP(2),a,b);
00612 }
00613
00614 template<class ScalarType>
00615 bool IntersectionPlaneBox(const vcg::Plane3<ScalarType> &pl,
00616 vcg::Box3<ScalarType> &bbox)
00617 {
00618 ScalarType dist,dist1;
00619 if(bbox.IsNull()) return false;
00620 dist = SignedDistancePlanePoint(pl,bbox.P(0)) ;
00621 for (int i=1;i<8;i++) if( SignedDistancePlanePoint(pl,bbox.P(i))*dist<0) return true;
00622 return true;
00623 }
00624
00625 template<class ScalarType>
00626 bool IntersectionTriangleBox(const vcg::Box3<ScalarType> &bbox,
00627 const vcg::Point3<ScalarType> &p0,
00628 const vcg::Point3<ScalarType> &p1,
00629 const vcg::Point3<ScalarType> &p2)
00630 {
00631 typedef typename vcg::Point3<ScalarType> CoordType;
00632 CoordType intersection;
00634 vcg::Box3<ScalarType> test;
00635 test.SetNull();
00636 test.Add(p0);
00637 test.Add(p1);
00638 test.Add(p2);
00639 if (!test.Collide(bbox))
00640 return false;
00642 if ((bbox.IsIn(p0))||(bbox.IsIn(p1))||(bbox.IsIn(p2)))
00643 return true;
00644
00646
00647
00648
00649
00650
00652 if (IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p0,p1),intersection)||
00653 IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p1,p2),intersection)||
00654 IntersectionSegmentBox<ScalarType>(bbox,vcg::Segment3<ScalarType>(p2,p0),intersection))
00655 return true;
00657
00658 Segment3<ScalarType> diag[4];
00659
00660 diag[0]=Segment3<ScalarType>(bbox.P(0),bbox.P(7));
00661 diag[1]=Segment3<ScalarType>(bbox.P(1),bbox.P(6));
00662 diag[2]=Segment3<ScalarType>(bbox.P(2),bbox.P(5));
00663 diag[3]=Segment3<ScalarType>(bbox.P(3),bbox.P(4));
00664 ScalarType a,b;
00665 for (int i=0;i<3;i++)
00666 if (IntersectionSegmentTriangle<ScalarType>(diag[i],p0,p1,p2,a,b))
00667 return true;
00668
00669 return false;
00670 }
00671
00672 template <class SphereType>
00673 bool IntersectionSphereSphere( const SphereType & s0,const SphereType & s1){
00674 return (s0.Center()-s1.Center()).SquaredNorm() < (s0.Radius()+s1.Radius())*(s0.Radius()+s1.Radius());
00675 }
00676
00677 template<class T>
00678 bool IntersectionPlanePlane (const Plane3<T> & plane0, const Plane3<T> & plane1,
00679 Line3<T> & line)
00680 {
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 T n00 = plane0.Direction()*plane0.Direction();
00701 T n01 = plane0.Direction()*plane1.Direction();
00702 T n11 = plane1.Direction()*plane1.Direction();
00703 T det = n00*n11-n01*n01;
00704
00705 const T tolerance = (T)(1e-06f);
00706 if ( math::Abs(det) < tolerance )
00707 return false;
00708
00709 T invDet = 1.0f/det;
00710 T c0 = (n11*plane0.Offset() - n01*plane1.Offset())*invDet;
00711 T c1 = (n00*plane1.Offset() - n01*plane0.Offset())*invDet;
00712
00713 line.SetDirection(plane0.Direction()^plane1.Direction());
00714 line.SetOrigin(plane0.Direction()*c0+ plane1.Direction()*c1);
00715
00716 return true;
00717 }
00718
00719
00720
00721 template <bool BACKFACETEST = true>
00722 class RayTriangleIntersectionFunctor {
00723 public:
00724 template <class TRIANGLETYPE, class SCALARTYPE>
00725 inline bool operator () (const TRIANGLETYPE & f, const Ray3<SCALARTYPE> & ray, SCALARTYPE & t) {
00726 typedef SCALARTYPE ScalarType;
00727 ScalarType u;
00728 ScalarType v;
00729
00730 bool bret = IntersectionRayTriangle(ray, Point3<SCALARTYPE>::Construct(f.cP(0)), Point3<SCALARTYPE>::Construct(f.cP(1)), Point3<SCALARTYPE>::Construct(f.cP(2)), t, u, v);
00731 if (BACKFACETEST) {
00732 if (!bret) {
00733 bret = IntersectionRayTriangle(ray, Point3<SCALARTYPE>::Construct(f.cP(0)), Point3<SCALARTYPE>::Construct(f.cP(2)), Point3<SCALARTYPE>::Construct(f.cP(1)), t, u, v);
00734 }
00735 }
00736 return (bret);
00737 }
00738 };
00739
00740
00744 }
00745 #endif