bool TMMesh::Save(const char *fileName) { std::ofstream fout(fileName); std::cout << "Saving " << fileName << std::endl; if (SaveVRML2(fout)) { fout.close(); return true; } return false; }
bool Mesh::SaveVRML2(const std::string & fileName) const { std::ofstream fout(fileName.c_str()); if (fout.is_open()) { const Material material; if (SaveVRML2(fout, material)) { fout.close(); return true; } return false; } return false; }
bool SaveVRML2(const std::string & fileName, const std::vector< HACD::Vec3<HACD::Real> > & points, const std::vector< HACD::Vec3<long> > & triangles, const HACD::Vec3<HACD::Real> * colors) { std::cout << "Saving " << fileName << std::endl; std::ofstream fout(fileName.c_str()); if (fout.is_open()) { const HACD::Material material; if (SaveVRML2(fout, points, triangles, material, colors)) { fout.close(); return true; } return false; } return false; }
bool TMMesh::SaveVRML2(std::ofstream &fout) { return SaveVRML2(fout, Material()); }
int main(int argc, char * argv[]) { if (argc != 9) { std::cout << "Usage: ./testHACD fileName.off minNClusters maxConcavity invertInputFaces addExtraDistPoints addFacesPoints ConnectedComponentsDist targetNTrianglesDecimatedMesh"<< std::endl; std::cout << "Recommended parameters: ./testHACD fileName.off 2 100 0 1 1 30 2000"<< std::endl; return -1; } const std::string fileName(argv[1]); size_t nClusters = atoi(argv[2]); double concavity = atof(argv[3]); bool invert = (atoi(argv[4]) == 0)?false:true; bool addExtraDistPoints = (atoi(argv[5]) == 0)?false:true; bool addFacesPoints = (atoi(argv[6]) == 0)?false:true; double ccConnectDist = atof(argv[7]); size_t targetNTrianglesDecimatedMesh = atoi(argv[8]); /* const std::string fileName("/Users/khaledmammou/Dev/HACD/data/Sketched-Brunnen.off"); size_t nClusters = 1; double concavity = 100.0; bool invert = false; bool addExtraDistPoints = true; bool addNeighboursDistPoints = false; bool addFacesPoints = true; double ccConnectDist = 30.0; size_t targetNTrianglesDecimatedMesh = 1000; */ std::string folder; int found = fileName.find_last_of(PATH_SEP); if (found != -1) { folder = fileName.substr(0,found); } if (folder == "") { folder = "."; } std::string file(fileName.substr(found+1)); std::string outWRLFileName = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + ".wrl"; std::string outOFFFileName = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + ".off"; std::string outOFFFileNameDecimated = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + "_decimated.off"; std::vector< HACD::Vec3<HACD::Real> > points; std::vector< HACD::Vec3<long> > triangles; LoadOFF(fileName, points, triangles, invert); SaveVRML2(outWRLFileName.c_str(), points, triangles); SaveOFF(outOFFFileName.c_str(), points, triangles); std::cout << "invert " << invert << std::endl; HACD::HeapManager * heapManager = HACD::createHeapManager(65536*(1000)); HACD::HACD * const myHACD = HACD::CreateHACD(heapManager); myHACD->SetPoints(&points[0]); myHACD->SetNPoints(points.size()); myHACD->SetTriangles(&triangles[0]); myHACD->SetNTriangles(triangles.size()); myHACD->SetCompacityWeight(0.0001); myHACD->SetVolumeWeight(0.0); myHACD->SetConnectDist(ccConnectDist); // if two connected components are seperated by distance < ccConnectDist // then create a virtual edge between them so the can be merged during // the simplification process myHACD->SetNClusters(nClusters); // minimum number of clusters myHACD->SetNVerticesPerCH(100); // max of 100 vertices per convex-hull myHACD->SetConcavity(concavity); // maximum concavity myHACD->SetSmallClusterThreshold(0.25); // threshold to detect small clusters myHACD->SetNTargetTrianglesDecimatedMesh(targetNTrianglesDecimatedMesh); // # triangles in the decimated mesh myHACD->SetCallBack(&CallBack); myHACD->SetAddExtraDistPoints(addExtraDistPoints); myHACD->SetAddFacesPoints(addFacesPoints); clock_t start, end; double elapsed; start = clock(); { myHACD->Compute(); } end = clock(); elapsed = static_cast<double>(end - start) / CLOCKS_PER_SEC; std::cout << "Time " << elapsed << " s"<< std::endl; nClusters = myHACD->GetNClusters(); bool printfInfo = false; if (printfInfo) { std::cout << "Output" << std::endl; for(size_t c = 0; c < nClusters; ++c) { std::cout << std::endl << "Convex-Hull " << c << std::endl; size_t nPoints = myHACD->GetNPointsCH(c); size_t nTriangles = myHACD->GetNTrianglesCH(c); HACD::Vec3<HACD::Real> * pointsCH = new HACD::Vec3<HACD::Real>[nPoints]; HACD::Vec3<long> * trianglesCH = new HACD::Vec3<long>[nTriangles]; myHACD->GetCH(c, pointsCH, trianglesCH); std::cout << "Points " << nPoints << std::endl; for(size_t v = 0; v < nPoints; ++v) { std::cout << v << "\t" << pointsCH[v].X() << "\t" << pointsCH[v].Y() << "\t" << pointsCH[v].Z() << std::endl; } std::cout << "Triangles " << nTriangles << std::endl; for(size_t f = 0; f < nTriangles; ++f) { std::cout << f << "\t" << trianglesCH[f].X() << "\t" << trianglesCH[f].Y() << "\t" << trianglesCH[f].Z() << std::endl; } delete [] pointsCH; delete [] trianglesCH; } } std::string outFileName = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + "_hacd.wrl"; myHACD->Save(outFileName.c_str(), false); const HACD::Vec3<HACD::Real> * const decimatedPoints = myHACD->GetDecimatedPoints(); const HACD::Vec3<long> * const decimatedTriangles = myHACD->GetDecimatedTriangles(); if (decimatedPoints && decimatedTriangles) { SaveOFF(outOFFFileNameDecimated, myHACD->GetNDecimatedPoints(), myHACD->GetNDecimatedTriangles(), decimatedPoints, decimatedTriangles); } bool exportSepFiles = false; if (exportSepFiles) { char outFileName[1024]; for(size_t c = 0; c < nClusters; c++) { sprintf(outFileName, "%s%s%s_hacd_%lu.wrl", folder.c_str(), PATH_SEP, file.substr(0, file.find_last_of(".")).c_str(), static_cast<unsigned long>(c)); myHACD->Save(outFileName, false, c); } } /* // to do: fix this in the case the simplification is on std::string outFileNamePartition = folder + PATH_SEP + file.substr(0, file.find_last_of(".")) + "_partition.wrl"; const long * const partition = myHACD->GetPartition(); SavePartition(outFileNamePartition, points, triangles, partition, nClusters); */ HACD::DestroyHACD(myHACD); HACD::releaseHeapManager(heapManager); return 0; }
bool SavePartition(const std::string & fileName, const std::vector< HACD::Vec3<HACD::Real> > & points, const std::vector< HACD::Vec3<long> > & triangles, const long * partition, const size_t nClusters) { if (!partition) { return false; } std::cout << "Saving " << fileName << std::endl; std::ofstream fout(fileName.c_str()); if (fout.is_open()) { HACD::Material mat; std::vector< HACD::Vec3<long> > triCluster; std::vector< HACD::Vec3<HACD::Real> > ptsCluster; std::vector< long > ptsMap; for(size_t c = 0; c < nClusters; c++) { ptsMap.resize(points.size()); mat.m_diffuseColor.X() = mat.m_diffuseColor.Y() = mat.m_diffuseColor.Z() = 0.0; while (mat.m_diffuseColor.X() == mat.m_diffuseColor.Y() || mat.m_diffuseColor.Z() == mat.m_diffuseColor.Y() || mat.m_diffuseColor.Z() == mat.m_diffuseColor.X() ) { mat.m_diffuseColor.X() = (rand()%100) / 100.0; mat.m_diffuseColor.Y() = (rand()%100) / 100.0; mat.m_diffuseColor.Z() = (rand()%100) / 100.0; } long ver[3]; long vCount = 1; for(size_t t = 0; t < triangles.size(); t++) { if (partition[t] == static_cast<long>(c)) { ver[0] = triangles[t].X(); ver[1] = triangles[t].Y(); ver[2] = triangles[t].Z(); for(int k = 0; k < 3; k++) { if (ptsMap[ver[k]] == 0) { ptsCluster.push_back(points[ver[k]]); ptsMap[ver[k]] = vCount; ver[k] = vCount-1; vCount++; } else { ver[k] = ptsMap[ver[k]]-1; } } triCluster.push_back(HACD::Vec3<long>(ver[0], ver[1], ver[2])); } } SaveVRML2(fout, ptsCluster, triCluster, mat); triCluster.clear(); ptsCluster.clear(); ptsMap.clear(); } fout.close(); return true; } return false; }