From 0047c70caef1621d5ff25ca3f15176d92d662aee Mon Sep 17 00:00:00 2001 From: cignoni Date: Fri, 5 Dec 2008 22:57:20 +0000 Subject: [PATCH] Translated comments, added various notes, removed some dead code, changed a bit the interface of the default edgelen predicate --- vcg/complex/trimesh/refine.h | 172 ++++++++++++++++------------------- 1 file changed, 78 insertions(+), 94 deletions(-) diff --git a/vcg/complex/trimesh/refine.h b/vcg/complex/trimesh/refine.h index 156ef8ce..f5572766 100644 --- a/vcg/complex/trimesh/refine.h +++ b/vcg/complex/trimesh/refine.h @@ -110,7 +110,10 @@ const Split SplitTab[8]={ /* 1 1 1 */ {4, {{3,4,5},{0,3,5},{3,1,4},{5,4,2}}, {{0,0},{0,0}}, {{3,3,3},{0,3,2},{0,1,3},{3,1,2}} }, }; -// Classe di suddivisione base. Taglia il lato esattamente a meta'. +// Basic subdivision class +// This class must provide methods for finding the position of the newly created vertices +// In this implemenation we simply put the new vertex in the MidPoint position. +// Color and TexCoords are interpolated accordingly. template struct MidPoint : public std::unary_function , typename MESH_TYPE::CoordType > { @@ -244,90 +247,67 @@ struct MidPointArcNaive : public std::unary_function< face::Pos class EdgeLen { - public: - FLT thr2; + FLT squaredThr; +public: + EdgeLen(){}; + EdgeLen(FLT threshold) {setThr(threshold);} + void setThr(FLT threshold) {squaredThr = threshold*threshold; } bool operator()(face::Pos ep) const { - return SquaredDistance(ep.f->V(ep.z)->P(), ep.f->V1(ep.z)->P())>thr2; + return SquaredDistance(ep.V()->P(), ep.VFlip()->P())>squaredThr; } }; -/* -template -bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelectedP=false) -{ - volatile RefineW,true> RT; - volatile RefineW,false> RF; - bool retval; - if(RefineSelectedP) retval=RT.RefineT(m,mid,thr); - if(!RefineSelectedP) retval=RF.RefineT(m,mid,thr); - return retval; -} - -template -bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep, bool RefineSelectedP=false) -{ - RefineW RT; - RefineW RF; - - bool retval; - if(RefineSelectedP) retval=RT.RefineT(m,mid,ep); - if(!RefineSelectedP) retval=RF.RefineT(m,mid,ep); - return retval; -} -*/ -/*********************************************************/ -/*********************************************************/ /*********************************************************/ +/********************************************************* -template -bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelected=false, CallBackPos *cb = 0) -{ - EdgeLen ep; - ep.thr2=thr*thr; - return RefineE(m,mid,ep,RefineSelected,cb); -} +Given a mesh the following function refines it according to two functor objects: + +- a predicate that tells if a given edge must be splitted + +- a functor that gives you the new poistion of the created vertices (starting from an edge) + +If RefineSelected is true only selected faces are taken into account for being splitted. + +Requirement: FF Adjacency and Manifoldness + +**********************************************************/ +/*********************************************************/ template bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, CallBackPos *cb = 0) { + // common typenames + typedef typename MESH_TYPE::VertexIterator VertexIterator; + typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::VertexPointer VertexPointer; + typedef typename MESH_TYPE::FacePointer FacePointer; + typedef typename MESH_TYPE::FaceType::TexCoordType TexCoordType; + + typedef face::Pos PosType; + int j,NewVertNum=0,NewFaceNum=0; - typedef std::pair vvpair; - std::map Edge2Vert; + typedef std::pair vvpair; + std::map Edge2Vert; // First Loop: We analyze the mesh to compute the number of the new faces and new vertices - typename MESH_TYPE::FaceIterator fi; + FaceIterator fi; int step=0,PercStep=m.fn/33; if(PercStep==0) PercStep=1; for(fi=m.face.begin(),j=0;fi!=m.face.end();++fi) if(!(*fi).IsD()) { if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); for(j=0;j<3;j++){ - if(ep(face::Pos (&*fi,j)) && + if(ep(PosType(&*fi,j)) && (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ){ ++NewFaceNum; if( ((*fi).V(j)<(*fi).V1(j)) || (*fi).IsB(j) ) @@ -336,67 +316,62 @@ bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, } } // end face loop if(NewVertNum==0) return false; - typename MESH_TYPE::VertexIterator lastv = tri::Allocator::AddVertices(m,NewVertNum); -// typename MESH_TYPE::VertexIterator lastv=m.AddVertices(NewVertNum); + VertexIterator lastv = tri::Allocator::AddVertices(m,NewVertNum); + + // Secondo loop: We initialize a edge->vertex map - // Secondo Ciclo si inizializza la mappa da edge a vertici - // e la posizione dei nuovi vertici - //j=0; - for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) + for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); for(j=0;j<3;j++) - if(ep(face::Pos (&*fi,j)) && + if(ep(PosType (&*fi,j)) && (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ) if((*fi).V(j)<(*fi).V1(j) || (*fi).IsB(j)){ - mid( (*lastv), face::Pos (&*fi,j)); - //(*lastv).P()=((*fi).V(j)->P()+(*fi).V1(j)->P())/2; + mid( (*lastv), PosType (&*fi,j)); Edge2Vert[ vvpair((*fi).V(j),(*fi).V1(j)) ] = &*lastv; ++lastv; } } assert(lastv==m.vert.end()); - - typename MESH_TYPE::FaceIterator lastf = tri::Allocator::AddFaces(m,NewFaceNum); -// MESH_TYPE::FaceIterator lastf = m.AddFaces(NewFaceNum); -// int ddd=0; distance(m.face.begin(),lastf,ddd); - typename MESH_TYPE::FaceIterator oldendf=lastf; + + FaceIterator lastf = tri::Allocator::AddFaces(m,NewFaceNum); + FaceIterator oldendf = lastf; /* - v0 + v0 - f0 + f0 - mp01 mp02 + mp01 f3 mp02 + + + f1 f2 - f3 - f1 f2 - - v1 mp12 v2 + v1 mp12 v2 */ - typename MESH_TYPE::VertexPointer vv[6]; // i sei vertici in gioco - // 0..2 vertici originali del triangolo - // 3..5 mp01, mp12, mp20 midpoints of the three edges - typename MESH_TYPE::FacePointer nf[4]; // le quattro facce in gioco. + VertexPointer vv[6]; // The six vertices that arise in the single triangle splitting + // 0..2 Original triangle vertices + // 3..5 mp01, mp12, mp20 midpoints of the three edges + FacePointer nf[4]; // The (up to) four faces that are created. - typename MESH_TYPE::FaceType::TexCoordType wtt[6]; // per ogni faccia sono al piu' tre i nuovi valori + TexCoordType wtt[6]; // per ogni faccia sono al piu' tre i nuovi valori // di texture per wedge (uno per ogni edge) - + int fca=0,fcn =0; for(fi=m.face.begin();fi!=oldendf;++fi) if(!(*fi).IsD()) { - if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); + if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); fcn++; vv[0]=(*fi).V(0); vv[1]=(*fi).V(1); vv[2]=(*fi).V(2); - bool e0=ep(face::Pos (&*fi,0)); - bool e1=ep(face::Pos (&*fi,1)); - bool e2=ep(face::Pos (&*fi,2)); - + bool e0=ep(PosType(&*fi,0)); + bool e1=ep(PosType(&*fi,1)); + bool e2=ep(PosType(&*fi,2)); + if(e0) if((*fi).V(0)<(*fi).V(1)|| (*fi).IsB(0)) vv[3]=Edge2Vert[ vvpair((*fi).V(0),(*fi).V(1)) ]; else vv[3]=Edge2Vert[ vvpair((*fi).V(1),(*fi).V(0)) ]; @@ -461,7 +436,6 @@ bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, } // m.fn= m.face.size(); - assert(lastf==m.face.end()); assert(!m.vert.empty()); for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()){ @@ -472,6 +446,16 @@ bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, vcg::tri::UpdateTopology::FaceFace(m); return true; } + +/*************************************************************************/ +// simple wrapper of the base refine for lazy coder that do not need a edge predicate + +template +bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelected=false, CallBackPos *cb = 0) +{ + EdgeLen ep(thr); + return RefineE(m,mid,ep,RefineSelected,cb); +} /*************************************************************************/ /*