gKitGL
RTTriangle.h
00001 
00002 #ifndef _RT_TRIANGLE_H
00003 #define _RT_TRIANGLE_H
00004 
00005 #include "Triangle.h"
00006 #include "Geometry.h"
00007 
00008 namespace gk {
00009 
00010 //! representation d'un triangle pour l'intersecteur rayon / triangle.
00011 struct RTTriangle
00012 {
00013     Point pa;
00014     Vector ab;
00015     Vector ac;
00016     unsigned int id;
00017     
00018     //! constructeur par defaut.
00019     RTTriangle( ) {}
00020     
00021     //! construit un triangle connaissant ses 3 sommets.
00022     RTTriangle( const Point& _a, const Point& _b, const Point& _c )
00023         :
00024         pa(_a),  ab(_a, _b), ac(_a, _c)
00025     {}
00026     
00027     //! construit un triangle a partir d'un triangle 'geometrique'.
00028     RTTriangle( const Triangle& triangle )
00029         :
00030         pa(triangle.a),  ab(triangle.a, triangle.b), ac(triangle.a, triangle.c)
00031     {}
00032     
00033     //! destructeur.
00034     ~RTTriangle( ) {}
00035     
00036     gk::Point a( ) const
00037     {
00038         return pa;
00039     }
00040     
00041     gk::Point b( ) const
00042     {
00043         return pa + ab;
00044     }
00045     
00046     gk::Point c( ) const
00047     {
00048         return pa + ac;
00049     }
00050     
00051     float getArea( ) const
00052     {
00053         return .5f * Cross(ab, ac).Length();
00054     }
00055     
00056     BBox getBBox( ) const
00057     {
00058         BBox bbox(pa, pa+ab);
00059         bbox.Union(pa + ac);
00060         return bbox;
00061     }
00062     
00063     float getBBoxCenter( const int axis ) const
00064     {
00065         float pMin ; 
00066         float pMax;
00067         pMin= std::min(pa[axis], pa[axis] + ab[axis]);
00068         pMin= std::min(pMin, pa[axis] + ac[axis]);
00069         pMax= std::max(pa[axis], pa[axis] + ab[axis]);
00070         pMax= std::max(pMax, pa[axis] + ac[axis]);
00071         return .5f * (pMin + pMax);
00072     }
00073     
00074     Point getCenter( ) const
00075     {
00076         return pa + (ab + ac) / 3.f;
00077     }
00078     
00079     float getCenter( const int axis ) const
00080     {
00081         return pa[axis] + (ab[axis] + ac[axis]) / 3.f;
00082     }
00083     
00084     //! calcule la normale geometrique du triangle.
00085     void getTriangleNormal( Normal &n ) const
00086     {
00087         n= Normal( Normalize(Cross(ab, ac)) ) ;
00088     }
00089 
00090     Normal getTriangleNormal( ) const
00091     {
00092         return Normal( Normalize( Cross(ab, ac) ));
00093     }
00094     
00095     //! intersection avec un rayon.
00096     //! renvoie faux s'il n'y a pas d'intersection, une intersection peut exister mais peut ne pas se trouver dans [tmin tmax] du rayon.
00097     //! renvoie vrai + les coordonnees barycentriques du point d'intersection + sa position le long du rayon.
00098     //! convention barycentrique : t(u, v)= (1 - u - v) * a + u * b + v * c
00099     /*! "Fast, Minimum Storage Ray/Triangle Intersection"
00100         cf http://www.acm.org/jgt/papers/MollerTrumbore97/
00101     */
00102     bool Intersect( const Ray &ray, const float htmax, 
00103         float &rt, float &ru, float&rv ) const
00104     {
00105         /* begin calculating determinant - also used to calculate U parameter */
00106         const Vector pvec= Cross(ray.d, ac);
00107         
00108         /* if determinant is near zero, ray lies in plane of triangle */
00109         const float det= Dot(ab, pvec);
00110         if (det > -EPSILON && det < EPSILON)
00111             return false;
00112         
00113         const float inv_det= 1.0f / det;
00114         
00115         /* calculate distance from vert0 to ray origin */
00116         const Vector tvec(pa, ray.o);
00117         
00118         /* calculate U parameter and test bounds */
00119         const float u= Dot(tvec, pvec) * inv_det;
00120         if(u < 0.0f || u > 1.0f)
00121             return false;
00122         
00123         /* prepare to test V parameter */
00124         const Vector qvec= Cross(tvec, ab);
00125         
00126         /* calculate V parameter and test bounds */
00127         const float v= Dot(ray.d, qvec) * inv_det;
00128         if(v < 0.0f || u + v > 1.0f)
00129             return false;
00130         
00131         /* calculate t, ray intersects triangle */
00132         rt= Dot(ac, qvec) * inv_det;
00133         ru= u;
00134         rv= v;
00135         
00136         // ne renvoie vrai que si l'intersection est valide (comprise entre tmin et tmax du rayon)
00137         //~ return (rt < htmax && rt > ray.tmin);
00138         return (rt < htmax && rt > RAY_EPSILON);
00139     }
00140     
00141     bool Intersect( const BasicRay &ray, const float htmax, 
00142         float &rt, float &ru, float&rv ) const
00143     {
00144         /* begin calculating determinant - also used to calculate U parameter */
00145         const Vector pvec= Cross(ray.d, ac);
00146         
00147         /* if determinant is near zero, ray lies in plane of triangle */
00148         const float det= Dot(ab, pvec);
00149         if (det > -EPSILON && det < EPSILON)
00150             return false;
00151         
00152         const float inv_det= 1.0f / det;
00153         
00154         /* calculate distance from vert0 to ray origin */
00155         const Vector tvec(pa, ray.o);
00156         
00157         /* calculate U parameter and test bounds */
00158         const float u= Dot(tvec, pvec) * inv_det;
00159         if(u < 0.0f || u > 1.0f)
00160             return false;
00161         
00162         /* prepare to test V parameter */
00163         const Vector qvec= Cross(tvec, ab);
00164         
00165         /* calculate V parameter and test bounds */
00166         const float v= Dot(ray.d, qvec) * inv_det;
00167         if(v < 0.0f || u + v > 1.0f)
00168             return false;
00169         
00170         /* calculate t, ray intersects triangle */
00171         rt= Dot(ac, qvec) * inv_det;
00172         ru= u;
00173         rv= v;
00174         
00175         // ne renvoie vrai que si l'intersection est valide (comprise entre tmin et tmax du rayon)
00176         //~ return (rt < htmax && rt > ray.tmin);
00177         return (rt < htmax && rt > RAY_EPSILON);
00178     }
00179 };
00180 
00181 }
00182 
00183 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends