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}} },
};
// 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>
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
};
/*
A partire da una mesh raffina una volta tutti i lati dei triangoli minore di thr
Se RefineSelected == true allora raffina SOLO le facce selezionate
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
// Basic Predicate that tells if a given edge must be splitted.
// the constructure requires the threshold.
// VERY IMPORTANT REQUIREMENT: this function must be symmetric
// e.g. it must return the same value if the Pos is VFlipped.
// If this function is not symmetric the Refine can crash.
template <class MESH_TYPE, class FLT>
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<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>
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;
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<class MESH_TYPE,class MIDPOINT, class EDGEPRED>
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;
typedef std::pair<typename MESH_TYPE::VertexPointer,typename MESH_TYPE::VertexPointer> vvpair;
std::map<vvpair,typename MESH_TYPE::VertexPointer> Edge2Vert;
typedef std::pair<VertexPointer,VertexPointer> vvpair;
std::map<vvpair,VertexPointer> 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<typename MESH_TYPE::FaceType> (&*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<MESH_TYPE>::AddVertices(m,NewVertNum);
// typename MESH_TYPE::VertexIterator lastv=m.AddVertices(NewVertNum);
VertexIterator lastv = tri::Allocator<MESH_TYPE>::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<typename MESH_TYPE::FaceType> (&*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<typename MESH_TYPE::FaceType> (&*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<MESH_TYPE>::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<MESH_TYPE>::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<typename MESH_TYPE::FaceType> (&*fi,0));
bool e1=ep(face::Pos<typename MESH_TYPE::FaceType> (&*fi,1));
bool e2=ep(face::Pos<typename MESH_TYPE::FaceType> (&*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<MESH_TYPE>::FaceFace(m);
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);
}
/*************************************************************************/
/*