$search
00001 /* 00002 James R. Diebel 00003 Stanford University 00004 00005 Started: 24 August 2004 00006 Last revised: 00007 00008 mesh_vert.cc - class implementation of Mesh class (mesh.hh) 00009 00010 Depends on: 00011 - Mesh class (mesh.hh) 00012 */ 00013 00014 #include "bmtk/triangulate.h" 00015 #include "bmtk/mesh.hh" 00016 #include <iostream> 00017 #include <list> 00018 #include <vector> 00019 #include <cstring> 00020 00021 namespace bmtk { 00022 00024 // Region Functions // 00026 void Mesh::findRegionFaceLists() { 00027 for (int i=0;i<nf;i++) f[i].r->fi.push_back(f[i].i); 00028 } 00029 00030 void Mesh::findRegionProps() { 00031 renumberRegions(); 00032 clearRegionProps(); 00033 findRegionNormals(); 00034 findRegionVariances(); 00035 } 00036 00037 void Mesh::clearRegionProps() { 00038 for (int i=0;i<nr;i++) { 00039 r[i].p = 0; 00040 r[i].ssn2 = 0; 00041 r[i].vi.clear(); 00042 r[i].tvi.clear(); 00043 r[i].ni.clear(); 00044 r[i].fi.clear(); 00045 r[i].n = 0; 00046 if (nd) for (int k=0;k<nd;k++) r[i].ns[k] = 0; 00047 if (nd) r[i].n = r[i].ns[0]; 00048 } 00049 } 00050 00051 void Mesh::findRegionNormals() { 00052 for (int i=0;i<nf;i++) { 00053 f[i].r->p++; 00054 f[i].r->n += f[i].n; 00055 if (nd) for (int k=0;k<nd;k++) f[i].r->ns[k] += f[i].ns[k]; 00056 } 00057 for (int i=0;i<nr;i++) { 00058 r[i].n.normalize(); 00059 if (nd) for (int k=0;k<nd;k++) r[i].ns[k].normalize(); 00060 } 00061 } 00062 00063 void Mesh::findRegionVariances() { 00064 for (int i=0;i<nf;i++) { 00065 if (nd) for (int k=0;k<nd;k++) 00066 f[i].r->ssn2 += f[i].ns[k].dist2To(f[i].r->ns[k]); 00067 else f[i].r->ssn2 += f[i].n.dist2To(f[i].r->n); 00068 } 00069 } 00070 00071 void Mesh::renumberRegions() { 00072 bool temp = po; 00073 po = false; 00074 resetFaceFlags(); 00075 nr = 0; 00076 for (int i=0;i<nf;i++) if (f[i].flag == -1) { 00077 Region* ri = f[i].r; 00078 q[0] = i; 00079 for (int in=1,out=0;in>out;out++) { 00080 if (f[q[out]].flag == -1 && f[q[out]].r == ri) { 00081 f[q[out]].flag = nr; 00082 for (int j=0;j<f[q[out]].nf;j++,in++) { 00083 q[in] = f[q[out]].f[j]->i; 00084 } 00085 } 00086 } 00087 nr++; 00088 } 00089 for (int i=0;i<nf;i++) f[i].r = &r[f[i].flag]; 00090 po = temp; 00091 } 00092 00093 void Mesh::findRegionSmoothNormals() { 00094 if (po) cout << "- Performing linear regression on region normals..." 00095 << flush << endl; 00096 00097 // create lists of all the boundary faces in a given region 00098 for (int i=0;i<nf;i++) if (f[i].flag != -1) 00099 f[i].r->fi.push_back(f[i].i); 00100 00101 // allocate memory 00102 float** aa = new float *[9]; 00103 for (int i=0;i<9;i++) aa[i] = new float[9]; 00104 float* xx = new float[9]; 00105 float* bb = new float[9]; 00106 00107 // fill optimization matrix 00108 for (int i=0;i<nr;i++) { 00109 // clear out working memory 00110 for (int j=0;j<9;j++) memset(aa[j],0,9*sizeof(float)); 00111 memset(bb,0,9*sizeof(float)); 00112 memset(xx,0,9*sizeof(float)); 00113 00114 // construct basis 00115 Vec3d e1 = v[r[i].vi[1]].x - v[r[i].vi[0]].x; 00116 e1 -= e1.dot(r[i].n)*r[i].n; 00117 e1.normalize(); 00118 Vec3d e2 = e1.cross(r[i].n); 00119 e2.normalize(); 00120 00121 // fill problem matrix-vector system 00122 for (int k=0;k<3;k++) aa[k*3][k*3] = 3*r[i].fi.size(); 00123 for (int j=0;j<r[i].fi.size();j++) for (int t=0;t<3;t++) { 00124 // project the current vertex onto basis 00125 Vec3d x2D = Vec3d(f[r[i].fi[j]].v[t]->x.dot(e1), 00126 f[r[i].fi[j]].v[t]->x.dot(e2),0.0f); 00127 for (int k=0;k<3;k++) { 00128 bb[3*k] += f[r[i].fi[j]].n[k]; 00129 for (int l=0;l<2;l++) { 00130 aa[3*k+1+l][3*k] += x2D[l]; 00131 aa[3*k][3*k+1+l] += x2D[l]; 00132 for (int s=0;s<2;s++) aa[3*k+1+s][3*k+1+l] += x2D[l]*x2D[s]; 00133 bb[3*k+1+l] += f[r[i].fi[j]].n[k]*x2D[l]; 00134 } 00135 } 00136 } 00137 00138 // compute linear regression 00139 gelimd2(aa,bb,xx,9); 00140 00141 // grab parameters 00142 Vec3d n0(xx[0],xx[3],xx[6]); 00143 Mat3x3 A(xx[1],xx[2],0.0f,xx[4],xx[5],0.0f,xx[7],xx[8],0.0f); 00144 00145 // define vertex normals according to fit 00146 for (int j=0;j<r[i].tvi.size();j++) { 00147 Vec3d x2D = Vec3d(v[r[i].tvi[j]].x.dot(e1), 00148 v[r[i].tvi[j]].x.dot(e2),0.0f); 00149 r[i].ni.push_back(n0 + A*x2D); 00150 r[i].ni.back().normalize(); 00151 } 00152 00153 // print some things 00154 /*cout << endl; 00155 for (int j=0;j<9;j++) { 00156 for (int k=0;k<9;k++) { 00157 printf("%8.1f",aa[j][k]); 00158 } 00159 printf(" | %8.1f | %8.1f\n",xx[j],bb[j]); 00160 } 00161 cout << endl << "region " << i << ": " << r[i].n << endl; 00162 cout << n0 << endl << A << endl; 00163 cout << (n0 + A*(f[r[i].fi[0]].x)) << endl;*/ 00164 } 00165 00166 // clean up 00167 for (int i=0;i<9;i++) delete [] aa[i]; 00168 delete [] xx; 00169 delete [] bb; 00170 00171 if (po) cout << " Done." << flush << endl; 00172 } 00173 00174 void Mesh::findRegionSmoothNormalsOld() { 00175 // create lists of all the boundary faces in a given region 00176 for (int i=0;i<nf;i++) if (f[i].flag != -1) f[i].r->fi.push_back(f[i].i); 00177 00178 // allocate memory 00179 float** aa = new float *[12]; 00180 for (int i=0;i<12;i++) aa[i] = new float[12]; 00181 float* xx = new float[12]; 00182 float* bb = new float[12]; 00183 00184 // fill optimization matrix 00185 for (int i=0;i<nr;i++) { 00186 // clear out working memory 00187 for (int j=0;j<12;j++) memset(aa[j],0,12*sizeof(float)); 00188 memset(bb,0,12*sizeof(float)); 00189 memset(xx,0,12*sizeof(float)); 00190 00191 // fill problem matrix-vector system 00192 for (int k=0;k<3;k++) aa[k*4][k*4] = r[i].p; 00193 for (int j=0;j<r[i].fi.size();j++) for (int t=0;t<3;t++) { 00194 for (int k=0;k<3;k++) { 00195 bb[4*k] += f[r[i].fi[j]].n[k]; 00196 for (int l=0;l<3;l++) { 00197 aa[4*k+1+l][4*k] += f[r[i].fi[j]].v[t]->x[l]; 00198 aa[4*k][4*k+1+l] += f[r[i].fi[j]].v[t]->x[l]; 00199 for (int s=0;s<3;s++) { 00200 aa[4*k+1+s][4*k+1+l] += (f[r[i].fi[j]].v[t]->x[l]* 00201 f[r[i].fi[j]].v[t]->x[s]); 00202 } 00203 bb[4*k+1+l] += f[r[i].fi[j]].n[k]*f[r[i].fi[j]].v[t]->x[l]; 00204 } 00205 } 00206 } 00207 00208 // compute linear regression 00209 gelimd2(aa,bb,xx,12); 00210 00211 // grab parameters 00212 Vec3d n0(xx[0],xx[4],xx[8]); 00213 Mat3x3 A(xx[1],xx[2],xx[3],xx[5],xx[6],xx[7],xx[9],xx[10],xx[11]); 00214 00215 // define vertex normals according to fit 00216 for (int j=0;j<r[i].tvi.size();j++) { 00217 r[i].ni.push_back(n0 + A*(v[r[i].tvi[j]].x)); 00218 r[i].ni.back().normalize(); 00219 } 00220 00221 // print some things 00222 /*cout << endl; 00223 for (int j=0;j<12;j++) { 00224 for (int k=0;k<12;k++) { 00225 printf("%8.1f",aa[j][k]); 00226 } 00227 printf(" | %8.1f | %8.1f\n",xx[j],bb[j]); 00228 } 00229 cout << endl << "region " << i << ": " << r[i].n << endl; 00230 cout << n0 << endl << A << endl; 00231 cout << (n0 + A*(f[r[i].fi[0]].x)) << endl;*/ 00232 } 00233 00234 // clean up 00235 for (int i=0;i<12;i++) delete [] aa[i]; 00236 delete [] xx; 00237 delete [] bb; 00238 } 00239 00240 void Mesh::doSegmentationStep() { 00241 for (int i=0;i<nf;i++) { 00242 for (int j=0;j<f[i].nf;j++) if (f[i].r != f[i].f[j]->r) { 00243 float cssn2 = 0; 00244 int pop = nd*(f[i].r->p + f[i].f[j]->r->p); 00245 Vec3d mn; 00246 if (nd) for (int k=0;k<nd;k++) { 00247 mn = (f[i].r->ns[k]*f[i].r->p 00248 + f[i].f[j]->r->ns[k]*f[i].f[j]->r->p); 00249 mn.normalize(); 00250 cssn2 += f[i].r->ssn2 + f[i].r->p*mn.dist2To(f[i].r->ns[k]) + 00251 f[i].f[j]->r->ssn2 + f[i].f[j]->r->p*mn.dist2To(f[i].f[j]->r->ns[k]); 00252 } else { 00253 mn = (f[i].r->n*f[i].r->p + f[i].f[j]->r->n*f[i].f[j]->r->p); 00254 mn.normalize(); 00255 cssn2 = f[i].r->ssn2 + f[i].r->p*mn.dist2To(f[i].r->n) + 00256 f[i].f[j]->r->ssn2 + f[i].f[j]->r->p*mn.dist2To(f[i].f[j]->r->n); 00257 pop = f[i].r->p + f[i].f[j]->r->p; 00258 } 00259 if (cssn2/float(pop) < segThresh*float(nd+1)) { 00260 if (f[i].r->p > f[i].f[j]->r->p) { 00261 mergeRegions(*(f[i].f[j]->r),*(f[i].r),*(f[i].f[j])); 00262 if (nd) for (int k=0;k<nd;k++) { 00263 f[i].r->ns[k] = (f[i].r->ns[k]*f[i].r->p 00264 + f[i].f[j]->r->ns[k]*f[i].f[j]->r->p); 00265 f[i].r->ns[k].normalize();; 00266 } else f[i].r->n = mn; 00267 f[i].r->ssn2 = cssn2; 00268 } else { 00269 mergeRegions(*(f[i].r),*(f[i].f[j]->r),f[i]); 00270 if (nd) for (int k=0;k<nd;k++) { 00271 f[i].f[j]->r->ns[k] = (f[i].r->ns[k]*f[i].r->p 00272 + f[i].f[j]->r->ns[k]*f[i].f[j]->r->p); 00273 f[i].f[j]->r->ns[k].normalize(); 00274 } else f[i].f[j]->r->n = mn; 00275 f[i].f[j]->r->ssn2 = cssn2; 00276 } 00277 continue; 00278 } 00279 00280 float diff = 0; 00281 if (nd) for (int k=0;k<nd;k++) 00282 diff += f[i].ns[k].dot(f[i].f[j]->r->ns[k]) - 00283 f[i].ns[k].dot(f[i].r->ns[k]); 00284 else diff = f[i].n.dot(f[i].f[j]->r->n) - f[i].n.dot(f[i].r->n); 00285 if (diff > 0) { 00286 swapFace(f[i],*(f[i].r),*(f[i].f[j]->r)); 00287 break; 00288 } 00289 } 00290 } 00291 findRegionProps(); 00292 } 00293 00294 // performs segementation 00295 void Mesh::runSegmentation() { 00296 if (po) cout << endl << "Performing mesh segmentation..." << flush << endl; 00297 for (int i=0;i<maxIter;i++) { 00298 cout << "- iteration " << i << " of " << maxIter << ": from " 00299 << nr << " to " << flush; 00300 doSegmentationStep(); 00301 cout << nr << " regions." << flush << endl; 00302 update(); 00303 } 00304 00305 if (po) cout << "Done with Segmentation." << flush << endl; 00306 findVertNormals(); 00307 findBoundaries(); 00308 triangulateContours(); 00309 findRegionSmoothNormalsOld(); 00310 } 00311 00312 // swaps Face fi from Region ri to Region rj 00313 void Mesh::swapFace(Face& fi, Region& ri, Region& rj) { 00314 if (!nd) { 00315 ri.ssn2 -= fi.n.dist2To(ri.n); 00316 ri.n *= ri.p; 00317 ri.n -= fi.n; 00318 ri.n.normalize(); 00319 00320 rj.n *= rj.p; 00321 rj.n += fi.n; 00322 rj.n.normalize(); 00323 rj.ssn2 += fi.n.dist2To(rj.n); 00324 } 00325 00326 ri.p--; 00327 rj.p++; 00328 fi.r = &rj; 00329 } 00330 00331 // merge Region ri into Region rj starting at Face fi 00332 void Mesh::mergeRegions(Region& ri, Region& rj, Face& fi) { 00333 rj.p += ri.p; 00334 ri.p = 0; 00335 q[0] = fi.i; 00336 for (int in=1,out=0;in>out;out++) if (f[q[out]].r == &ri) { 00337 f[q[out]].r = &rj; 00338 for (int j=0;j<f[q[out]].nf;j++,in++) q[in] = f[q[out]].f[j]->i; 00339 } 00340 nr--; 00341 } 00342 00343 // find boundaries between regions, keypoints 00344 void Mesh::findBoundaries() { 00345 // merge single-triangle floaters with surrounding region 00346 for (int i=0;i<nf;i++) if (f[i].r->p == 1) { 00347 bool floater = false; 00348 if (f[i].nf > 1) { 00349 floater = true; 00350 for (int j=1;j<f[i].nf;j++) { 00351 floater = floater && (f[i].f[j]->r == f[i].f[j-1]->r); 00352 } 00353 } 00354 if (floater) mergeRegions(*(f[i].r),*(f[i].f[0]->r),f[i]); 00355 } 00356 00357 // recalculate region properties 00358 findRegionProps(); 00359 00360 // Mark all keypoints with current regions 00361 markKeypoints(); 00362 00363 // scan through all faces, looking for edges to trace 00364 for (int i=0;i<nf;i++) if (f[i].flag != -1) { 00365 for (int j=0;j<3;j++) { 00366 // if the edge is a region boundary and has not been visited yet 00367 if ((f[i].e[j]->flag != -1) && (f[i].e[j]->flag != f[i].r->i) && 00368 f[i].r->vi.size() == 0){ 00369 traceBoundary(f[i].e[j]->v[0],f[i].e[j],&f[i],f[i].r); 00370 } 00371 } 00372 } 00373 } 00374 00375 void Mesh::markKeypoints() { 00376 resetEdgeFlags(); 00377 resetVertFlags(); 00378 resetFaceFlags(); 00379 00380 // flag edges, faces as boundaries, vertices as keypoints 00381 for (int i=0;i<ne;i++) { 00382 switch (e[i].nf) { 00383 case 1: 00384 e[i].flag = -2; 00385 e[i].f[0]->flag = -2; 00386 e[i].v[1]->flag-=2; 00387 e[i].v[0]->flag-=2; 00388 break; 00389 case 2: 00390 if (e[i].f[0]->r != e[i].f[1]->r) { 00391 e[i].flag = -3; 00392 e[i].f[0]->flag = e[i].f[1]->flag = -3; 00393 e[i].v[0]->flag-=1; 00394 e[i].v[1]->flag-=1; 00395 } 00396 break; 00397 } 00398 } 00399 } 00400 00401 void Mesh::traceBoundary(Vert* vc, Edge* ec, Face* fc, Region* rc) { 00402 list<int> trace; 00403 list<int>::iterator it; 00404 bool done,found; 00405 00406 do { 00407 // add the current contour 00408 trace.push_back(vc->i); 00409 00410 // move current vertex along current edge to next vertex 00411 if (vc == ec->v[0]) vc = ec->v[1]; else vc = ec->v[0]; 00412 ec->flag = rc->i; 00413 00414 // if new vertex has been visited before, delete everything between first 00415 // and second visits to ensure simply connected region 00416 if (vc->marker == rc->i) while (trace.back() != vc->i) trace.pop_back(); 00417 00418 // mark new vertex as visited (note that we leave the first vertex 00419 // unmarked because we wish to return to it without causing a problem 00420 vc->marker = rc->i; 00421 00422 // look for next edge by traversing neighboring faces 00423 do { 00424 // assume that we have nowhere else to go 00425 done = true; 00426 found = false; 00427 00428 // check for valid edge in current face 00429 for (int i=0;i<3;i++) { 00430 //cout << "." << flush; 00431 if (fc->e[i]->flag != -1 && 00432 fc->e[i]->flag != rc->i && 00433 *vc < *(fc->e[i])) { 00434 ec = fc->e[i]; 00435 found = true; done = false; 00436 break; 00437 } 00438 } 00439 if (found) break; 00440 00441 // otherwise try a neighboring face that also touches current vertex 00442 // and is part of the current region 00443 fc->flag = vc->i; 00444 for (int i=0;i<fc->nf;i++) { 00445 if (fc->f[i]->flag != vc->i && 00446 fc->f[i]->r == rc && 00447 *vc < *(fc->f[i])) { 00448 fc = fc->f[i]; 00449 done = false; 00450 break; 00451 } 00452 } 00453 } while (!done); 00454 } while (!done); 00455 00456 // traverse trace, filling the region contour with keypoints only 00457 trace.unique(); 00458 for (it = trace.begin();it!=trace.end();it++) if (v[*it].flag < -3) 00459 rc->vi.push_back(*it); 00460 00461 // terminate the chain with a flag 00462 rc->vi.push_back(-1); 00463 00464 // print the contour 00465 /*cout << "Region " << rc->i << ": " << flush; 00466 for (int i=0;i<rc->vi.size();i++) 00467 cout << rc->vi[i] << " "; 00468 cout << endl << flush;*/ 00469 } 00470 00471 // generates decimated mesh after call to findBoundaries() 00472 void Mesh::triangulateContours() { 00473 if (po) cout << "Triangulating region contours..." << endl << flush; 00474 00475 // some STL lists used by the triangulation routines 00476 Vector2dVector contour; 00477 VertexList mappings,triangles; 00478 00479 // for each (polygon <-> region), perform tessellation 00480 for (int i=0;i<nr;i++) { 00481 if (r[i].vi.size() < 4) continue; 00482 00483 // construct local 2D basis 00484 Vec3d e1 = v[r[i].vi[1]].x - v[r[i].vi[0]].x; 00485 e1 -= e1.dot(r[i].n)*r[i].n; 00486 e1.normalize(); 00487 Vec3d e2 = e1.cross(r[i].n); 00488 00489 // grab contours and tessellate 00490 contour.clear(); 00491 mappings.clear(); 00492 for (int j=0;j<r[i].vi.size();j++) { 00493 if (r[i].vi[j] != -1) { 00494 float x1 = v[r[i].vi[j]].x.dot(e1); 00495 float x2 = v[r[i].vi[j]].x.dot(e2); 00496 contour.push_back(Vector2d(x1,x2)); 00497 mappings.push_back(r[i].vi[j]); 00498 } 00499 else { 00500 if (mappings.size() < 3) { 00501 contour.clear(); 00502 mappings.clear(); 00503 break; 00504 } 00505 // and triangulate that contour, storing results in triangles 00506 Triangulate::Process(contour,triangles); 00507 00508 // finally, remap the recent additions to our triangles list to respect 00509 // the global definitions of the vertices 00510 r[i].tvi.clear(); 00511 for (int k=0;k<triangles.size();k++) { 00512 r[i].tvi.push_back(mappings[triangles[k]]); 00513 } 00514 contour.clear(); 00515 mappings.clear(); 00516 triangles.clear(); 00517 } 00518 } 00519 } 00520 00521 if (po) cout << "Done triangulating contour." << endl << flush; 00522 } 00523 00524 // generates decimated mesh after call to findBoundaries() 00525 Mesh* Mesh::genDecimatedMesh() { 00526 if (po) cout << "Generating decimated mesh..." << endl << flush; 00527 // count vertices in decimated mesh and create links 00528 int numvertices = 0; 00529 for (int i=0;i<nv;i++) if (v[i].flag < -3) { 00530 v[i].flag = numvertices; 00531 numvertices++; 00532 } else v[i].flag = -1; 00533 00534 // create new vertex list and fill it from source mesh 00535 float* vertices = new float[3*numvertices]; 00536 for (int i=0;i<nv;i++) if (v[i].flag >= 0) { 00537 for (int j=0;j<3;j++) { 00538 vertices[3*v[i].flag+j] = v[i].x[j]; 00539 } 00540 } 00541 00542 // some STL lists used by the triangulation routines 00543 Vector2dVector contour; 00544 VertexList mappings,triangles,polygons; 00545 00546 // for each (polygon <-> region), perform tessellation 00547 for (int i=0;i<nr;i++) { 00548 if (r[i].vi.size() < 4) continue; 00549 00550 // construct local 2D basis 00551 Vec3d e1 = v[r[i].vi[1]].x - v[r[i].vi[0]].x; 00552 e1 -= e1.dot(r[i].n)*r[i].n; 00553 e1.normalize(); 00554 Vec3d e2 = e1.cross(r[i].n); 00555 00556 // grab contours and tessellate 00557 contour.clear(); 00558 mappings.clear(); 00559 for (int j=0;j<r[i].vi.size();j++) { 00560 if (r[i].vi[j] != -1) { 00561 float x1 = v[r[i].vi[j]].x.dot(e1); 00562 float x2 = v[r[i].vi[j]].x.dot(e2); 00563 contour.push_back(Vector2d(x1,x2)); 00564 mappings.push_back(v[r[i].vi[j]].flag); 00565 } 00566 else { 00567 if (mappings.size() < 3) { 00568 contour.clear(); 00569 mappings.clear(); 00570 break; 00571 } 00572 // and triangulate that contour, storing results in triangles 00573 int n = triangles.size(); 00574 Triangulate::Process(contour,triangles); 00575 00576 // finally, remap the recent additions to our triangles list to respect 00577 // the global definitions of the vertices 00578 for (int k=n;k<triangles.size();k++) { 00579 triangles[k] = mappings[triangles[k]]; 00580 polygons.push_back(i); 00581 } 00582 contour.clear(); 00583 mappings.clear(); 00584 } 00585 } 00586 } 00587 00588 // create and fill up triangle list 00589 int numfaces = triangles.size()/3; 00590 int* faces = new int[3*numfaces]; 00591 for (int i=0;i<numfaces;i++) { 00592 faces[3*i] = triangles[3*i+1]; 00593 faces[3*i+1] = triangles[3*i]; 00594 faces[3*i+2] = triangles[3*i+2]; 00595 } 00596 00597 // Build new mesh 00598 Mesh* dm = new Mesh(); 00599 vector<int> badFaces = dm->buildFrom(vertices,numvertices,faces,numfaces); 00600 00601 // Allocate space for other datasets, if needed 00602 if (nd) { 00603 dm->nd = nd; 00604 for (int i=0;i<dm->nv;i++) dm->v[i].xs = new Vec3d[nd]; 00605 for (int i=0;i<dm->nf;i++) { 00606 dm->f[i].ns = new Vec3d[nd]; 00607 dm->r[i].ns = new Vec3d[nd]; 00608 } 00609 } 00610 00611 // Go through the source vertices and fill new mesh 00612 if (nd) for (int i=0;i<nv;i++) if (v[i].flag >= 0) { 00613 for (int k=0;k<nd;k++) dm->v[v[i].flag].xs[k] = v[i].xs[k]; 00614 } 00615 00616 // Fix the normal vectors to be the same as that of the parent region 00617 // and add in data from other data sets if available 00618 if (badFaces.size() == 0) { 00619 for (int i=0;i<dm->nf;i++) { 00620 dm->f[i].n = r[polygons[i*3]].n; 00621 if (nd) for (int ii=0;ii<nd;ii++) 00622 dm->f[i].ns[ii] = r[polygons[i*3]].ns[ii]; 00623 } 00624 } else { 00625 for (int i=0,j=0,k=0;i<numfaces;i++) { 00626 if (j<badFaces.size()) if (i==badFaces[j]) { 00627 j++; continue; 00628 } 00629 dm->f[k].n = r[polygons[i*3]].n; 00630 if (nd) for (int ii=0;ii<nd;ii++) { 00631 dm->f[k].ns[ii] = r[polygons[i*3]].ns[ii]; 00632 } 00633 k++; 00634 } 00635 } 00636 00637 // Clean up and get out of here! 00638 delete [] vertices; 00639 delete [] faces; 00640 00641 if (po) cout << "Done building decimated mesh." << endl << flush; 00642 00643 return dm; 00644 } 00645 00646 } // namespace bmtk