Translated comments, added various notes, removed some dead code, changed a bit the interface of the default edgelen predicate

This commit is contained in:
Paolo Cignoni 2008-12-05 22:57:20 +00:00
parent 0e13472efb
commit 0047c70cae
1 changed files with 78 additions and 94 deletions

View File

@ -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}} }, /* 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<class MESH_TYPE> template<class MESH_TYPE>
struct MidPoint : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::CoordType > struct MidPoint : public std::unary_function<face::Pos<typename MESH_TYPE::FaceType> , typename MESH_TYPE::CoordType >
{ {
@ -244,90 +247,67 @@ struct MidPointArcNaive : public std::unary_function< face::Pos<typename MESH_TY
}; };
// Basic Predicate that tells if a given edge must be splitted.
/* // the constructure requires the threshold.
// VERY IMPORTANT REQUIREMENT: this function must be symmetric
A partire da una mesh raffina una volta tutti i lati dei triangoli minore di thr // e.g. it must return the same value if the Pos is VFlipped.
Se RefineSelected == true allora raffina SOLO le facce selezionate // If this function is not symmetric the Refine can crash.
i cui edge sono piu'corti di thr.
I nuovi vertici e facce della mesh sono aggiunte in fondo
Requirement: Topologia (in effetti se non si usa la il raffinamento per selezione non servirebbe)
Restituisce false se non raffina nemmeno una faccia.
Si assume che se la mesh ha dati per wedge la funzione di midpoint interpoli i nuovi wedge
tutti uguali per tutti i wedge sulla stessa 'vecchia' faccia.
*/
// binary predicate che dice quando splittare un edge
// la refine usa qt funzione di default: raffina se l'edge^2 e' piu lungo di thr2
template <class MESH_TYPE, class FLT> template <class MESH_TYPE, class FLT>
class EdgeLen class EdgeLen
{ {
public: FLT squaredThr;
FLT thr2; public:
EdgeLen(){};
EdgeLen(FLT threshold) {setThr(threshold);}
void setThr(FLT threshold) {squaredThr = threshold*threshold; }
bool operator()(face::Pos<typename MESH_TYPE::FaceType> ep) const bool operator()(face::Pos<typename MESH_TYPE::FaceType> 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<class MESH_TYPE, class MIDPOINT>
bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelectedP=false)
{
volatile RefineW<MESH_TYPE,MIDPOINT,EdgeLen<typename MESH_TYPE::ScalarType>,true> RT;
volatile RefineW<MESH_TYPE,MIDPOINT,EdgeLen<typename MESH_TYPE::ScalarType>,false> RF;
bool retval;
if(RefineSelectedP) retval=RT.RefineT(m,mid,thr);
if(!RefineSelectedP) retval=RF.RefineT(m,mid,thr);
return retval;
}
template<class MESH_TYPE, class MIDPOINT, class EDGEPRED>
bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep, bool RefineSelectedP=false)
{
RefineW<MESH_TYPE,MIDPOINT,EDGEPRED,true> RT;
RefineW<MESH_TYPE,MIDPOINT,EDGEPRED,false> RF;
bool retval;
if(RefineSelectedP) retval=RT.RefineT(m,mid,ep);
if(!RefineSelectedP) retval=RF.RefineT(m,mid,ep);
return retval;
}
*/
/*********************************************************/
/*********************************************************/
/*********************************************************/ /*********************************************************/
/*********************************************************
template<class MESH_TYPE,class MIDPOINT> Given a mesh the following function refines it according to two functor objects:
bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelected=false, CallBackPos *cb = 0)
{ - a predicate that tells if a given edge must be splitted
EdgeLen <MESH_TYPE, typename MESH_TYPE::ScalarType> ep;
ep.thr2=thr*thr; - a functor that gives you the new poistion of the created vertices (starting from an edge)
return RefineE(m,mid,ep,RefineSelected,cb);
} If RefineSelected is true only selected faces are taken into account for being splitted.
Requirement: FF Adjacency and Manifoldness
**********************************************************/
/*********************************************************/
template<class MESH_TYPE,class MIDPOINT, class EDGEPRED> template<class MESH_TYPE,class MIDPOINT, class EDGEPRED>
bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false, CallBackPos *cb = 0) 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<typename MESH_TYPE::FaceType> PosType;
int j,NewVertNum=0,NewFaceNum=0; int j,NewVertNum=0,NewFaceNum=0;
typedef std::pair<typename MESH_TYPE::VertexPointer,typename MESH_TYPE::VertexPointer> vvpair; typedef std::pair<VertexPointer,VertexPointer> vvpair;
std::map<vvpair,typename MESH_TYPE::VertexPointer> Edge2Vert; std::map<vvpair,VertexPointer> Edge2Vert;
// First Loop: We analyze the mesh to compute the number of the new faces and new vertices // 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; int step=0,PercStep=m.fn/33;
if(PercStep==0) PercStep=1; if(PercStep==0) PercStep=1;
for(fi=m.face.begin(),j=0;fi!=m.face.end();++fi) if(!(*fi).IsD()) for(fi=m.face.begin(),j=0;fi!=m.face.end();++fi) if(!(*fi).IsD())
{ {
if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining...");
for(j=0;j<3;j++){ for(j=0;j<3;j++){
if(ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,j)) && if(ep(PosType(&*fi,j)) &&
(!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ){ (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ){
++NewFaceNum; ++NewFaceNum;
if( ((*fi).V(j)<(*fi).V1(j)) || (*fi).IsB(j) ) 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 } // end face loop
if(NewVertNum==0) return false; if(NewVertNum==0) return false;
typename MESH_TYPE::VertexIterator lastv = tri::Allocator<MESH_TYPE>::AddVertices(m,NewVertNum); VertexIterator lastv = tri::Allocator<MESH_TYPE>::AddVertices(m,NewVertNum);
// typename MESH_TYPE::VertexIterator lastv=m.AddVertices(NewVertNum);
// Secondo loop: We initialize a edge->vertex map
// Secondo Ciclo si inizializza la mappa da edge a vertici for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
// e la posizione dei nuovi vertici
//j=0;
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{ {
if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining..."); if(cb && (++step%PercStep)==0)(*cb)(step/PercStep,"Refining...");
for(j=0;j<3;j++) for(j=0;j<3;j++)
if(ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,j)) && if(ep(PosType (&*fi,j)) &&
(!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) ) (!RefineSelected || ((*fi).IsS() && (*fi).FFp(j)->IsS())) )
if((*fi).V(j)<(*fi).V1(j) || (*fi).IsB(j)){ if((*fi).V(j)<(*fi).V1(j) || (*fi).IsB(j)){
mid( (*lastv), face::Pos<typename MESH_TYPE::FaceType> (&*fi,j)); mid( (*lastv), PosType (&*fi,j));
//(*lastv).P()=((*fi).V(j)->P()+(*fi).V1(j)->P())/2;
Edge2Vert[ vvpair((*fi).V(j),(*fi).V1(j)) ] = &*lastv; Edge2Vert[ vvpair((*fi).V(j),(*fi).V1(j)) ] = &*lastv;
++lastv; ++lastv;
} }
} }
assert(lastv==m.vert.end()); assert(lastv==m.vert.end());
typename MESH_TYPE::FaceIterator lastf = tri::Allocator<MESH_TYPE>::AddFaces(m,NewFaceNum); FaceIterator lastf = tri::Allocator<MESH_TYPE>::AddFaces(m,NewFaceNum);
// MESH_TYPE::FaceIterator lastf = m.AddFaces(NewFaceNum); FaceIterator oldendf = lastf;
// int ddd=0; distance(m.face.begin(),lastf,ddd);
typename MESH_TYPE::FaceIterator oldendf=lastf;
/* /*
v0 v0
f0 f0
mp01 mp02 mp01 f3 mp02
f1 f2
f3 v1 mp12 v2
f1 f2
v1 mp12 v2
*/ */
typename MESH_TYPE::VertexPointer vv[6]; // i sei vertici in gioco VertexPointer vv[6]; // The six vertices that arise in the single triangle splitting
// 0..2 vertici originali del triangolo // 0..2 Original triangle vertices
// 3..5 mp01, mp12, mp20 midpoints of the three edges // 3..5 mp01, mp12, mp20 midpoints of the three edges
typename MESH_TYPE::FacePointer nf[4]; // le quattro facce in gioco. 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) // di texture per wedge (uno per ogni edge)
int fca=0,fcn =0; int fca=0,fcn =0;
for(fi=m.face.begin();fi!=oldendf;++fi) if(!(*fi).IsD()) 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++; fcn++;
vv[0]=(*fi).V(0); vv[0]=(*fi).V(0);
vv[1]=(*fi).V(1); vv[1]=(*fi).V(1);
vv[2]=(*fi).V(2); vv[2]=(*fi).V(2);
bool e0=ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,0)); bool e0=ep(PosType(&*fi,0));
bool e1=ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,1)); bool e1=ep(PosType(&*fi,1));
bool e2=ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,2)); bool e2=ep(PosType(&*fi,2));
if(e0) if(e0)
if((*fi).V(0)<(*fi).V(1)|| (*fi).IsB(0)) vv[3]=Edge2Vert[ vvpair((*fi).V(0),(*fi).V(1)) ]; 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)) ]; 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(); // m.fn= m.face.size();
assert(lastf==m.face.end()); assert(lastf==m.face.end());
assert(!m.vert.empty()); assert(!m.vert.empty());
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()){
@ -472,6 +446,16 @@ bool RefineE(MESH_TYPE &m, MIDPOINT mid, EDGEPRED ep,bool RefineSelected=false,
vcg::tri::UpdateTopology<MESH_TYPE>::FaceFace(m); vcg::tri::UpdateTopology<MESH_TYPE>::FaceFace(m);
return true; return true;
} }
/*************************************************************************/
// simple wrapper of the base refine for lazy coder that do not need a edge predicate
template<class MESH_TYPE,class MIDPOINT>
bool Refine(MESH_TYPE &m, MIDPOINT mid, typename MESH_TYPE::ScalarType thr=0,bool RefineSelected=false, CallBackPos *cb = 0)
{
EdgeLen <MESH_TYPE, typename MESH_TYPE::ScalarType> ep(thr);
return RefineE(m,mid,ep,RefineSelected,cb);
}
/*************************************************************************/ /*************************************************************************/
/* /*