From eb117f8394a95f8812c6e92e939662f451732bc0 Mon Sep 17 00:00:00 2001 From: cnr-isti-vclab Date: Wed, 16 Mar 2005 16:14:12 +0000 Subject: [PATCH] aggiunta funzione PasoDobleSmooth e relative: - FitMesh - FaceErrorGrad - CrossProdGradient - TriAreaGradient - NormalSmooth e le classi: - PDVertInfo - PDFaceInfo necessarie per utilizzare SimpleTempData --- vcg/complex/trimesh/smooth.h | 218 +++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/vcg/complex/trimesh/smooth.h b/vcg/complex/trimesh/smooth.h index 5d0a1aa7..12d0dd66 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.1 2004/12/11 14:53:19 ganovelli +first partial porting: compiled gcc,intel and msvc + /****************************************************************************/ @@ -494,6 +497,221 @@ void DepthSmooth(MESH_TYPE &m, TD.Stop(); } + + +/****************************************************************************************************************/ +/****************************************************************************************************************/ +// Paso Double Smoothing +/****************************************************************************************************************/ +/****************************************************************************************************************/ +// Classi di info +template +class PDVertInfo +{ +public: + Point3 np; +}; + +template +class PDFaceInfo +{ +public: + Point3 m; +}; +/***************************************************************************/ +// 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 +// +template +void NormalSmooth(MESH_TYPE &m, + SimpleTempData > &TD, + float sigma) +{ + int i; + //vcg::face::Pos ep; + vcg::face::VFIterator ep; + + + MESH_TYPE::FaceIterator fi; + for(fi=m.face.begin();fi!=m.face.end();++fi) + { + + Point3f bc=(*fi).Barycenter(); + for(i=0;i<3;++i) + { + + ep.f=(*fi).V(i)->VFp(); + ep.z=(*fi).V(i)->VFi(); + + while (!ep.End()) + { + ep.f->ClearS(); + ep++; + } + + } + + + + //TD[*fi]->SetV(); + (*fi).SetS(); + Point3f mm=Point3f(0,0,0); + for(i=0;i<3;++i) + { + ep.f=(*fi).V(i)->VFp(); + ep.z=(*fi).V(i)->VFi(); + while (!ep.End()) + { + //if(!TD[*(ep.f)]->IsV()) + if(! (*ep.f).IsS() ) + { + if(sigma>0) + { + float dd=SquaredDistance(ep.f->Barycenter(),bc); + float ang=Angle(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++; + } + } + mm.Normalize(); + TD[*fi].m=mm; + + } +} + +/****************************************************************************************************************/ +// 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. +// Ottimizzato con Maple e poi pesantemente a mano. +template +Point3 TriAreaGradient(Point3 &p,Point3 &p0,Point3 &p1) +{ + Point3 dd = p1-p0; + Point3 d0 = p-p0; + Point3 d1 = p-p1; + Point3 grad; + + FLT t16 = d0[1]* d1[2] - d0[2]* d1[1]; + FLT t5 = -d0[2]* d1[0] + d0[0]* d1[2]; + FLT t4 = -d0[0]* d1[1] + d0[1]* d1[0]; + + FLT delta= sqrtf(t4*t4 + t5*t5 +t16*t16); + + grad[0]= (t5 * (-dd[2]) + t4 * ( dd[1]))/delta; + grad[1]= (t16 * (-dd[2]) + t4 * (-dd[0]))/delta; + grad[2]= (t16 * ( dd[1]) + t5 * ( dd[0]))/delta; + + return grad; +} + +template +Point3 CrossProdGradient(Point3 &p,Point3 &p0,Point3 &p1, Point3 &m) +{ + Point3 grad; + + grad[0] = (-p0[2] + p1[2])*m[1] + (-p1[1] + p0[1])*m[2]; + grad[1] = (-p1[2] + p0[2])*m[0] + (-p0[0] + p1[0])*m[2]; + grad[2] = (-p0[1] + p1[1])*m[0] + (-p1[0] + p0[0])*m[1]; + + return grad; +} + +/* +Deve Calcolare il gradiente di +E(p) = A(p,p0,p1) (n - m)^2 = +A(...) (2-2nm) = +(p0-p)^(p1-p) +2A - 2A * ------------- m = +2A + +2A - 2 (p0-p)^(p1-p) * m +*/ +template +Point3 FaceErrorGrad(Point3 &p,Point3 &p0,Point3 &p1, Point3 &m) +{ + return TriAreaGradient(p,p0,p1) *2.0f + - CrossProdGradient(p,p0,p1,m) *2.0f ; +} +/***************************************************************************/ +// Paso Doble Step 2 Fitta la mesh a un dato insieme di normali +/***************************************************************************/ + +template +void FitMesh(MESH_TYPE &m, + SimpleTempData > &TDV, + SimpleTempData > &TDF, + float lambda) +{ + //vcg::face::Pos ep; + vcg::face::VFIterator ep; + MESH_TYPE::VertexIterator vi; + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + { + Point3f ErrGrad=Point3f(0,0,0); + + ep.f=(*vi).VFp(); + ep.z=(*vi).VFi(); + while (!ep.End()) + { + ErrGrad+=FaceErrorGrad(ep.f->V(ep.z)->P(),ep.f->V1(ep.z)->P(),ep.f->V2(ep.z)->P(),TDF[ep.f].m); + ep++; + } + TDV[*vi].np=(*vi).P()-ErrGrad*lambda; + } + + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + (*vi).P()=TDV[*vi].np; + +} +/****************************************************************************************************************/ + + + + + + + + + +template +void PasoDobleSmooth(MESH_TYPE &m, int step, typename MESH_TYPE::ScalarType Sigma=0, int FitStep=10, typename MESH_TYPE::ScalarType FitLambda=0.05) +{ + + + SimpleTempData< typedef MESH_TYPE::VertContainer, PDVertInfo > TDV(m.vert); + SimpleTempData< typedef MESH_TYPE::FaceContainer, PDFaceInfo > TDF(m.face); + PDVertInfo lpzv; + lpzv.np=typename MESH_TYPE::CoordType(0,0,0); + PDFaceInfo lpzf; + lpzf.m=typename MESH_TYPE::CoordType(0,0,0); + + assert(m.HasVFTopology()); + m.HasVFTopology(); + TDV.Start(lpzv); + TDF.Start(lpzf); + for(int j=0;j::PerFace(m); + NormalSmooth(m,TDF,Sigma); + for(int k=0;k(m,TDV,TDF,FitLambda); + } + + TDF.Stop(); + TDV.Stop(); + +} + + + } // End namespace vcg #endif // VCG_SMOOTH \ No newline at end of file