shape_doc 0.1
|
00001 # include <shape/ssiqts.hpp> 00002 # include <shape/surface_parametric.hpp> 00003 # define ParametricSurface shape::surface_parametric<double> 00004 00005 namespace mmx { 00006 #include <shape/ssiqts_offsets.hpp> 00007 00008 static bool swap; 00009 00010 SSIQTS::sample::sample( ParametricSurface * s, int m, int n ) 00011 { 00012 m_uvals = new double[3*m*n+m+n]; 00013 m_vvals = m_uvals + m; 00014 m_svals = (fxv<double,3>*)(m_vvals + n); 00015 m_nrows = m; 00016 m_ncols = n; 00017 swap = true; s->sample((double*)m_svals,m,n,m_uvals,m_vvals); 00018 // for ( int i = 0; i < m*n; i ++ ) std::cout << m_svals[i] << std::endl; 00019 }; 00020 00021 SSIQTS::sample::~sample() { delete[] m_uvals; }; 00022 00023 static SSIQTS::aabb3 * alloc( int& l, int m, int& s ) 00024 { 00025 int c = m*m; 00026 s = 0; 00027 l = 0; 00028 while ( c ) { s += c; c /= 4; l ++; }; 00029 return new SSIQTS::aabb3[s]; 00030 }; 00031 00032 static void fillpatchbox( SSIQTS::aabb3& b, const SSIQTS::vector3 * a, SSIQTS& ssi ) 00033 { 00034 // unsigned nrows = ssi.m*ssi.udeg+1; 00035 unsigned ncols = ssi.m*ssi.vdeg+1; 00036 // unsigned srows = ssi.udeg*ncols; 00037 const SSIQTS::vector3 * la = a; 00038 const SSIQTS::vector3 * ela = a + (ssi.udeg+1)*ncols; 00039 const SSIQTS::vector3 * ca; 00040 for ( int d = 0; d < 3; d ++ ) b[d][0] = b[d][1] = (*a)[d]; 00041 for ( ca = a+1; ca != la + ssi.vdeg+1; ca++ ) 00042 for ( int d = 0; d < 3; d ++ ) 00043 { 00044 if ( (*ca)[d] < b[d][0] ) b[d][0] = (*ca)[d]; 00045 else if ( (*ca)[d] > b[d][1]) b[d][1] = (*ca)[d]; 00046 }; 00047 00048 for ( la = a+ncols; la != ela; la += ncols ) 00049 for ( ca = la; ca != la + ssi.vdeg+1; ca ++ ) 00050 for ( int d = 0; d < 3; d ++ ) 00051 { 00052 if ( (*ca)[d] < b[d][0] ) b[d][0] = (*ca)[d]; 00053 else if ( (*ca)[d] > b[d][1] ) b[d][1] = (*ca)[d]; 00054 }; 00055 }; 00056 00057 00058 static void fillboxes( SSIQTS::aabb3 * qta, const SSIQTS::vector3 * base, SSIQTS& ssi ) 00059 { 00060 unsigned nrows = ssi.m*ssi.udeg+1; 00061 unsigned ncols = ssi.m*ssi.vdeg+1; 00062 unsigned srows = ssi.udeg*ncols; 00063 const SSIQTS::vector3 * lptr = base; 00064 const SSIQTS::vector3 * cptr; 00065 const SSIQTS::vector3 * elptr = base + nrows*(ncols-1); 00066 for ( lptr = base; lptr != elptr; lptr += srows ) 00067 for ( cptr = lptr; cptr != lptr + ncols-1; cptr += ssi.vdeg, qta++ ) 00068 fillpatchbox( *qta, cptr, ssi ); 00069 }; 00070 00071 static bool intersectp( const SSIQTS::aabb3 & a, const SSIQTS::aabb3 & b ) 00072 { 00073 for ( int i = 0; i < 3; i ++ ) 00074 if ( a[i][1] < b[i][0] || b[i][1] < a[i][0] ) return false; 00075 return true; 00076 }; 00077 00078 static void merge( SSIQTS::aabb3 & box, const SSIQTS::aabb3& a, const SSIQTS::aabb3 & b ) 00079 { 00080 for ( unsigned i = 0; i < 3; i ++ ) 00081 { 00082 box[i][0] = std::min(a[i][0],b[i][0]); 00083 box[i][1] = std::max(a[i][1],b[i][1]); 00084 }; 00085 }; 00086 00087 static void update( SSIQTS::aabb3& box, const SSIQTS::aabb3& a, const SSIQTS::aabb3& b ) 00088 { 00089 double tmp; 00090 for ( int i = 0; i < 3; i ++ ) 00091 { 00092 tmp = std::min(a[i][0],b[i][0]); 00093 if ( tmp < box[i][0] ) box[i][0] = tmp; 00094 tmp = std::max(a[i][1],b[i][1]); 00095 if ( tmp > box[i][1] ) box[i][1] = tmp; 00096 }; 00097 }; 00098 00099 static void build( SSIQTS::aabb3 * base, const SSIQTS & ssi ) 00100 { 00101 int N = ssi.m; 00102 SSIQTS::aabb3 * cptr,*eptr,*next,*enext; 00103 cptr = base; 00104 eptr = base + N; 00105 next = base + N*N; 00106 enext = next + (N/2*N/2); 00107 00108 while ( next < enext ) 00109 { 00110 base = next; 00111 do 00112 { 00113 for ( ;cptr < eptr; cptr += 2, next++ ) 00114 { 00115 merge(*next,*cptr,*(cptr+1)); 00116 update(*next,*(cptr+N),*(cptr+1+N)); 00117 }; 00118 00119 cptr += N; 00120 eptr = cptr + N; 00121 } 00122 while ( next < enext ); 00123 cptr = base; 00124 N /= 2; 00125 eptr = cptr + N; 00126 enext = next + (N/2)*(N/2); 00127 }; 00128 }; 00129 00130 00131 /* tests de collision sur un niveau de subdivision */ 00132 static int cfhunt( 00133 SSIQTS::aabb3 * lbb, /* ensemble des boites de la surface "gauche" au niveau actuel de subdivision */ 00134 SSIQTS::aabb3 * rbb, /* ensemble des boites de la surface "droite" au niveau actuel de subdivision */ 00135 int * bcf, /* debut de la liste des conflits */ 00136 int * ecf ) /* fin de la liste des conflits */ 00137 { 00138 int s = 0; 00139 int * rqp; // right-quad pointer 00140 int * cf; 00141 int * lrqp; // the last right-quad pointer... 00142 00143 /* pour tous les conflits encore presents a la resolution actuelle */ 00144 for ( cf = bcf; cf != ecf; cf += *cf ) 00145 { 00146 const int lq = cf[cflq_]; // addresse de l'element de la surface "gauche" 00147 lrqp = cf+cfbg_; // debut de la liste des elements de "droite" 00148 /* pour tout les elements de droite test d'intersection avec l'element de gauche */ 00149 for ( rqp = lrqp; rqp != cf + *cf; rqp ++ ) 00150 { 00151 /* si les boites s'intersectent, tassement de la liste */ 00152 if ( intersectp(*(lbb+lq),*(rbb+*rqp)) ) { *lrqp++ = *rqp; }; 00153 }; 00154 if ( lrqp != rqp ) *lrqp = -1; // marque la fin de liste 00155 int nc = lrqp-(cf+cfbg_); // nombre de collisions restantes 00156 s += (nc)?4*(cfhsz+4*nc):0; // taille necessaire pour leurs subdivisions 00157 }; 00158 return s; // taille totale necessaire apres traitement d'un niveau de subdivision 00159 } 00160 00161 00162 static int * cfsimplify( int * bcf, int * ecf ) 00163 { 00164 int * necf = bcf; 00165 for ( int * cf = bcf; cf != ecf; ) 00166 { 00167 int * rp = cf+cfbg_; 00168 // int i = 0; 00169 int * dst = necf+cfbg_; 00170 while( *rp != -1 && rp < cf + *cf ) *dst++ = *rp++; 00171 necf[cflq_] = cf[cflq_]; 00172 00173 cf += *cf; 00174 *necf = dst-necf; 00175 necf += *necf; 00176 }; 00177 return necf; 00178 }; 00179 00180 static int * expandcf( int * cf, int * ncf, int m ) 00181 { 00182 int * ecf, * rpq, *pncf; 00183 ecf = cf + cf[cfsz_]; 00184 rpq = cf + cfbg_; 00185 while ( *rpq != -1 && rpq != ecf ) rpq++; 00186 if ( rpq == cf + cfbg_ ) return ncf; 00187 *ncf = 4*(rpq-(cf+cfbg_))+cfhsz; 00188 rpq = cf + cfbg_; 00189 for ( pncf = ncf + cfbg_; pncf != ncf + *ncf; pncf += 4 , rpq ++ ) 00190 { 00191 int i = *rpq / m; 00192 int j = *rpq % m; 00193 int a = i*(4*m)+2*j; 00194 pncf[0] = a;//2**rpq; 00195 pncf[1] = a+1;//2**rpq+1; 00196 pncf[2] = a+2*m;//2*(*rpq+m); 00197 pncf[3] = a+2*m+1;//2*(*rpq+m)+1; 00198 }; 00199 // they are all the same 00200 for ( pncf = ncf + *ncf; pncf != ncf + 4**ncf; pncf += *ncf ) 00201 std::copy(ncf,ncf+*ncf,pncf); 00202 // with a change on the left quad ... 00203 int i = cf[cflq_]/ m; 00204 int j = cf[cflq_]% m; 00205 int a = i*(4*m)+2*j; 00206 (ncf+0**ncf)[cflq_] = a;//2*cf[1]; 00207 (ncf+1**ncf)[cflq_] = a+1;//2*cf[1]+1; 00208 (ncf+2**ncf)[cflq_] = a+2*m;//2*(cf[1]+m); 00209 (ncf+3**ncf)[cflq_] = a+2*m+1;//2*(cf[1]+m)+1; 00210 return ncf + 4**ncf; 00211 }; 00212 00213 static void cfforward( int * ncf, int * bcf, int * ecf, int m ) 00214 { 00215 for ( int * cf = bcf; cf != ecf; ncf = expandcf(cf,ncf,m), cf += *cf ); 00216 }; 00217 00218 00219 static void search( SSIQTS::aabb3 * lroot, SSIQTS::aabb3 * rroot, SSIQTS & ssi ) 00220 { 00221 int S, M; 00222 int * bcf, * ecf, * ncf; 00223 00224 // nxt,ext,lq,b0,b1... 00225 /* conflits de depart: (0, 0) */ 00226 bcf = new int[cfhsz+1]; 00227 bcf[cfsz_] = cfhsz+1; 00228 bcf[cflq_] = 0; 00229 bcf[cfbg_] = 0; 00230 ecf = bcf + bcf[cfsz_]; 00231 int s = 0; 00232 00233 SSIQTS::aabb3 *lbb = lroot; /* represente le niveau courant dans le quadtree "gauche" */ 00234 SSIQTS::aabb3 *rbb = rroot; /* represente le niveau courant dans le quadtree "droit" */ 00235 00236 /* pour toutes resolutions M = 1 .. m=2^p */ 00237 for ( S = 1, M = 1, lbb = lroot, rbb = rroot; M != ssi.m; M *= 2, S *= 4, lbb -= S, rbb -= S ) 00238 { 00239 /* traitement des collisions pour chaque conflit */ 00240 s = cfhunt( lbb, rbb, bcf, ecf ); 00241 /* si pas de collisions retour */ 00242 if ( !s ) { delete[] bcf; return; }; 00243 /* sinon allocation de l'espace necessaire */ 00244 ncf = new int[ s ]; 00245 /* definition des nouveaux conflits a tester */ 00246 // std::cout << "cfforward\n"; 00247 cfforward(ncf,bcf,ecf,M); 00248 /* suppression des anciens conflits */ 00249 delete[] bcf; 00250 bcf = ncf; 00251 ecf = ncf + s; 00252 }; 00253 00254 /* traitement du dernier niveau */ 00255 s = cfhunt(lbb,rbb,bcf,ecf); 00256 ecf = cfsimplify(bcf,ecf); 00257 ssi.m_bcf = bcf; 00258 ssi.m_ecf = ecf; 00259 }; 00260 00261 /* print a la gnuplot des conflits */ 00262 static void cfprint( std::ostream& gp, std::ostream& gpl , int * bcf, int * ecf, int m ) 00263 { 00264 for( int * cf = bcf; cf != ecf; cf += *cf ) 00265 { 00266 if ( cf[cfbg_] != -1 ) 00267 { 00268 gp << (cf[cflq_]/m) << " " << (cf[cflq_]%m) << std::endl; 00269 int * rpq = cf+cfbg_; 00270 while ( *rpq != -1 && rpq != cf+*cf ) 00271 { 00272 gpl << (*rpq/m) << " " << (*rpq%m) << std::endl; 00273 rpq++; 00274 }; 00275 } 00276 }; 00277 }; 00278 void SSIQTS::cfprint( std::ostream& gp, std::ostream& gpl ) 00279 { 00280 mmx::cfprint(gp, gpl, m_bcf, m_ecf, m ); 00281 }; 00282 00283 SSIQTS::SSIQTS( ParametricSurface * srfa, ParametricSurface * srfb, int n, int degu, int degv ) 00284 { 00285 udeg = degu; 00286 vdeg = degv; 00287 int p = 0; 00288 m = 1; 00289 while( n ) { p++; n/=2; m *= 2; }; 00290 smpa = new sample(srfa,m*degu+1,m*degv+1); 00291 smpb = new sample(srfb,m*degu+1,m*degv+1); 00292 int s; 00293 int deep; 00294 boxa = alloc(deep,m,s); 00295 // std::cout << deep << " " << s << std::endl; 00296 boxb = alloc(deep,m,s); 00297 // std::cout << deep << " " << s << std::endl; 00298 // switch u interpolant 00299 // switch v interpolant 00300 fillboxes( boxa, smpa->m_svals, *this); 00301 fillboxes( boxb, smpb->m_svals, *this); 00302 build(boxa,*this); 00303 build(boxb,*this); 00304 search(boxa+s-1,boxb+s-1,*this); 00305 // std::cout << "end search\n"; 00306 }; 00307 00308 SSIQTS::~SSIQTS() 00309 { 00310 if ( smpa ) delete smpa; 00311 if ( smpb ) delete smpb; 00312 if ( boxa ) delete[] boxa; 00313 if ( boxb ) delete[] boxb; 00314 }; 00315 00316 } //namespace mmx 00317 00318 #undef ParametricSurface