From d59c8cdc49ea4f36b137902e1c9d34204f8f9f60 Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 25 Sep 2006 09:41:41 +0000 Subject: [PATCH] Added new version of pasodoble smoothing --- apps/sample/trimesh_smooth/trimesh_smooth.cpp | 41 ++++- vcg/complex/trimesh/smooth.h | 173 +++++++++++++++--- 2 files changed, 179 insertions(+), 35 deletions(-) diff --git a/apps/sample/trimesh_smooth/trimesh_smooth.cpp b/apps/sample/trimesh_smooth/trimesh_smooth.cpp index 7077ee37..9f6f389a 100644 --- a/apps/sample/trimesh_smooth/trimesh_smooth.cpp +++ b/apps/sample/trimesh_smooth/trimesh_smooth.cpp @@ -1,8 +1,13 @@ #include -#include -#include +#include +#include +#include + #include + +#include +#include // to clean up a mesh #include #include @@ -13,19 +18,29 @@ using namespace vcg; +using namespace std; + +class MyEdge; // dummy prototype never used class MyFace; -class MyEdge; -class MyVertex:public Vertex{}; -class MyFace :public FaceFN{}; -class MyMesh: public tri::TriMesh< std::vector, std::vector >{}; +class MyVertex; +class MyVertex : public VertexSimp2< MyVertex, MyEdge, MyFace, vert::VFAdj, vert::Coord3f, vert::Normal3f, vert::BitFlags >{}; +class MyFace : public FaceSimp2 < MyVertex, MyEdge, MyFace, face::VFAdj, face::Normal3f, face::VertexRef, face::BitFlags > {}; +class MyMesh : public vcg::tri::TriMesh, vector > {}; + +//class MyFace; +//class MyEdge; +//class MyVertex:public Vertex{}; +//class MyFace :public FaceFN{}; +//class MyMesh: public tri::TriMesh< std::vector, std::vector >{}; +// int main(int argc,char ** argv) { if(argc<3) { - printf("Usage: trimesh_smooth \n"); + printf("Usage: trimesh_smooth \n"); return 0; } @@ -40,10 +55,18 @@ if(argc<3) // some cleaning to get rid of bad file formats like stl that duplicate vertexes.. int dup = tri::Clean::RemoveDuplicateVertex(m); int unref = tri::Clean::RemoveUnreferencedVertex(m); - printf("Removed %i duplicate and %i unreferenced vertices from mesh %s\n",dup,unref,argv[1]); + int Step= atoi(argv[2]); + tri::UpdateTopology::VertexFace(m); + tri::UpdateNormals::PerFaceNormalized(m); + + for(int i=0;i::PerFaceNormalized(m); + PasoDobleSmoothFast(m,atoi(argv[3]),atof(argv[4]),atoi(argv[5])); + } - LaplacianSmooth(m,atoi(argv[2])); + //LaplacianSmooth(m,atoi(argv[2])); tri::io::ExporterPLY::Save(m,"out.ply"); return 0; diff --git a/vcg/complex/trimesh/smooth.h b/vcg/complex/trimesh/smooth.h index 438f5ec0..56a1ac28 100644 --- a/vcg/complex/trimesh/smooth.h +++ b/vcg/complex/trimesh/smooth.h @@ -23,6 +23,9 @@ /**************************************************************************** History $Log: not supported by cvs2svn $ +Revision 1.9 2006/02/06 10:45:47 cignoni +Added missing typenames + Revision 1.7 2006/01/24 13:23:22 pietroni used template types instead of point3f and float inside function calls @@ -534,6 +537,9 @@ void DepthSmooth(MESH_TYPE &m, /****************************************************************************************************************/ /****************************************************************************************************************/ // Paso Double Smoothing +// The proposed +// approach is a two step method where in the first step the face normals +// are adjusted and then, in a second phase, the vertex positions are updated. /****************************************************************************************************************/ /****************************************************************************************************************/ // Classi di info @@ -553,60 +559,55 @@ public: /***************************************************************************/ // Paso Doble Step 1 compute the smoothed normals /***************************************************************************/ -// Calcola la normale media per ogni faccia come area weighted mean con tutte -// le facce adiacenti anche per vertice -// +// Requirements: +// VF Topology +// Normalized Face Normals +// +// This is the Normal Smoothing approach of Shen and Berner +// Fuzzy Vector Median-Based Surface Smoothing TVCG 2004 + template -void NormalSmooth(MESH_TYPE &m, +void NormalSmoothSB(MESH_TYPE &m, SimpleTempData > &TD, - float sigma) + typename MESH_TYPE::ScalarType sigma) { int i; - //vcg::face::Pos ep; - vcg::face::VFIterator ep; - + typedef typename MESH_TYPE::CoordType CoordType; typedef typename MESH_TYPE::ScalarType ScalarType; typename MESH_TYPE::FaceIterator fi; + for(fi=m.face.begin();fi!=m.face.end();++fi) { CoordType bc=(*fi).Barycenter(); + // 1) Clear all the selected flag of faces that are vertex-adjacent to fi for(i=0;i<3;++i) { - - ep.f=(*fi).V(i)->VFp(); - ep.z=(*fi).V(i)->VFi(); - - while (!ep.End()) + vcg::face::VFIterator ep(&*fi,i); + while (!ep.End()) { ep.f->ClearS(); ++ep; } - } - - - //TD[*fi]->SetV(); - (*fi).SetS(); + // 1) Effectively average the normals weighting them with + (*fi).SetS(); CoordType mm=CoordType(0,0,0); for(i=0;i<3;++i) { - ep.f=(*fi).V(i)->VFp(); - ep.z=(*fi).V(i)->VFi(); - while (!ep.End()) + vcg::face::VFIterator ep(&*fi,i); + while (!ep.End()) { - //if(!TD[*(ep.f)]->IsV()) if(! (*ep.f).IsS() ) { if(sigma>0) { ScalarType dd=SquaredDistance(ep.f->Barycenter(),bc); - ScalarType ang=Angle(ep.f->N(),(*fi).N()); - mm+=ep.f->N()*exp(((ScalarType)-sigma)*ang*ang/dd); + ScalarType ang=AngleN(ep.f->N(),(*fi).N()); + mm+=ep.f->N()*exp((-sigma)*ang*ang/dd); } else mm+=ep.f->N(); - //TD[*(ep.f)]->SetV(); (*ep.f).SetS(); } ++ep; @@ -614,10 +615,70 @@ void NormalSmooth(MESH_TYPE &m, } mm.Normalize(); TD[*fi].m=mm; - } } +/***************************************************************************/ +// Paso Doble Step 1 compute the smoothed normals +/***************************************************************************/ +// Requirements: +// VF Topology +// Normalized Face Normals +// +// This is the Normal Smoothing approach bsased on a angle thresholded weighting +// sigma is in the 0 .. 1 range +template +void NormalSmooth(MESH_TYPE &m, + SimpleTempData > &TD, + typename MESH_TYPE::ScalarType sigma) +{ + int i; + + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename vcg::face::VFIterator VFLocalIterator; + typename MESH_TYPE::FaceIterator fi; + + for(fi=m.face.begin();fi!=m.face.end();++fi) + { + CoordType bc=Barycenter(*fi); + // 1) Clear all the selected flag of faces that are vertex-adjacent to fi + for(i=0;i<3;++i) + { + VFLocalIterator ep(&*fi,i); + for (;!ep.End();++ep) + ep.f->ClearS(); + } + + // 1) Effectively average the normals weighting them with + //(*fi).SetS(); + CoordType mm=CoordType(0,0,0); + //CoordType mm=(*fi).N(); + for(i=0;i<3;++i) + { + VFLocalIterator ep(&*fi,i); + for (;!ep.End();++ep) + { + if(! (*ep.f).IsS() ) + { + ScalarType cosang=ep.f->N()*(*fi).N(); + if(cosang >= sigma) + { + ScalarType w = cosang-sigma; + mm += ep.f->N()*(w*w); + } + (*ep.f).SetS(); + } + } + } + mm.Normalize(); + TD[*fi].m=mm; + } + + for(fi=m.face.begin();fi!=m.face.end();++fi) + (*fi).N()=TD[*fi].m; +} + /****************************************************************************************************************/ // Restituisce il gradiente dell'area del triangolo nel punto p. // Nota che dovrebbe essere sempre un vettore che giace nel piano del triangolo e perpendicolare al lato opposto al vertice p. @@ -708,7 +769,36 @@ void FitMesh(MESH_TYPE &m, /****************************************************************************************************************/ +template +void FastFitMesh(MESH_TYPE &m, + SimpleTempData > &TDV, + SimpleTempData > &TDF) +{ + //vcg::face::Pos ep; + vcg::face::VFIterator ep; + typename MESH_TYPE::VertexIterator vi; + typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename vcg::face::VFIterator VFLocalIterator; + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + { + CoordType Sum(0,0,0); + ScalarType cnt=0; + VFLocalIterator ep(&*vi); + for (;!ep.End();++ep) + { + CoordType bc=Barycenter(*ep.F()); + Sum += ep.F()->N()*(ep.F()->N()*(bc - (*vi).P())); + ++cnt; + } + TDV[*vi].np=(*vi).P()+ Sum*(1.0/cnt); + } + + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + (*vi).P()=TDV[*vi].np; + +} @@ -746,6 +836,37 @@ void PasoDobleSmooth(MeshType &m, int step, typename MeshType::ScalarType Sigma= TDV.Stop(); } +template +void PasoDobleSmoothFast(MeshType &m, int step, typename MeshType::ScalarType Sigma=0, int FitStep=50) +{ + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::CoordType CoordType; + + + SimpleTempData< typename MeshType::VertContainer, PDVertInfo > TDV(m.vert); + SimpleTempData< typename MeshType::FaceContainer, PDFaceInfo > TDF(m.face); + PDVertInfo lpzv; + lpzv.np=CoordType(0,0,0); + PDFaceInfo lpzf; + lpzf.m=CoordType(0,0,0); + + assert(m.HasVFTopology()); + m.HasVFTopology(); + TDV.Start(lpzv); + TDF.Start(lpzf); + + for(int j=0;j(m,TDF,Sigma); + + for(int j=0;j(m,TDV,TDF); + + + + TDF.Stop(); + TDV.Stop(); + +}