#include #include // stuff to define the mesh #include #include #include #include // io //#include //#include // update #include #include #include #include #include "border.h" class MyEdge; class MyFace; class MyVertex:public vcg::VertexAFVMVNf{public: ScalarType w; vcg::math::Quadric >q; ScalarType & W(){return w;} } ; class MyFace : public vcg::FaceAV{}; class MyMesh: public vcg::tri::TriMesh< std::vector, std::vector >{}; class MyTriEdgeCollapse: public vcg::tri::TriEdgeCollapseQuadric< MyMesh, MyTriEdgeCollapse >{ public: typedef vcg::tri::TriEdgeCollapseQuadric TECQ; typedef TECQ::PosType PosType; MyTriEdgeCollapse(PosType p, int i):TECQ(p,i){} ~MyTriEdgeCollapse(){} }; using namespace vcg; using namespace tri; using namespace nxs; using namespace std; void Cluster(MyMesh &mesh, unsigned int target_faces); float Decimate(unsigned int target_faces, vector &newvert, vector &newface, vector &newbord, vector &vert_remap) { MyMesh mesh; //build mesh for(unsigned int i = 0; i < newvert.size(); i++) { MyVertex vertex; vertex.ClearFlags(); vertex.P() = newvert[i]; mesh.vert.push_back(vertex); } mesh.vn = mesh.vert.size(); for(unsigned int i = 0; i < newface.size(); i+=3) { MyFace face; face.ClearFlags(); for(int k = 0; k < 3; k++) { assert(newface[i+k] < mesh.vn); face.V(k) = &mesh.vert[newface[i+k]]; } mesh.face.push_back(face); } mesh.fn = mesh.face.size(); //emark borders for(unsigned int i = 0; i < newbord.size(); i++) mesh.vert[newbord[i].start_vert].ClearW(); // int FinalSize = mesh.face.size()/2; // if(FinalSize > target_faces) FinalSize = target_faces; int FinalSize = target_faces; int t0=clock(); printf("mesh loaded %d %d \n",mesh.vn,mesh.fn); printf("reducing it to %i\n",FinalSize); vcg::tri::UpdateTopology::VertexFace(mesh); // cerr << "topology ok" << endl; int t1=clock(); //micro random semplificatore /* for(unsigned int i = 0; i < mesh.face.size(); i+= 2) { MyFace &face = mesh.face[i]; if(face.V(0)->IsW() && face.V(1)->IsW() && face.V(1)->IsW()) mesh.face[i].SetD(); } for(unsigned int i = 0; i < mesh.vert.size(); i++) { if(mesh.vert[i].IsW()) mesh.vert[i].SetD(); } for(unsigned int i = 0; i < mesh.face.size(); i++) { MyFace &face = mesh.face[i]; if(face.IsD()) continue; face.V(0)->ClearD(); face.V(1)->ClearD(); face.V(2)->ClearD(); }*/ // Cluster(mesh, target_faces); // cerr << "simplified" << endl; vcg::LocalOptimization DeciSession(mesh); MyTriEdgeCollapse::SetDefaultParams(); DeciSession.Init(); int t2=clock(); // printf("Initial Heap Size %i\n",DeciSession.h.size()); FinalSize = mesh.fn - FinalSize; //number of faces to remove FinalSize/=2; //Number of vertices to remove DeciSession.SetTargetOperations(FinalSize); DeciSession.DoOptimization(); float error = 1; //get error; int t3=clock(); /* printf(" vol %d \n lkv %d \n lke %d \n lkf %d \n ood %d\n bor %d\n ", MyTriEdgeCollapse::FailStat::Volume() , MyTriEdgeCollapse::FailStat::LinkConditionFace(), MyTriEdgeCollapse::FailStat::LinkConditionEdge(), MyTriEdgeCollapse::FailStat::LinkConditionVert(), MyTriEdgeCollapse::FailStat::OutOfDate() , MyTriEdgeCollapse::FailStat::Border() );*/ // printf("Completed in %i+%i+%i msec\n",t1-t0,t2-t1,t3-t2); // printf("mesh %d %d \n",mesh.vn,mesh.fn); //recort vert start. newvert.clear(); newface.clear(); unsigned int totvert = 0; vert_remap.resize(mesh.vert.size(), -1); for(unsigned int i = 0; i < mesh.vert.size(); i++) { if(mesh.vert[i].IsD()) continue; newvert.push_back(mesh.vert[i].cP()); vert_remap[i] = totvert++; } MyMesh::VertexPointer vert_start = &mesh.vert[0]; for(unsigned int i = 0; i < mesh.face.size(); i++) { MyFace &face = mesh.face[i]; if(face.IsD()) continue; for(int k = 0; k < 3; k++) { assert(vert_remap[face.V(k) - vert_start] != -1); newface.push_back(vert_remap[face.V(k) - vert_start]); } } for(unsigned int i = 0; i < newbord.size(); i++) { unsigned short &v = newbord[i].start_vert; assert(vert_remap[v] != -1); v = vert_remap[v]; } return error; } void Cluster(MyMesh &mesh, unsigned int target_faces) { unsigned int starting = mesh.vn; cerr << "starting face: " << mesh.fn << endl; //veramente brutale vector remap; remap.resize(mesh.vert.size()); for(int i = 0; i < mesh.vert.size(); i++) remap[i] = -1; int toremove = mesh.fn - target_faces; cerr << "counting" << endl; map > dist; for(int i = 0; i < mesh.vert.size(); i++) { if(mesh.vert[i].IsD()) continue; if(!mesh.vert[i].IsW()) continue; for(int k = i+1; k < mesh.vert.size(); k++) { if(mesh.vert[k].IsD()) continue; if(!mesh.vert[k].IsW()) continue; float d = (mesh.vert[i].P() - mesh.vert[k].P()).SquaredNorm(); dist[d] = make_pair(i, k); } } cerr << "done" << endl; map >::iterator s; for(s = dist.begin(); s != dist.end(); s++) { if(toremove < 0) break; int target = (*s).second.first; int source = (*s).second.second; if(remap[target] != -1) continue; if(remap[source] != -1) continue; assert(!mesh.vert[target].IsD()); assert(!mesh.vert[source].IsD()); mesh.vert[source].SetD(); remap[source] = target; remap[target] = target; toremove -= 2; mesh.vn--; // if(mesh.vn < starting/2) break; } //PULIAMO LE FACCE for(int i = 0; i < mesh.face.size(); i++) { MyFace &face = mesh.face[i]; if(face.IsD()) continue; for(int k = 0; k < 3; k++) { if(face.V(k)->IsD()) { face.V(k) = &mesh.vert[remap[face.V(k) - &mesh.vert[0]]]; } assert(!face.V(k)->IsD()); } if(face.V(0) == face.V(1) || face.V(0) == face.V(2) || face.V(1) == face.V(2)) { face.SetD(); mesh.fn--; } } cerr << "Ending faces: " << mesh.fn << endl; }