From 5e7f95f94a4e0afaeefffbae3a428f1ab7a09a2e Mon Sep 17 00:00:00 2001 From: nicopietroni Date: Thu, 8 Mar 2012 18:09:31 +0000 Subject: [PATCH] major changes --- .../parametrization/tangent_field_operators.h | 276 +++++++++++++++--- .../algorithms/parametrization/uv_utils.h | 123 ++++++-- 2 files changed, 334 insertions(+), 65 deletions(-) diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index dab461ad..34e5493b 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -21,6 +21,9 @@ * * ****************************************************************************/ +#include +#include + #ifndef VCG_TANGENT_FIELD_OPERATORS #define VCG_TANGENT_FIELD_OPERATORS @@ -39,7 +42,180 @@ namespace vcg { private: static ScalarType Sign(ScalarType a){return (ScalarType)((a>0)?+1:-1);} + static void NormalizePerVertImportanceVal(MeshType &mesh) + { + vcg::Distribution Distr; + for (int i=0;iIsD())continue; + Distr.Add(fabs(v->K2())); + Distr.Add(fabs(v->K1())); + /*if (fabs(v->K1())>MaxK) + MaxK=fabs(fabs(v->K1())); + if (fabs(v->K2())>MaxK) + MaxK=fabs(fabs(v->K2()));*/ + } + ScalarType perc=Distr.Percentile(.99); + for (int i=0;iIsD())continue; + ScalarType val; + val=fabs(v->K1()); + if (val>perc) + val=perc; + else + val/=perc; + + v->K1()=val; + val=(v->K2()); + if (val>perc) + val=perc; + else + val/=perc; + v->K2()=val; + } + } + + //static void NormalizePerVertImportanceVal(MeshType &mesh) + //{ + // //vcg::Distribution Distr; + // ScalarType MaxK=0; + // ScalarType MinK=0; + // for (int i=0;iIsD())continue; + // Distr.Add((v->K2())); + // Distr.Add((v->K1())); + // if (fabs(v->K1())>MaxK) + // MaxK=fabs(fabs(v->K1())) + // if (fabs(v->K2())>MaxK) + // MaxK=fabs(fabs(v->K2()));*/ + // } + // ScalarType perc0=Distr.Percentile(.1); + // ScalarType perc1=Distr.Percentile(.9); + // ScalarType val=perc0-perc1 + // for (int i=0;iIsD())continue; + // ScalarType val; + // val=(v->K1()); + // if (valK1()=val; + // val=(v->K2()); + // if (val>perc) + // val=perc; + // else + // val/=perc; + // v->K2()=val; + // } + //} + public: + static void AddCrossAttributesIfNeeded(MeshType &mesh, + PerFaceAttributeHandle &_FHDir0, + PerFaceAttributeHandle &_FHDir1) + //PerFaceScalarAttributeHandle &_FHVal) + { + bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0"); + bool CrossDir1 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir1"); + bool CrossVal = vcg::tri::HasPerFaceAttribute(mesh,"CrossVal"); + + if (!CrossDir0) + _FHDir0=vcg::tri::Allocator::AddPerFaceAttribute(mesh,std::string("CrossDir0")); + else + _FHDir0=vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir0")); + + if (!CrossDir1) + _FHDir1=vcg::tri::Allocator::AddPerFaceAttribute(mesh,std::string("CrossDir1")); + else + _FHDir1=vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir1")); + + + /*if (!CrossVal) + _FHVal=vcg::tri::Allocator::AddPerFaceAttribute(test_mesh,std::string("CrossVal")); + else + _FHVal=vcg::tri::Allocator::GetPerFaceAttribute(test_mesh,std::string("CrossVal"));*/ + } + + static void CopyFaceCrossField(MeshType &left,MeshType &right) + { + + PerFaceAttributeHandle _FHR0,_FHR1; + PerFaceScalarAttributeHandle _FHRVal; + bool CrossDir0 = vcg::tri::HasPerFaceAttribute(right,"CrossDir0"); + bool CrossDir1 = vcg::tri::HasPerFaceAttribute(right,"CrossDir1"); + //bool CrossVal = vcg::tri::HasPerFaceAttribute(right,"CrossVal"); + assert(CrossDir0); + assert(CrossDir1); + //assert(CrossVal); + + _FHR0=vcg::tri::Allocator::GetPerFaceAttribute(right,std::string("CrossDir0")); + _FHR1=vcg::tri::Allocator::GetPerFaceAttribute(right,std::string("CrossDir1")); + //_FHRVal=vcg::tri::Allocator::GetPerFaceAttribute(right,std::string("CrossVal")); + + PerFaceAttributeHandle _FHL0,_FHL1; + //PerFaceScalarAttributeHandle _FHLVal; + AddCrossAttributesIfNeeded(left,_FHL0,_FHL1);//,_FHLVal); + + assert(left.face.size()==right.face.size()); + for (int i=0;i::FaceFace(mesh); + vcg::tri::UpdateTopology::VertexFace(mesh); + vcg::tri::UpdateBounding::Box(mesh); + + //set as selected high curvature value + vcg::tri::UpdateCurvature::PrincipalDirectionsNormalCycles(mesh); + NormalizePerVertImportanceVal(mesh); + ///save the curvature value + std::vector K1,K2; + K1.resize(mesh.vert.size()); + K2.resize(mesh.vert.size()); + for (int j=0;jIsD())continue; + K1[j]=v->K1(); + K2[j]=v->K2(); + } + ///then find multiscale curvature directions + vcg::tri::UpdateCurvature::PrincipalDirectionsPCA(mesh,mesh.bbox.Diag()/200.0); + ///and save back importance val + for (int j=0;jIsD())continue; + v->K1()=K1[j]; + v->K2()=K2[j]; + } + + ///set normal according to curvature + for (int j=0;jIsD())continue; + CoordType N0=v->N(); + v->N()=v->PD1()^v->PD2(); + v->N().Normalize(); + if (N0*v->N()<0) + v->N()=-v->N(); + } + } ///fird a tranformation matrix to transform ///the 3D space to 2D tangent space specified @@ -146,21 +322,21 @@ namespace vcg { CrossVector(mesh,f,axis); return axis[index]; } - + ///return the direction of the cross field in 3D static void SetCrossVector(MeshType &mesh, - const FaceType &f, - CoordType dir0, - CoordType dir1) + const FaceType &f, + CoordType dir0, + CoordType dir1) { bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0"); assert(CrossDir0); bool CrossDir1 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir1"); assert(CrossDir1); MeshType::PerFaceAttributeHandle Fh0= - vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir0")); + vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir0")); MeshType::PerFaceAttributeHandle Fh1= - vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir1")); + vcg::tri::Allocator::GetPerFaceAttribute(mesh,std::string("CrossDir1")); Fh0[f]=dir0; Fh1[f]=dir1; } @@ -189,14 +365,33 @@ namespace vcg { ///interpolate cross field with barycentric coordinates static CoordType InterpolateCrossField(const CoordType &t0, - const CoordType &t1, - const CoordType &t2, - const CoordType &n, - const CoordType &bary) + const CoordType &t1, + const CoordType &t2, + const CoordType &n0, + const CoordType &n1, + const CoordType &n2, + const CoordType &target_n, + const CoordType &bary) { - CoordType trans0=t0; - CoordType trans1=K_PI(t1,t0,n); - CoordType trans2=K_PI(t2,t0,n); + vcg::Matrix33 R0=vcg::RotationMatrix(n0,target_n); + vcg::Matrix33 R1=vcg::RotationMatrix(n1,target_n); + vcg::Matrix33 R2=vcg::RotationMatrix(n2,target_n); + ///rotate + CoordType trans0=R0*t0; + CoordType trans1=R1*t1; + CoordType trans2=R2*t2; + /*CoordType trans0=t0; + CoordType trans1=t1; + CoordType trans2=t2;*/ + trans0.Normalize(); + trans1.Normalize(); + trans2.Normalize(); + ///k_PI/2 rotation + trans1=K_PI(trans1,trans0,target_n); + trans2=K_PI(trans2,trans0,target_n); + trans1.Normalize(); + trans2.Normalize(); + CoordType sum = trans0*bary.X() + trans1 * bary.Y() + trans2 * bary.Z(); return sum; } @@ -226,18 +421,27 @@ namespace vcg { return sum; } - /*///interpolate cross field with barycentric coordinates - template - typename FaceType::CoordType InterpolateCrossField(const typename FaceType::CoordType &t0, - const typename FaceType::CoordType &t1, - const typename FaceType::CoordType &n, - const typename FaceType::ScalarType &weight) + ///interpolate cross field with scalar weight + static typename FaceType::CoordType InterpolateCrossFieldLine(const typename FaceType::CoordType &t0, + const typename FaceType::CoordType &t1, + const typename FaceType::CoordType &n0, + const typename FaceType::CoordType &n1, + const typename FaceType::CoordType &target_n, + const typename FaceType::ScalarType &weight) { - CoordType trans0=t0; - CoordType trans1=K_PI(t1,t0,n); - CoordType sum = t0*weight + MyCross::V( t1, t0, n ) * (1.0-weight); - return sum; - }*/ + vcg::Matrix33 R0=vcg::RotationMatrix(n0,target_n); + vcg::Matrix33 R1=vcg::RotationMatrix(n1,target_n); + CoordType trans0=R0*t0; + CoordType trans1=R1*t1; + //CoordType trans0=t0;//R0*t0; + //CoordType trans1=t1;//R1*t1; + trans0.Normalize(); + trans1.Normalize(); + trans1=K_PI(trans1,trans0,target_n); + trans1.Normalize(); + CoordType sum = trans0*weight + trans1 * (1.0-weight); + return sum; + } ///return the difference of two cross field, values between [0,0.5] @@ -254,8 +458,8 @@ namespace vcg { ///compute the mismatch between 2 faces static int MissMatch(MeshType &mesh, - const FaceType &f0, - const FaceType &f1) + const FaceType &f0, + const FaceType &f1) { CoordType dir0=CrossVector(mesh,f0,0); CoordType dir1=CrossVector(mesh,f1,0); @@ -274,10 +478,10 @@ namespace vcg { k=(-(3*i))%4; return k; } - + static void SortedFaces(MeshType &mesh, - VertexType &v, - std::vector &faces) + VertexType &v, + std::vector &faces) { typedef typename VertexType::FaceType FaceType; @@ -309,7 +513,7 @@ namespace vcg { VFI.FlipE(); FaceType *next_f=VFI.F(); - + ///test if I've finiseh with the face exploration complete_turn=(next_f==f_init); /// or if I've just crossed a mismatch @@ -371,7 +575,7 @@ namespace vcg { //} static int SimilarDir(CoordType dir[4], - CoordType TestD) + CoordType TestD) { int ret=-1; ScalarType maxAcc=-1; @@ -389,14 +593,14 @@ namespace vcg { } static bool IsSingular(MeshType &mesh, - VertexType &v, - int &missmatch) + VertexType &v, + int &missmatch) { typedef typename VertexType::FaceType FaceType; ///check that is on border.. if (v.IsB()) return false; - + std::vector faces; SortedFaces(mesh,v,faces); for (int i=0;i - vcg::Box2 PerWedgeUVBox(MeshType &m) + class UV_Utils { - vcg::Box2 UVBox; - typename MeshType::FaceIterator fi; - for (fi=m.face.begin();fi!=m.face.end();fi++) + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::FaceIterator FaceIterator; + typedef typename vcg::Point2 UVCoordType; + + public: + ///calculate the BBox in UV space + static vcg::Box2 PerWedgeUVBox(MeshType &m) { - if ((*fi).IsD()) continue; - for (int i=0;i<3;i++) - UVBox.Add((*fi).WT(i).P()); + vcg::Box2 UVBox; + FaceIterator fi; + for (fi=m.face.begin();fi!=m.face.end();fi++) + { + if ((*fi).IsD()) continue; + for (int i=0;i<3;i++) + UVBox.Add((*fi).WT(i).P()); + } + return UVBox; + } + + ///calculate the BBox in UV space + static vcg::Box2 PerVertUVBox(MeshType &m) + { + vcg::Box2 UVBox; + VertexIterator vi; + for (vi=m.vert.begin();vi!=m.vert.end();vi++) + { + if ((*vi).IsD()) continue; + UVBox.Add((*vi).T().P()); + } + return UVBox; } - return UVBox; - } - ///transform curvature to UV space - template - vcg::Point2 Coord3DtoUV(FaceType &f, - typename FaceType::CoordType dir) - { - ///then transform to UV - CoordType bary3d=(f.P(0)+f.P(1)+f.P(2))/3.0; - vcg::Point2 baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0; - CoordType dir3d=bary3d+dir; - CoordType baryCoordsUV; - vcg::InterpolationParameters(f,dir3d,baryCoordsUV); - vcg::Point2 dirUV=baryCoordsUV.X()*f.WT(0).P()+ - baryCoordsUV.Y()*f.WT(1).P()+ - baryCoordsUV.Z()*f.WT(2).P()-baryUV; - dirUV.Normalize(); - return dirUV; - } + ///transform curvature to UV space + static UVCoordType Coord3DtoUV(FaceType &f,const CoordType &dir) + { + ///then transform to UV + CoordType bary3d=(f.P(0)+f.P(1)+f.P(2))/3.0; + UVCoordType baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0; + CoordType dir3d=bary3d+dir; + CoordType baryCoordsUV; + vcg::InterpolationParameters(f,dir3d,baryCoordsUV); + UVCoordType dirUV=baryCoordsUV.X()*f.WT(0).P()+ + baryCoordsUV.Y()*f.WT(1).P()+ + baryCoordsUV.Z()*f.WT(2).P()-baryUV; + dirUV.Normalize(); + return dirUV; + } -} //End Namespace Tri + static void GloballyMirrorX(MeshType &m) + { + vcg::Box2 BBuv=PerVertUVBox(m); + ScalarType Xmin=BBuv.min.X(); + ScalarType Xmax=BBuv.max.X(); + ScalarType XAv=(Xmax+Xmin)/2; + VertexIterator vi; + for (vi=m.vert.begin();vi!=m.vert.end();vi++) + { + ScalarType distAV=(*vi).T().P().X()-XAv; + (*vi).T().P().X()=XAv-distAV; + } + } + + static void LaplacianUVVert(MeshType &m,bool fix_borders=false,int steps=3) + { + FaceIterator fi; + for (int s=0;s num(m.vert.size(),0); + std::vector UVpos(m.vert.size(),UVCoordType(0,0)); + for (fi=m.face.begin();fi!=m.face.end();fi++) + { + for (int j=0;j<3;j++) + { + VertexType *v0=(*fi).V(0); + VertexType *v1=(*fi).V1(0); + VertexType *v2=(*fi).V2(0); + UVCoordType uv1=v1->T().P(); + UVCoordType uv2=v2->T().P(); + int index=v0-&(m.vert[0]); + num[index]+=2; + UVpos[index]+=uv1; + UVpos[index]+=uv2; + } + } + VertexIterator vi; + for (int i=0;i