From 8f17d6b9bd641665238f715e197d1a070012f984 Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 6 Jun 2011 00:11:18 +0000 Subject: [PATCH] Mini sample with texture aware edge collapse based quadric simplification --- apps/texdeci/texdeci.cpp | 230 +++++++++++++++++++++++++++++++++++++++ apps/texdeci/texdeci.pro | 16 +++ 2 files changed, 246 insertions(+) create mode 100644 apps/texdeci/texdeci.cpp create mode 100644 apps/texdeci/texdeci.pro diff --git a/apps/texdeci/texdeci.cpp b/apps/texdeci/texdeci.cpp new file mode 100644 index 00000000..9d8d80bc --- /dev/null +++ b/apps/texdeci/texdeci.cpp @@ -0,0 +1,230 @@ +#include +#include + +#include +#include + +// stuff to define the mesh +#include +#include +#include +#include + +#include +#include + +// io +#include +#include + +// update +#include +#include +#include + +// local optimization +#include +#include +#include + +using namespace vcg; +using namespace tri; + +// The class prototypes. +class MyVertex; +class MyEdge; +class MyFace; + +struct MyUsedTypes: public UsedTypes::AsVertexType, Use::AsEdgeType, Use::AsFaceType>{}; + +class MyVertex : public Vertex< MyUsedTypes, + vertex::VFAdj, + vertex::Coord3f, + vertex::Normal3f, + vertex::Mark, + vertex::BitFlags >{ + }; + +class MyEdge : public Edge< MyUsedTypes> {}; + +typedef BasicVertexPair VertexPair; + +class MyFace : public Face< MyUsedTypes, + face::VFAdj, + face::VertexRef, + face::BitFlags, + face::WedgeTexCoord2f> {}; + +// the main mesh class +class MyMesh : public vcg::tri::TriMesh, std::vector > {}; + +class MyTriEdgeCollapseQTex: public TriEdgeCollapseQuadricTex< MyMesh, VertexPair, MyTriEdgeCollapseQTex, QuadricTexHelper > { + public: + typedef TriEdgeCollapseQuadricTex< MyMesh, VertexPair, MyTriEdgeCollapseQTex, QuadricTexHelper > TECQ; + inline MyTriEdgeCollapseQTex( const VertexPair &p, int i,BaseParameterClass *pp) :TECQ(p,i,pp){} +}; + + +void TexDecimation(MyMesh &m, bool CleaningFlag,int TargetFaceNum) +{ + tri::TriEdgeCollapseQuadricTexParameter pp; + + pp.SetDefaultParams(); + if(CleaningFlag){ + int dup = tri::Clean::RemoveDuplicateVertex(m); + int unref = tri::Clean::RemoveUnreferencedVertex(m); + printf("Removed %i duplicate and %i unreferenced vertices from mesh \n",dup,unref); + } + + printf("reducing it to %i\n",TargetFaceNum); + int t1=clock(); + + tri::UpdateBounding::Box(m); + math::Quadric QZero; + QZero.SetZero(); + QuadricTexHelper::QuadricTemp TD3(m.vert,QZero); + QuadricTexHelper::TDp3()=&TD3; + + std::vector,Quadric5 > > qv; + + QuadricTexHelper::Quadric5Temp TD(m.vert,qv); + QuadricTexHelper::TDp()=&TD; + + + vcg::LocalOptimization DeciSession(m, &pp); +// cb(1,"Initializing simplification"); + DeciSession.Init(); + + DeciSession.SetTargetSimplices(TargetFaceNum); + DeciSession.SetTimeBudget(0.1f); + // int startFn=m.fn; + + int faceToDel=m.fn-TargetFaceNum; + int t2=clock(); + + while( DeciSession.DoOptimization() && m.fn>TargetFaceNum ) + { + printf("Simplifing heap size %i ops %i\n",int(DeciSession.h.size()),DeciSession.nPerfmormedOps); + }; + + DeciSession.Finalize(); + + int t3=clock(); + printf("mesh %d %d Error %g \n",m.vn,m.fn,DeciSession.currMetric); + printf("\nCompleted in (%i+%i) msec\n",t2-t1,t3-t2); +} + +// mesh to simplify + +int main(int argc, char**argv){ + + int meshNum=argc-1; + +//std::vector meshVec(meshNum); + +MyMesh meshVec[10]; +int tt0=clock(); +char buf[255]; +int i; + +for(i=0;i::Open(meshVec[i],argv[i+1]); + if(err) + { + printf("Unable to open mesh %s : '%s'\n",argv[i+1], vcg::tri::io::Importer::ErrorMsg(err)); + exit(-1); + } + printf("mesh loaded %d %d \n",meshVec[i].vn,meshVec[i].fn); + + int t1=clock(); + tri::Smooth::VertexCoordLaplacian(meshVec[i],5*i); + + TexDecimation(meshVec[i],true,meshVec[i].fn/2); + int t2=clock(); + printf("%i %5.3f sec\n",i,float(t2-t1)/CLOCKS_PER_SEC); + sprintf(buf,"out%i.ply",i); + tri::io::ExporterPLY::Save(meshVec[i],buf,false); +} + +int tt1=clock(); +printf("---Total %5.3f sec\n",float(tt1-tt0)/CLOCKS_PER_SEC); + +for(int i=0;i::Save(meshVec[i],buf,false); +} + +// TriEdgeCollapseQuadricParameter qparams; +// qparams.QualityThr =.3; +// float TargetError=std::numeric_limits::max(); +// bool CleaningFlag =false; +// // parse command line. +// for(int i=4; i < argc;) +// { +// if(argv[i][0]=='-') +// switch(argv[i][1]) +// { +// case 'H' : qparams.SafeHeapUpdate=true; printf("Using Safe heap option\n"); break; +// case 'Q' : if(argv[i][2]=='y') { qparams.QualityCheck = true; printf("Using Quality Checking\n"); } +// else { qparams.QualityCheck = false; printf("NOT Using Quality Checking\n"); } break; +// case 'N' : if(argv[i][2]=='y') { qparams.NormalCheck = true; printf("Using Normal Deviation Checking\n"); } +// else { qparams.NormalCheck = false; printf("NOT Using Normal Deviation Checking\n"); } break; +// case 'O' : if(argv[i][2]=='y') { qparams.OptimalPlacement = true; printf("Using OptimalPlacement\n"); } +// else { qparams.OptimalPlacement = false; printf("NOT Using OptimalPlacement\n"); } break; +// case 'S' : if(argv[i][2]=='y') { qparams.ScaleIndependent = true; printf("Using ScaleIndependent\n"); } +// else { qparams.ScaleIndependent = false; printf("NOT Using ScaleIndependent\n"); } break; +// case 'B' : if(argv[i][2]=='y') { qparams.PreserveBoundary = true; printf("Preserving Boundary\n"); } +// else { qparams.PreserveBoundary = false; printf("NOT Preserving Boundary\n"); } break; +// case 'T' : if(argv[i][2]=='y') { qparams.PreserveTopology = true; printf("Preserving Topology\n"); } +// else { qparams.PreserveTopology = false; printf("NOT Preserving Topology\n"); } break; +// case 'q' : qparams.QualityThr = atof(argv[i]+2); printf("Setting Quality Thr to %f\n",atof(argv[i]+2)); break; +// case 'n' : qparams.NormalThrRad = math::ToRad(atof(argv[i]+2)); printf("Setting Normal Thr to %f deg\n",atof(argv[i]+2)); break; +// case 'b' : qparams.BoundaryWeight = atof(argv[i]+2); printf("Setting Boundary Weight to %f\n",atof(argv[i]+2)); break; +// case 'e' : TargetError = float(atof(argv[i]+2)); printf("Setting TargetError to %g\n",atof(argv[i]+2)); break; +// case 'P' : CleaningFlag=true; printf("Cleaning mesh before simplification\n"); break; + +// default : printf("Unknown option '%s'\n", argv[i]); +// exit(0); +// } +// i++; +// } + + + +// if(CleaningFlag){ +// int dup = tri::Clean::RemoveDuplicateVertex(mesh); +// int unref = tri::Clean::RemoveUnreferencedVertex(mesh); +// printf("Removed %i duplicate and %i unreferenced vertices from mesh \n",dup,unref); +// } + + +// printf("reducing it to %i\n",FinalSize); + +// vcg::tri::UpdateBounding::Box(mesh); + +// // decimator initialization +// vcg::LocalOptimization DeciSession(mesh,&qparams); + +// int t1=clock(); +// DeciSession.Init(); +// int t2=clock(); +// printf("Initial Heap Size %i\n",int(DeciSession.h.size())); + +// DeciSession.SetTargetSimplices(FinalSize); +// DeciSession.SetTimeBudget(0.5f); +// if(TargetError< std::numeric_limits::max() ) DeciSession.SetTargetMetric(TargetError); + +// while(DeciSession.DoOptimization() && mesh.fn>FinalSize && DeciSession.currMetric < TargetError) +// printf("Current Mesh size %7i heap sz %9i err %9g \r",mesh.fn, int(DeciSession.h.size()),DeciSession.currMetric); + +// int t3=clock(); +// printf("mesh %d %d Error %g \n",mesh.vn,mesh.fn,DeciSession.currMetric); +// printf("\nCompleted in (%i+%i) msec\n",t2-t1,t3-t2); + +// vcg::tri::io::ExporterPLY::Save(mesh,argv[2]); + return 0; + +} diff --git a/apps/texdeci/texdeci.pro b/apps/texdeci/texdeci.pro new file mode 100644 index 00000000..cc6f9724 --- /dev/null +++ b/apps/texdeci/texdeci.pro @@ -0,0 +1,16 @@ +#DEFINES += VCG_USE_EIGEN +TARGET = texdeci +#LIBPATH += +DEPENDPATH += . +INCLUDEPATH += . ../.. +CONFIG += console stl debug_and_release +TEMPLATE = app +HEADERS += +SOURCES += texdeci.cpp ../../wrap/ply/plylib.cpp + +QT-=gui + + +# Mac specific Config required to avoid to make application bundles +CONFIG -= app_bundle +