gKitGL
|
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