$search
00001 /* 00002 James R. Diebel 00003 Stanford University 00004 00005 Started: 24 August 2004 00006 Last revised: 27 Sugust 2004 00007 00008 mesh.cc - class implementation of Mesh class (mesh.hh) 00009 - I/O functions only 00010 00011 Depends on: 00012 - Mesh class (mesh.hh) 00013 */ 00014 00015 #include "bmtk/mesh.hh" 00016 #include <trimesh/trimesh.h> 00017 #include <iostream> 00018 #include <fstream> 00019 #include <stdlib.h> 00020 #include <stdio.h> 00021 #include <list> 00022 #include <vector> 00023 #include <IL/il.h> 00024 #include <IL/ilu.h> 00025 #include <IL/ilut.h> 00026 00027 using namespace std; 00028 using namespace trimesh; 00029 00030 namespace bmtk { 00031 00033 // Export Mesh to ply format // 00035 void Mesh::exportToPLY(char *plyfile) { 00036 if (po) { 00037 cout << endl 00038 << "/---------------------------------\\" << endl 00039 << "| Writing PLY Mesh to passed file |" << endl 00040 << "\\--------------------------------/" << endl << flush; 00041 } 00042 // create TriMesh to fill 00043 TriMesh tm(nv,nf); 00044 for (int i=0;i<nv;i++) { 00045 for (int j=0;j<3;j++) { 00046 tm.vertices[i][j] = v[i].x[j]; 00047 } 00048 } 00049 for (int i=0;i<nf;i++) { 00050 for (int j=0;j<3;j++) { 00051 tm.faces[i][j] = f[i].v[j]->i; 00052 } 00053 } 00054 00055 // write TriMesh from file 00056 tm.WritePly(plyfile); 00057 } 00058 00060 // Function to build a fully-connected mesh // 00061 // from passed plyfile // 00063 void Mesh::buildFromPLY(char* plyfile) { 00064 if (po) { 00065 cout << endl 00066 << "/-----------------------------------\\" << endl 00067 << "| Reading PLY Mesh from passed file |" << endl 00068 << "\\----------------------------------/" << endl << flush; 00069 } 00070 // read TriMesh from file 00071 TriMesh *tm; 00072 tm = TriMesh::ReadPly(plyfile); 00073 if (!tm) exit(1); 00074 tm->need_faces(); 00075 00076 // parse TriMesh into standard vertex and face lists 00077 float* v = new float[3*tm->numvertices]; 00078 int* f = new int[3*tm->numfaces]; 00079 for (int i=0;i<tm->numvertices;i++) { 00080 v[3*i] = tm->vertices[i][0]; 00081 v[3*i+1] = tm->vertices[i][1]; 00082 v[3*i+2] = tm->vertices[i][2]; 00083 } 00084 for (int i=0;i<tm->numfaces;i++) { 00085 f[3*i] = tm->faces[i][0]; 00086 f[3*i+1] = tm->faces[i][1]; 00087 f[3*i+2] = tm->faces[i][2]; 00088 } 00089 00090 // parse it into my new Mesh format 00091 buildFrom(v,tm->numvertices,f,tm->numfaces); 00092 00093 // de-allocate memory 00094 delete [] v; 00095 delete [] f; 00096 } 00097 00099 // Function to build a fully-connected mesh // 00100 // from passed plyfile // 00102 void Mesh::buildFromMAP(char* mapfile, char* intfile) { 00103 if (po) { 00104 cout << endl 00105 << "/-----------------------------------\\" << endl 00106 << "| Reading Disp Map from passed file |" << endl 00107 << "\\-----------------------------------/" << endl << flush; 00108 } 00109 00110 // Load image from file 00111 // Initialize DevIL (Developer's Image Library) 00112 ILuint ImgId; 00113 ilInit(); iluInit(); 00114 // Since we are only using one image at a time, initialize it now 00115 ilGenImages(1, &ImgId); 00116 // Bind this image name 00117 ilBindImage(ImgId); 00118 // Load the actual file from disk 00119 ILenum ilerr = ilLoadImage((const ILstring)mapfile); 00120 if (ilerr == IL_FALSE) { 00121 cerr << endl << "Error reading disp map, exiting..." << endl << flush; 00122 exit(1); 00123 } 00124 if (int(ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL)) != 1) { 00125 cerr << endl << "Error, image depth is not 1, exiting..." << endl << flush; 00126 exit(1); 00127 } 00128 // grab a pointer to the raw image data 00129 ILubyte* inData = ilGetData(); 00130 int nj = int(ilGetInteger(IL_IMAGE_WIDTH)); 00131 int ni = int(ilGetInteger(IL_IMAGE_HEIGHT)); 00132 int num_vertices = ni*nj; 00133 int num_faces_max = (ni-1)*(nj-1)*2; 00134 if (po==1) cout << nj << " x " << ni << " x 1" << "... " << endl << flush; 00135 00136 // Read camera intrinsics from file 00137 float fi,fj,s,pi,pj,dzMax,d0; 00138 ifstream fin(intfile); 00139 if (!fin) { 00140 cerr << endl << "Error reading intrinsics file, exiting..." << endl 00141 << flush; 00142 exit(1); 00143 } else { 00144 fin >> fi >> fj >> s >> pi >> pj >> dzMax >> d0; 00145 fin.close(); 00146 } 00147 Mat3x3 proj(fi,s,pi,0.0f,fj,pj,0.0f,0.0f,1.0f); 00148 Mat3x3 iproj = proj.inv(); 00149 00150 // generate vertex list 00151 float* vertices = new float[num_vertices*3]; 00152 for (int i=0,k=0;i<ni;i++) for (int j=0;j<nj;j++,k++) { 00153 // project point to given depth using intrinsics 00154 float z = 1/(float(inData[k])+d0); 00155 Vec3d w = Vec3d(float(i),float(j),1.0); 00156 Vec3d u = iproj*w; 00157 w = u*(z/u[2]); 00158 // add vertex to list 00159 for (int l=0;l<3;l++) vertices[3*k+l] = w[l]; 00160 } 00161 00162 // generate face list 00163 int* faces = new int[num_faces_max*3]; 00164 int num_faces = 0; 00165 for (int i=0,k=0;i<ni;i++) for (int j=0;j<nj;j++,k++) { 00166 if (i > 0 && j > 0) { 00167 // if pixel is black, don't include it 00168 if (inData[k] == 0 || inData[k-1] == 0 || 00169 inData[k-nj-1] == 0 || inData[k-nj] == 0) continue; 00170 00171 // check if dz is too great; if not, add face to list 00172 float z0 = 1/(float(inData[k])+d0); 00173 float z1 = 1/(float(inData[k-1])+d0); 00174 float z2 = 1/(float(inData[k-nj-1])+d0); 00175 float z3 = 1/(float(inData[k-nj])+d0); 00176 if (fabsf(z0-z1) < dzMax && 00177 fabsf(z0-z2) < dzMax && 00178 fabsf(z1-z2) < dzMax) { 00179 faces[3*num_faces] = k; 00180 faces[3*num_faces+1] = k-1; 00181 faces[3*num_faces+2] = k-nj-1; 00182 num_faces++; 00183 } 00184 if (fabsf(z0-z2) < dzMax && 00185 fabsf(z0-z3) < dzMax && 00186 fabsf(z2-z3) < dzMax) { 00187 faces[3*num_faces] = k; 00188 faces[3*num_faces+1] = k-nj-1; 00189 faces[3*num_faces+2] = k-nj; 00190 num_faces++; 00191 } 00192 } 00193 } 00194 00195 // parse it into my new Mesh format 00196 buildFrom(vertices,num_vertices,faces,num_faces); 00197 00198 // de-allocate memory 00199 delete [] vertices; 00200 delete [] faces; 00201 } 00202 00203 void Mesh::buildFromLST(char* listfile) { 00204 if (po) { 00205 cout << endl 00206 << "/-----------------------------------\\" << endl 00207 << "| Building SuperMesh from List File |" << endl 00208 << "\\----------------------------------/" << endl << flush; 00209 } 00210 ifstream fin(listfile); 00211 fin >> nd; 00212 00213 // Read first file and build topology 00214 char filename[200]; 00215 fin >> filename; 00216 buildFromPLY(filename); 00217 00218 // Allocate memory for all other data sets and fill first set 00219 for (int i=0;i<nv;i++) { 00220 v[i].xs = new Vec3d[nd]; 00221 v[i].xs[0] = v[i].x; 00222 } 00223 for (int i=0;i<nf;i++) { 00224 f[i].ns = new Vec3d[nd]; 00225 f[i].ns[0] = f[i].n; 00226 r[i].ns = new Vec3d[nd]; 00227 } 00228 00229 // And fill the data sets 00230 TriMesh *tm; 00231 for (int i=1;i<nd;i++) { 00232 fin >> filename; 00233 tm = TriMesh::ReadPly(filename); 00234 tm->need_faces(); 00235 tm->need_normals(); 00236 if (!tm) exit(1); 00237 for (int j=0;j<nv;j++) { 00238 v[j].xs[i][0] = tm->vertices[j][0]; 00239 v[j].xs[i][1] = tm->vertices[j][1]; 00240 v[j].xs[i][2] = tm->vertices[j][2]; 00241 } 00242 for (int j=0;j<nf;j++) { 00243 f[j].ns[i][0] = tm->facenormals[j][0]; 00244 f[j].ns[i][1] = tm->facenormals[j][1]; 00245 f[j].ns[i][2] = tm->facenormals[j][2]; 00246 } 00247 tm->~TriMesh(); 00248 } 00249 } 00250 00252 // Export Mesh to TMF format // 00254 void Mesh::exportToTMF(char *tmffile) { 00255 if (po) { 00256 cout << endl 00257 << "/---------------------------------\\" << endl 00258 << "| Writing TMF Mesh to passed file |" << endl 00259 << "\\--------------------------------/" << endl << flush; 00260 } 00261 00262 ofstream fout(tmffile); 00263 fout << "# Blah" << endl; 00264 fout << "# " << nv << " vertices" << endl << "# " << nf << " faces" << endl; 00265 for (int i=0;i<nv;i++) 00266 fout <<"v " << v[i].x[0] 00267 << " " << v[i].x[1] 00268 << " " << v[i].x[2] << endl; 00269 for (int i=0;i<nf;i++) 00270 fout << "f "<< f[i].v[0]->i+1 00271 << " " << f[i].v[1]->i+1 00272 << " " << f[i].v[2]->i+1 << endl; 00273 fout.close(); 00274 } 00275 00277 // Function to build a fully-connected mesh // 00278 // from passed TMF file // 00280 void Mesh::buildFromTMF(char* tmffile) { 00281 if (po) { 00282 cout << endl 00283 << "/-----------------------------------\\" << endl 00284 << "| Reading TMF Mesh from passed file |" << endl 00285 << "\\----------------------------------/" << endl << flush; 00286 } 00287 00288 ifstream fin(tmffile); 00289 fin >> nv >> nf; 00290 00291 // parse TriMesh into standard vertex and face lists 00292 float* v = new float[3*nv]; 00293 int* f = new int[3*nf]; 00294 float tempFloat; 00295 for (int i=0;i<nv;i++) { 00296 for (int j=0;j<3;j++) { 00297 fin >> tempFloat; 00298 v[3*i+j] = tempFloat; 00299 } 00300 } 00301 int tempInt; 00302 for (int i=0;i<nf;i++) { 00303 for (int j=0;j<3;j++) { 00304 fin >> tempInt; 00305 f[3*i+j] = tempInt; 00306 } 00307 } 00308 00309 // parse it into my new Mesh format 00310 buildFrom(v,nv,f,nf); 00311 00312 // de-allocate memory 00313 delete [] v; 00314 delete [] f; 00315 } 00316 00318 // Function to build a fully-connected mesh // 00319 // from passed GTS file // 00321 void Mesh::buildFromGTS(char* gtsfile) { 00322 if (po) { 00323 cout << endl 00324 << "/-----------------------------------\\" << endl 00325 << "| Reading GTS Mesh from passed file |" << endl 00326 << "\\----------------------------------/" << endl << flush; 00327 } 00328 00329 int tempInt; 00330 int face[6]; 00331 float tempFloat; 00332 char tempChar[100]; 00333 00334 ifstream fin(gtsfile); 00335 fin >> nv >> ne >> nf; 00336 fin >> tempChar >> tempChar >> tempChar >> tempChar; 00337 00338 // parse TriMesh into standard vertex and face lists 00339 float* v = new float[3*nv]; 00340 int* f = new int[3*nf]; 00341 int* e = new int[2*ne]; 00342 for (int i=0;i<nv;i++) { 00343 for (int j=0;j<3;j++) { 00344 fin >> tempFloat; 00345 v[3*i+j] = tempFloat; 00346 } 00347 if(strcmp(tempChar,"vertexoffset")==0) 00348 for (int j=0;j<3;j++) fin >> tempFloat; 00349 } 00350 for (int i=0;i<ne;i++) { 00351 for (int j=0;j<2;j++) { 00352 fin >> tempInt; 00353 e[2*i+j] = tempInt-1; 00354 } 00355 } 00356 for (int i=0;i<nf;i++) { 00357 for (int j=0;j<3;j++) { 00358 fin >> tempInt; 00359 face[2*j] = e[2*(tempInt-1)]; 00360 face[2*j+1] = e[2*(tempInt-1)+1]; 00361 } 00362 if (face[0] == face[2] || face[0] == face[3]) { 00363 tempInt = face[0]; face[0] = face[1]; face[1] = tempInt; 00364 } 00365 if (face[3] == face[1]) { 00366 tempInt = face[3]; face[3] = face[2]; face[2] = tempInt; 00367 } 00368 if (face[5] == face[3]) { 00369 tempInt = face[5]; face[5] = face[4]; face[4] = tempInt; 00370 } 00371 for (int j=0;j<3;j++) f[3*i+j] = face[2*j]; 00372 } 00373 00374 // parse it into my new Mesh format 00375 buildFrom(v,nv,f,nf); 00376 00377 // de-allocate memory 00378 delete [] v; 00379 delete [] f; 00380 } 00381 00383 // Function to build a fully-connected mesh // 00384 // from passed OFF file // 00386 void Mesh::buildFromOFF(char* offfile) { 00387 if (po) { 00388 cout << endl 00389 << "/-----------------------------------\\" << endl 00390 << "| Reading OFF Mesh from passed file |" << endl 00391 << "\\----------------------------------/" << endl << flush; 00392 } 00393 00394 char buf[100]; 00395 char dump[100]; 00396 int tempInt; 00397 ifstream fin(offfile); 00398 00399 for (int i=0;i<6;i++) fin >> buf; 00400 fin >> nv; 00401 for (int i=0;i<11;i++) fin >> buf; 00402 fin >> nf; 00403 for (int i=0;i<6;i++) fin >> buf; 00404 00405 00406 cout << nv << " " << nf << endl << flush; 00407 00408 // parse TriMesh into standard vertex and face lists 00409 float* v = new float[3*nv]; 00410 int* f = new int[3*nf]; 00411 float tempFloat; 00412 for (int i=0;i<nv;i++) { 00413 for (int j=0;j<3;j++) { 00414 fin >> tempFloat; 00415 v[3*i+j] = tempFloat; 00416 } 00417 } 00418 for (int i=0;i<nf;i++) { 00419 fin >> tempInt; 00420 for (int j=0;j<3;j++) { 00421 fin >> tempInt; 00422 f[3*i+j] = tempInt; 00423 } 00424 } 00425 00426 // parse it into my new Mesh format 00427 buildFrom(v,nv,f,nf); 00428 00429 // de-allocate memory 00430 delete [] v; 00431 delete [] f; 00432 } 00433 00435 // Function to export the current regions // 00436 // to passed file // 00438 void Mesh::exportRegions(char* regfile) { 00439 if (po) { 00440 cout << endl 00441 << "/---------------------\\" << endl 00442 << "| Writing Region File |" << endl 00443 << "\\--------------------/" << endl << flush; 00444 } 00445 00446 // find lists of faces in each region 00447 findRegionFaceLists(); 00448 00449 // open a file and write those lists to disk 00450 ofstream fout(regfile); 00451 fout << nr << endl; 00452 if (po) cout << "- Writing " << nr << " regions with " << nf 00453 << " faces to " << regfile << "." << flush << endl; 00454 for (int i=0;i<nr;i++) { 00455 fout << r[i].fi.size() << " "; 00456 for (int j=0;j<r[i].fi.size();j++) { 00457 fout << r[i].fi[j] << " "; 00458 } 00459 fout << endl; 00460 } 00461 fout.close(); 00462 if (po) cout << "Done writing regions." << flush << endl; 00463 } 00464 00466 // Function to export the current regions // 00467 // to passed file // 00469 void Mesh::importRegions(char* regfile) { 00470 if (po) { 00471 cout << endl 00472 << "/---------------------\\" << endl 00473 << "| Reading Region File |" << endl 00474 << "\\--------------------/" << endl << flush; 00475 } 00476 00477 // clear current region properties 00478 clearRegionProps(); 00479 00480 // open a file and write those lists to disk 00481 ifstream fin(regfile); 00482 int temp1,temp2; 00483 fin >> nr; 00484 if (po) cout << "- Reading " << nr << " regions with " << nf 00485 << " faces from " << regfile << "." << flush << endl; 00486 for (int i=0;i<nr;i++) { 00487 fin >> temp1; 00488 for (int j=0;j<temp1;j++) { 00489 fin >> temp2; 00490 r[i].fi.push_back(temp2); 00491 f[temp2].r = &(r[i]); 00492 } 00493 } 00494 fin.close(); 00495 00496 // recalculate region properties 00497 findRegionProps(); 00498 00499 // and compute the polygonal mesh 00500 findBoundaries(); 00501 triangulateContours(); 00502 findRegionSmoothNormalsOld(); 00503 00504 if (po) cout << "Done reading regions." << flush << endl; 00505 } 00506 00508 // Create covariance matrices aligned with the line-of-sight // 00509 // from the origin - used to apply reasonable uncertainties // 00510 // in cases where no such information has been recorded // 00512 void Mesh::applyLineOfSightCovar(float sr) { 00513 for (int i=0;i<nv;i++) { 00514 Vec3d e0 = v[i].x; e0[2] -= 100; 00515 e0.normalize(); 00516 Vec3d e1(1,0,0); e1 = e0.cross(e1); e1.normalize(); 00517 Vec3d e2 = e0.cross(e1); 00518 Vec3d lambda(sr,1,1); lambda.normalize(); 00519 v[i].iCov = (Mat3x3::eigenReconst(e0,e1,e2,lambda)).inv(); 00520 if (i==100) cout << v[i].iCov; 00521 } 00522 } 00523 00525 // Function to build a fully-connected mesh // 00526 // from lists of vertices and triangles // 00528 vector<int> Mesh::buildFrom(float* vertices, int numvertices, 00529 int* faces, int numfaces) { 00530 00531 // Tell the console that we have started 00532 if (po) 00533 cout << endl 00534 << "/------------------------------------------\\" << endl 00535 << "| Building Mesh from vertex and face lists |" << endl 00536 << "\\------------------------------------------/" << endl << flush; 00537 00538 // Fill vertex and face lists 00539 fillVertsAndFaces(vertices, numvertices, faces, numfaces); 00540 00541 // Find links between neighboring faces 00542 vector<int> badFaces; 00543 int nbad = findInterFaceLinks(); 00544 if (nbad) { 00545 if (po) cout << endl << nbad << " Bad triangles, removing " 00546 << "offending triangles and trying again..." 00547 << endl << flush; 00548 00549 // remove bad triangles 00550 for (int in=0,out=0;in<nf;in++) if (f[in].flag != -101) { 00551 if (in != out) for (int j=0;j<3;j++) { 00552 faces[out*3+j] = faces[in*3+j]; 00553 } 00554 out++; 00555 } else badFaces.push_back(in); 00556 00557 cout << "." << flush; 00558 00559 delete [] v; 00560 delete [] f; 00561 delete [] r; 00562 delete [] q; 00563 delete [] qv; 00564 nv = ne = nf = nr = nn = 0; 00565 numfaces -= nbad; 00566 00567 cout << "." << flush; 00568 00569 // Fill vertex and face lists 00570 fillVertsAndFaces(vertices, numvertices, faces, numfaces); 00571 00572 // Find links between neighboring faces 00573 nbad = findInterFaceLinks(); 00574 if (nbad) exit(1); 00575 } 00576 00578 // Allocate memory for edges // 00580 //ne = 3*nf-nn/2; 00581 ne = 3*nf; 00582 if (po) cout << "- Allocating memory for " << ne << " edges..." << flush; 00583 e = new Edge[ne]; 00584 if (po) cout << "Done." << endl << flush; 00585 00587 // Go back through faces to create edges // 00589 if (po) 00590 cout << "- Creating face-to-edge and edge-to-face mappings..." << endl 00591 << flush; 00592 list<int> nbrs; // list of possible neighboring faces 00593 list<int>::iterator i1,i2; // iterators to scan list for valid neighbors 00594 int ce=0; 00595 for (int i=0;i<nf;i++) { 00596 for (int j=0;j<3;j++) { 00597 // for each of the three edges per face: 00598 // assume edge is a new one and add it to the global list 00599 e[ce].i = ce; 00600 e[ce].m = this; 00601 e[ce].v[0] = f[i].v[j]; e[ce].v[1] = f[i].v[(j+1)%3]; 00602 if (e[ce].v[0] == e[ce].v[1]) { 00603 cerr << endl << "PROBLEM: triangle with repeated vertex" << endl 00604 << f[i] << "Exiting now." << endl << flush; 00605 exit(1); 00606 } 00607 // Find the faces that this edge separates 00608 nbrs.clear(); 00609 // add (faces attached to given edge) to a list 00610 for (int k=0;k<f[i].v[j]->nf;k++) { 00611 if (e[ce]<*(f[i].v[j]->f[k])) 00612 nbrs.push_back(f[i].v[j]->f[k]->i); 00613 } 00614 for (int k=0;k<f[i].v[(j+1)%3]->nf;k++) { 00615 if (e[ce]<*(f[i].v[(j+1)%3]->f[k])) 00616 nbrs.push_back(f[i].v[(j+1)%3]->f[k]->i); 00617 } 00618 // sort list and prune out duplicates 00619 nbrs.sort(); 00620 nbrs.unique(); 00621 00622 // check those faces if that edge already exists 00623 bool exists = false; 00624 for (i1 = nbrs.begin();i1!=nbrs.end();i1++) { 00625 for (int k=0;k<f[*i1].ne;k++) { 00626 exists = exists || (e[ce] == *f[*i1].e[k]); 00627 } 00628 } 00629 if (!exists) { // then finish building new edge 00630 // allocate memory for this edge's face list 00631 e[ce].nf = nbrs.size(); 00632 if (e[ce].nf > 2) { 00633 cerr << endl 00634 << "PROBLEM: found edge with at least three faces." << endl 00635 << "Mesh is not 2d manifold." << endl 00636 << "Ignoring." << endl 00637 << "Edge " << ce << " has " << e[ce].nf << " faces." << endl 00638 << flush; 00639 } 00640 int temp = e[ce].nf; 00641 e[ce].nf = 0; // reset for use as counter 00642 00643 for (i1 = nbrs.begin();i1!=nbrs.end();i1++) { 00644 // add edge to faces 00645 if (f[*i1].ne > 2) { 00646 cerr << endl << "PROBLEM: too many edges for this face " << endl 00647 << f[*i1] << e[ce] << *f[*i1].e[0] 00648 << *f[*i1].e[1] << *f[*i1].e[2] 00649 << "Ignoring..." << endl << flush; 00650 continue; 00651 } 00652 f[*i1].e[f[*i1].ne] = &e[ce]; 00653 f[*i1].ne++; 00654 // add faces to edge 00655 if (e[ce].nf > 1) break; 00656 e[ce].f[e[ce].nf] = &f[*i1]; 00657 e[ce].nf++; 00658 } 00659 00660 // increment counters of edges leaving each vertex 00661 e[ce].v[0]->ne++; e[ce].v[1]->ne++; 00662 00663 // and increment our current edge counter 00664 ce++; 00665 } 00666 } 00667 } 00668 ne = ce; 00669 if (po) cout << " " << ce << " edges added, Done." << endl << flush; 00670 00672 // Create vertex-to-edge and vertex-to-vertex mappings // 00674 if (po) cout << "- Creating vertex-to-edge and vertex-to-vertex mappings..." 00675 << flush; 00676 // Go back through vertices to create edge lists 00677 for (int i=0;i<nv;i++) { 00678 if (v[i].ne) { 00679 v[i].e = new Edge*[v[i].ne]; 00680 v[i].v = new Vert*[v[i].ne]; 00681 } 00682 v[i].ne = 0; // reset for use as counter 00683 } 00684 if (po) cout << "." << flush; 00685 // And go back through the edges to fill the vertex-to-edge mappings 00686 for (int i=0,iv0,iv1;i<ne;i++) { 00687 // create vertex-to-edge mappings 00688 iv0 = e[i].v[0]->i; iv1 = e[i].v[1]->i; 00689 v[iv0].e[v[iv0].ne] = &e[i]; 00690 v[iv1].e[v[iv1].ne] = &e[i]; 00691 if (e[i].nf == 1) v[iv0].bound = v[iv1].bound = true; 00692 // create vertex-to-vertex mappings 00693 v[iv0].v[v[iv0].ne] = &v[iv1]; 00694 v[iv1].v[v[iv1].ne] = &v[iv0]; 00695 // increment counters 00696 v[iv0].ne++; 00697 v[iv1].ne++; 00698 } 00699 // and go through and flag edge faces and vertices 00700 for (int i=0;i<nv;i++) { 00701 if (v[i].bound) for (int j=0;j<v[i].nf;j++) v[i].f[j]->bound = 1; 00702 } 00703 if (po) cout << "Done." << endl << flush; 00704 00705 // and find various other derived quantities 00706 findMeshProps(); 00707 00708 // and set original face normals 00709 for (int i=0;i<nf;i++) { 00710 f[i].n0 = f[i].n; 00711 } 00712 00713 if (po) cout << "Done building Mesh." << endl << endl << flush; 00714 00715 return badFaces; 00716 } 00717 00719 // Fill Mesh with passed vertices and faces // 00721 void Mesh::fillVertsAndFaces(float* vertices, int numvertices, 00722 int* faces, int numfaces) { 00724 // Allocate memory for vertices and faces // 00726 nv = numvertices; 00727 nr = nf = numfaces; 00728 if (po) cout << "- Allocating memory for " << nv << " vertices and " 00729 << nf << " faces..." << flush; 00730 v = new Vert[nv]; 00731 f = new Face[nf]; 00732 r = new Region[nf]; 00733 q = new int[nf]; 00734 qv = new int[nv]; 00735 if (po) cout << "Done." << endl << flush; 00736 00738 // Add faces from TriMesh to Mesh // 00740 if (po) cout << "- Adding faces to global face list..." << flush; 00741 for (int i=0;i<nf;i++) { 00742 // add self-reference, parent-mesh reference, region reference 00743 f[i].i = i; 00744 r[i].i = i; 00745 r[i].m = this; 00746 f[i].m = this; 00747 f[i].r = &r[i]; 00748 // add links to all three vertices of face 00749 for (int j=0;j<3;j++) { 00750 int in = faces[3*i+j]; 00751 if (in < 0 || in >= nv) { 00752 cerr << "Error! vertex index out of range in face " << i << " " << in; 00753 exit(1); 00754 } 00755 f[i].v[j] = &v[in]; 00756 v[in].nf++; 00757 } 00758 } 00759 if (po) cout << "Done." << endl << flush; 00760 00762 // Add vertices from TriMesh to Mesh // 00764 if (po) cout << "- Adding vertices to global vertex list..." << flush; 00765 for (int i=0;i<nv;i++) { 00766 // add vertex position, self-reference, parent-mesh reference, 00767 // default variance 00768 for (int j=0;j<3;j++) v[i].x0[j] = v[i].x[j] = vertices[3*i+j]; 00769 v[i].i = i; 00770 v[i].m = this; 00771 // allocate memory for adjacent face list 00772 if (v[i].nf) v[i].f = new Face*[v[i].nf]; 00773 // reset adjacent face counter for use as index in mappings (next) 00774 v[i].nf = 0; 00775 } 00776 if (po) cout << "Done." << endl << flush; 00777 00779 // Create links from vertices to faces by scanning all faces // 00781 if (po) cout << "- Creating vertex-to-face mappings..." << flush; 00782 for (int i=0;i<nf;i++) { 00783 for (int j=0;j<3;j++) { 00784 // add link from every vertex of every face to said face 00785 f[i].v[j]->f[f[i].v[j]->nf] = &f[i]; 00786 f[i].v[j]->nf++; 00787 } 00788 } 00789 if (po) cout << "Done." << endl << flush; 00790 } 00791 00792 00794 // Create links from faces to neighboring faces // 00796 int Mesh::findInterFaceLinks() { 00797 if (po) cout << "- Creating face-to-face mappings..." << flush; 00798 int nbad = 0; // number of bad triangles in case of failure 00799 list<int> nbrs; // list of possible neighboring faces 00800 list<int>::iterator i1,i2; // iterators to scan list for valid neighbors 00801 for (int i=0;i<nf;i++) { 00802 nbrs.clear(); 00803 for (int j=0;j<3;j++) { 00804 for (int k=0;k<f[i].v[j]->nf;k++) { 00805 // add every face of every vertex of every face to a list 00806 if ((((*f[i].v[0]<*f[i].v[j]->f[k])+(*f[i].v[1]<*f[i].v[j]->f[k])+ 00807 (*f[i].v[2]<*f[i].v[j]->f[k]))>=2) && (f[i].v[j]->f[k]->i != i)) 00808 nbrs.push_back(f[i].v[j]->f[k]->i); 00809 } 00810 } 00811 // sort list and prune out duplicates 00812 nbrs.sort(); 00813 nbrs.unique(); 00814 00815 // and stream the list into the array meant for it 00816 f[i].nf = nbrs.size(); 00817 if (f[i].nf > 3) { 00818 nbad++; 00819 f[i].flag = -101; 00820 f[i].nf = 3; 00821 } 00822 nn += f[i].nf; // keep track of total number of neighbors to compute ne 00823 i1=nbrs.begin(); 00824 for (int j=0;j<f[i].nf;j++,i1++) f[i].f[j] = &f[*i1]; 00825 } 00826 if (!nbad) if (po) cout << "Done." << endl << flush; 00827 return nbad; 00828 } 00829 00831 // Function to read options file from disk // 00833 int Mesh::readOptions(char *filename_) { 00834 if (po) cout << "- Loading MRF options..." << flush; 00835 ifstream fin(filename_); 00836 if (fin) { 00837 fin >> gs2; 00838 fin >> gsn2; 00839 fin >> segThresh; 00840 fin >> maxIter; 00841 } 00842 fin.close(); 00843 setVertVar(gs2); 00844 setNormalVar(gsn2); 00845 if (po) cout << "Done." << endl << flush; 00846 return 1; 00847 } 00848 00850 // Function to write options file to disk // 00852 int Mesh::writeOptions(char *filename_) { 00853 if (po) cout << "- Saving MRF options..." << flush; 00854 ofstream fout(filename_); 00855 if (fout) { 00856 fout << gs2 << endl; 00857 fout << gsn2 << endl; 00858 fout << segThresh << endl; 00859 fout << maxIter << endl; 00860 } 00861 fout.close(); 00862 if (po) cout << "Done." << endl << flush; 00863 return 1; 00864 } 00865 00866 00867 /******************************************** 00868 ******************************************** 00869 * Function to write Mesh to disk * 00870 ******************************************** 00871 ********************************************/ 00872 int Mesh::writeMesh(char *filename_) { 00873 // tell the console that we have started 00874 if (po) cout << endl 00875 << "/-------------------------------\\" << endl 00876 << "| Writing Mesh in native format |" << endl 00877 << "\\-------------------------------/" << endl << flush; 00878 00879 00881 // open file for writing // 00883 if (po) cout << "- Opening " << filename_ << " for writing..." << flush; 00884 FILE *file; 00885 if((file = fopen(filename_, "wb" )) == NULL) { 00886 cerr << "Failed to open file " << filename_ << endl; 00887 return 1; 00888 } 00889 if (po) cout << "Done." << endl << flush; 00890 00892 // write mesh to disk // 00894 if (po) cout << "- Writing Mesh data..." << flush; 00895 // write overall sizes to disk 00896 fwrite(&nv,sizeof(int),1,file); 00897 fwrite(&nf,sizeof(int),1,file); 00898 fwrite(&ne,sizeof(int),1,file); 00899 fwrite(&nd,sizeof(int),1,file); 00900 00901 // write vertices to disk 00902 if (po) cout << " vertices" << flush; 00903 for (int i=0;i<nv;i++) { 00904 // per-vertex properties 00905 fwrite(v[i].x0.x,sizeof(float[3]),1,file); 00906 fwrite(v[i].x.x,sizeof(float[3]),1,file); 00907 for (int j=0;j<nd;j++) fwrite(v[i].xs[j].x,sizeof(float[3]),1,file); 00908 fwrite(v[i].n.x,sizeof(float[3]),1,file); 00909 fwrite(v[i].c.x,sizeof(float[3]),1,file); 00910 fwrite(v[i].iCov.x,sizeof(float[9]),1,file); 00911 fwrite(&(v[i].bound),sizeof(bool),1,file); 00912 00913 // vertex-face connectivity 00914 fwrite(&(v[i].nf),sizeof(int),1,file); 00915 for (int j=0;j<v[i].nf;j++) { 00916 fwrite(&(v[i].f[j]->i),sizeof(int),1,file); 00917 } 00918 00919 // vertex-edge and vertex-vertex connectivty 00920 fwrite(&(v[i].ne),sizeof(int),1,file); 00921 for (int j=0;j<v[i].ne;j++) { 00922 fwrite(&(v[i].e[j]->i),sizeof(int),1,file); 00923 fwrite(&(v[i].v[j]->i),sizeof(int),1,file); 00924 } 00925 } 00926 00927 // write faces to disk 00928 if (po) cout << ", faces" << flush; 00929 for (int i=0;i<nf;i++) { 00930 // per-face properties 00931 fwrite(f[i].n0.x,sizeof(float[3]),1,file); 00932 fwrite(f[i].n.x,sizeof(float[3]),1,file); 00933 for (int j=0;j<nd;j++) fwrite(f[i].ns[j].x,sizeof(float[3]),1,file); 00934 fwrite(&(f[i].bound),sizeof(bool),1,file); 00935 // face-vertex and face-edge connectivity 00936 for (int j=0;j<3;j++) { 00937 fwrite(&(f[i].v[j]->i),sizeof(int),1,file); 00938 fwrite(&(f[i].e[j]->i),sizeof(int),1,file); 00939 } 00940 // face-face connectivity 00941 fwrite(&(f[i].nf),sizeof(int),1,file); 00942 for (int j=0;j<f[i].nf;j++) { 00943 fwrite(&(f[i].f[j]->i),sizeof(int),1,file); 00944 } 00945 } 00946 00947 // write edges to disk 00948 if (po) cout << ", edges" << flush; 00949 for (int i=0;i<ne;i++) { 00950 // edge-vertex connectivity 00951 for (int j=0;j<2;j++) { 00952 fwrite(&(e[i].v[j]->i),sizeof(int),1,file); 00953 } 00954 00955 // edge-face connectivity 00956 fwrite(&(e[i].nf),sizeof(int),1,file); 00957 for (int j=0;j<e[i].nf;j++) { 00958 fwrite(&(e[i].f[j]->i),sizeof(int),1,file); 00959 } 00960 } 00961 00962 if (po) cout << ", Done." << endl << flush; 00963 00965 // close file // 00967 if (po) cout << "- Closing " << filename_ << "..." << flush; 00968 if (fclose(file)) { 00969 cout << "Failed to close file " << filename_ << endl; 00970 return 1; 00971 } 00972 if (po) cout << "Done." << endl << flush; 00973 00974 // normal return 00975 if (po) cout << "Done saving Mesh." << endl << endl << flush; 00976 return 0; 00977 } 00978 00979 00980 00981 /******************************************** 00982 ******************************************** 00983 * Function to read Mesh from disk * 00984 ******************************************** 00985 ********************************************/ 00986 int Mesh::readMesh(char *filename_) { 00987 // tell the console that we have started 00988 if (po) cout << endl 00989 << "/-------------------------------\\" << endl 00990 << "| Reading Mesh in native format |" << endl 00991 << "\\-------------------------------/" << endl << flush; 00992 00994 // open file for reading // 00996 if (po) cout << "- Opening " << filename_ << " for reading..." << flush; 00997 filename = filename_; 00998 FILE *file; 00999 if((file = fopen(filename_, "rb" )) == NULL) { 01000 cerr << "Failed to open file " << filename_ << endl; 01001 return 1; 01002 } 01003 if (po) cout << "Done." << endl << flush; 01004 01006 // read mesh from disk // 01008 if (po) cout << "- Reading Mesh data..." << endl << flush; 01009 // read overall sizes from disk 01010 fread(&nv,sizeof(int),1,file); 01011 fread(&nf,sizeof(int),1,file); 01012 nr = nf; 01013 fread(&ne,sizeof(int),1,file); 01014 fread(&nd,sizeof(int),1,file); 01015 01016 // Allocate memory for vertex, face, edge lists 01017 if (po) cout << " - Allocating memory for " << endl 01018 << " " << nv << " vertices" << endl 01019 << " " << nf << " faces" << endl 01020 << " " << ne << " edges..." << flush; 01021 v = new Vert[nv]; 01022 f = new Face[nf]; 01023 e = new Edge[ne]; 01024 r = new Region[nf]; 01025 q = new int[nf]; 01026 qv = new int[nv]; 01027 if (po) cout << "Done." << endl << flush; 01028 01029 // read vertices from disk 01030 if (po) cout << " - Reading vertices..." << flush; 01031 for (int i=0;i<nv;i++) { 01032 // self-reference, parent-mesh reference 01033 v[i].i = i; 01034 v[i].m = this; 01035 // per-vertex properties 01036 fread(v[i].x0.x,sizeof(float[3]),1,file); 01037 fread(v[i].x.x,sizeof(float[3]),1,file); 01038 v[i].xs = new Vec3d[nd]; 01039 for (int j=0;j<nd;j++) fread(v[i].xs[j].x,sizeof(float[3]),1,file); 01040 fread(v[i].n.x,sizeof(float[3]),1,file); 01041 fread(v[i].c.x,sizeof(float[3]),1,file); 01042 fread(v[i].iCov.x,sizeof(float[9]),1,file); 01043 fread(&(v[i].bound),sizeof(bool),1,file); 01044 01045 // vertex-face connectivity 01046 fread(&(v[i].nf),sizeof(int),1,file); 01047 if (v[i].nf) v[i].f = new Face*[v[i].nf]; 01048 for (int j=0,k;j<v[i].nf;j++) { 01049 fread(&k,sizeof(int),1,file); 01050 v[i].f[j] = &f[k]; 01051 } 01052 01053 // vertex-edge and vertex-vertex connectivity 01054 fread(&(v[i].ne),sizeof(int),1,file); 01055 if (v[i].ne) { 01056 v[i].e = new Edge*[v[i].ne]; 01057 v[i].v = new Vert*[v[i].ne]; 01058 } 01059 for (int j=0,k;j<v[i].ne;j++) { 01060 fread(&k,sizeof(int),1,file); 01061 v[i].e[j] = &e[k]; 01062 fread(&k,sizeof(int),1,file); 01063 v[i].v[j] = &v[k]; 01064 } 01065 } 01066 if (po) cout << "Done." << endl << flush; 01067 01068 // read faces from disk 01069 if (po) cout << " - Reading faces..." << flush; 01070 for (int i=0;i<nf;i++) { 01071 // self-reference, parent-mesh reference, region reference 01072 f[i].i = i; 01073 r[i].i = i; 01074 f[i].m = this; 01075 f[i].r = &r[i]; 01076 // per-face properties 01077 fread(f[i].n0.x,sizeof(float[3]),1,file); 01078 fread(f[i].n.x,sizeof(float[3]),1,file); 01079 f[i].ns = new Vec3d[nd]; 01080 r[i].ns = new Vec3d[nd]; 01081 for (int j=0;j<nd;j++) fread(f[i].ns[j].x,sizeof(float[3]),1,file); 01082 fread(&(f[i].bound),sizeof(bool),1,file); 01083 // face-vertex and face-edge connectivity 01084 f[i].ne = 3; 01085 for (int j=0,k;j<3;j++) { 01086 fread(&k,sizeof(int),1,file); 01087 f[i].v[j] = &v[k]; 01088 fread(&k,sizeof(int),1,file); 01089 f[i].e[j] = &e[k]; 01090 } 01091 01092 // face-face connectivity 01093 fread(&(f[i].nf),sizeof(int),1,file); 01094 for (int j=0,k;j<f[i].nf;j++) { 01095 fread(&k,sizeof(int),1,file); 01096 f[i].f[j] = &f[k]; 01097 } 01098 } 01099 if (po) cout << "Done." << endl << flush; 01100 01101 // read edges from disk 01102 if (po) cout << " - Reading edges..." << flush; 01103 for (int i=0;i<ne;i++) { 01104 // self-reference, parent-mesh reference 01105 e[i].i = i; 01106 e[i].m = this; 01107 // edge-vertex connectivity 01108 for (int j=0,k;j<2;j++) { 01109 fread(&k,sizeof(int),1,file); 01110 e[i].v[j] = &v[k]; 01111 } 01112 01113 // edge-face connectivity 01114 fread(&(e[i].nf),sizeof(int),1,file); 01115 for (int j=0,k;j<e[i].nf;j++) { 01116 fread(&k,sizeof(int),1,file); 01117 e[i].f[j] = &f[k]; 01118 } 01119 } 01120 if (po) cout << "Done." << endl << flush; 01121 if (po) cout << " Done." << endl << flush; 01122 01124 // close file // 01126 if (po) cout << "- Closing " << filename_ << "..." << flush; 01127 if (fclose(file)) { 01128 cout << "Failed to close file " << filename_ << endl; 01129 return 1; 01130 } 01131 if (po) cout << "Done." << endl << flush; 01132 01133 // normal return 01134 if (po) cout << "Done reading Mesh." << endl << flush; 01135 return 0; 01136 01137 } 01138 01139 } // namespace bmtk