gKitGL
TriangleBox.h
00001 
00002 #ifndef _GK_TRIANGLEBOX_H
00003 #define _GK_TRIANGLEBOX_H
00004 
00005 #include "Geometry.h"
00006 #include "RTTriangle.h"
00007 
00008 
00009 namespace gk {
00010     
00011 //! representation d'un triangle pour la construction efficace d'une partition sah
00012 //! l'operation la plus frequente est l'obtention de la boite englobante du triangle et de son centre,
00013 //! pMin, pMax representent les points extremes de la bbox, et p stocke les autres coordonnees, 
00014 //! shuffle indexe pour chaque sommet dans quel point (pMin, pMax, p) se trouve chaque composante
00015 struct TriangleBox
00016 {
00017     gk::Point pMin;
00018     gk::Point pMax;
00019     gk::Point p;
00020     unsigned char shuffle[4];   // [abc0]= xindex | yindex | zindex
00021     //~ unsigned int id;
00022 
00023     enum
00024     {
00025         X_MASK= 2+1,
00026         Y_MASK= 8+4,
00027         Z_MASK= 32+16
00028     };
00029     
00030     enum
00031     {
00032         X_SHIFT= 0,
00033         Y_SHIFT= 2,
00034         Z_SHIFT= 4,
00035     };
00036     
00037     enum
00038     {
00039         PMIN_ID= 0,
00040         PMAX_ID= 1,
00041         P_ID= 2
00042     };
00043     
00044     //! retrouve les composantes d'un sommet du triangle.
00045     gk::Point vertex( const unsigned int v ) const
00046     {
00047         unsigned int idx= (shuffle[v] & X_MASK)>>X_SHIFT;
00048         float x= (&pMin)[idx].x;
00049         
00050         unsigned int idy= (shuffle[v] & Y_MASK)>>Y_SHIFT;
00051         float y= (&pMin)[idy].y;
00052         
00053         unsigned int idz= (shuffle[v] & Z_MASK)>>Z_SHIFT;
00054         float z= (&pMin)[idz].z;
00055         
00056         return gk::Point(x, y, z);
00057     }
00058     
00059     //! renvoie le sommet a du triangle abc.
00060     gk::Point a( ) const
00061     {
00062         return vertex(0);
00063     }
00064     
00065     //! renvoie le sommet b du triangle abc.
00066     gk::Point b( ) const
00067     {
00068         return vertex(1);
00069     }
00070     
00071     //! renvoie le sommet c du triangle abc.
00072     gk::Point c( ) const
00073     {
00074         return vertex(2);
00075     }
00076     
00077     unsigned int get_shuffle( const unsigned int shift, const float v, const float min, const float max, float& p )
00078     {
00079         if(v == min)
00080             return (PMIN_ID<<shift);
00081         
00082         else if(v == max)
00083             return (PMAX_ID<<shift);
00084         
00085         p= v;
00086         return (P_ID<<shift);
00087     }
00088     
00089     void init( const gk::Point& a, const gk::Point& b, const gk::Point& c )
00090     {
00091         BBox bounds(a, b);
00092         bounds.Union(c);
00093         pMin= bounds.pMin;
00094         pMax= bounds.pMax;
00095         
00096         shuffle[0]= get_shuffle(X_SHIFT, a.x, pMin.x, pMax.x, p.x);
00097         shuffle[0]|= get_shuffle(Y_SHIFT, a.y, pMin.y, pMax.y, p.y);
00098         shuffle[0]|= get_shuffle(Z_SHIFT, a.z, pMin.z, pMax.z, p.z);
00099 
00100         shuffle[1]= get_shuffle(X_SHIFT, b.x, pMin.x, pMax.x, p.x);
00101         shuffle[1]|= get_shuffle(Y_SHIFT, b.y, pMin.y, pMax.y, p.y);
00102         shuffle[1]|= get_shuffle(Z_SHIFT, b.z, pMin.z, pMax.z, p.z);
00103         
00104         shuffle[2]= get_shuffle(X_SHIFT, c.x, pMin.x, pMax.x, p.x);
00105         shuffle[2]|= get_shuffle(Y_SHIFT, c.y, pMin.y, pMax.y, p.y);
00106         shuffle[2]|= get_shuffle(Z_SHIFT, c.z, pMin.z, pMax.z, p.z);
00107         
00108         shuffle[3]= 0;
00109         
00110     #if 0
00111         printf("pMin "); pMin.print();
00112         printf("pMax "); pMax.print();
00113         printf("p "); p.print();
00114         
00115         printf("a "); a.print();
00116         printf("  shuffle %d %d %d, values ", 
00117             (shuffle[0] & X_MASK)>>X_SHIFT, (shuffle[0] & Y_MASK)>>Y_SHIFT, (shuffle[0] & Z_MASK)>>Z_SHIFT);
00118         vertex(0).print();
00119         
00120         printf("b "); b.print();
00121         printf("  shuffle %d %d %d, values ", 
00122             (shuffle[1] & X_MASK)>>X_SHIFT, (shuffle[1] & Y_MASK)>>Y_SHIFT, (shuffle[2] & Z_MASK)>>Z_SHIFT);
00123         vertex(1).print();
00124         printf("c "); c.print();
00125         printf("  shuffle %d %d %d, values ", 
00126             (shuffle[2] & X_MASK)>>X_SHIFT, (shuffle[2] & Y_MASK)>>Y_SHIFT, (shuffle[2] & Z_MASK)>>Z_SHIFT);
00127         vertex(2).print();
00128     #endif
00129     }
00130     
00131     //! constructeur par defaut.
00132     TriangleBox( ) 
00133         //~ :
00134         //~ id(-1)
00135     {}
00136     
00137     //! construit un triangle connaissant ses 3 sommets.
00138     TriangleBox( const gk::Point& _a, const gk::Point& _b, const gk::Point& _c, const unsigned int _id= -1 )
00139         //~ :
00140         //~ id(_id)
00141     {
00142         init(_a, _b, _c);
00143         assert(a() == _a);
00144         assert(b() == _b);
00145         assert(c() == _c);
00146     }
00147     
00148     //! construit un triangle a partir d'un triangle 'geometrique'.
00149     TriangleBox( const gk::Triangle& triangle, const unsigned int _id= -1 )
00150         //~ :
00151         //~ id(_id)
00152     {
00153         init(triangle.a, triangle.b, triangle.c);
00154         assert(a() == triangle.a);
00155         assert(b() == triangle.b);
00156         assert(c() == triangle.c);
00157     }
00158     
00159     //! destructeur.
00160     ~TriangleBox( ) {}
00161  
00162     //! renvoie la bbox du triangle.
00163     gk::BBox getBBox( ) const
00164     {
00165         gk::BBox bbox;
00166         bbox.pMin= pMin;
00167         bbox.pMax= pMax;
00168         
00169         return bbox;
00170     }
00171     
00172     //! renvoie une composante du centre de la bbox du triangle.
00173     float getBBoxCenter( const int axis ) const
00174     {
00175         return .5f * (pMin[axis] + pMax[axis]);
00176     }
00177 
00178     //! intersection avec un rayon.
00179     //! 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.
00180     //! renvoie vrai + les coordonnees barycentriques du point d'intersection + sa position le long du rayon.
00181     //! convention barycentrique : t(u, v)= (1 - u - v) * a + u * b + v * c
00182     /*! "Fast, Minimum Storage Ray/Triangle Intersection"
00183         cf http://www.acm.org/jgt/papers/MollerTrumbore97/
00184     */
00185     bool Intersect( const gk::BasicRay &ray, const float htmax, 
00186         float &rt, float &ru, float&rv ) const
00187     {
00188         // solution naive : extrait les composantes des sommets abc et renvoie un objet triangle classique.
00189         return gk::RTTriangle(a(), b(), c()).Intersect(ray, htmax, rt, ru, rv);
00190     }
00191 };
00192 
00193 }
00194 
00195 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends