major changes

This commit is contained in:
Nico Pietroni 2012-03-08 18:09:31 +00:00
parent f97f54a89b
commit 5e7f95f94a
2 changed files with 334 additions and 65 deletions

View File

@ -21,6 +21,9 @@
* *
****************************************************************************/
#include <vcg/math/histogram.h>
#include <vcg/complex/algorithms/update/curvature.h>
#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<ScalarType> Distr;
for (int i=0;i<mesh.vert.size();i++)
{
VertexType *v=&mesh.vert[i];
if (v->IsD())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;i<mesh.vert.size();i++)
{
VertexType *v=&mesh.vert[i];
if (v->IsD())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<ScalarType> Distr;
// ScalarType MaxK=0;
// ScalarType MinK=0;
// for (int i=0;i<mesh.vert.size();i++)
// {
// VertexType *v=&mesh.vert[i];
// if (v->IsD())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;i<mesh.vert.size();i++)
// {
// VertexType *v=&mesh.vert[i];
// if (v->IsD())continue;
// ScalarType val;
// val=(v->K1());
// if (val<perc0)
// val=perc0;
// else
// val/=perc;
// v->K1()=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<MeshType>::AddPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
else
_FHDir0=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
if (!CrossDir1)
_FHDir1=vcg::tri::Allocator<MeshType>::AddPerFaceAttribute<CoordType>(mesh,std::string("CrossDir1"));
else
_FHDir1=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir1"));
/*if (!CrossVal)
_FHVal=vcg::tri::Allocator<MeshType>::AddPerFaceAttribute<ScalarType>(test_mesh,std::string("CrossVal"));
else
_FHVal=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<ScalarType>(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<MeshType>::GetPerFaceAttribute<CoordType>(right,std::string("CrossDir0"));
_FHR1=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(right,std::string("CrossDir1"));
//_FHRVal=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<ScalarType>(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<left.face.size();i++)
{
_FHL0[i]=_FHR0[i];
_FHL1[i]=_FHR1[i];
//_FHLVal[i]=_FHRVal[i];
}
}
static void SetVertCrossFromCurvature(MeshType &mesh)
{
vcg::tri::UpdateTopology<MeshType>::FaceFace(mesh);
vcg::tri::UpdateTopology<MeshType>::VertexFace(mesh);
vcg::tri::UpdateBounding<MeshType>::Box(mesh);
//set as selected high curvature value
vcg::tri::UpdateCurvature<MeshType>::PrincipalDirectionsNormalCycles(mesh);
NormalizePerVertImportanceVal(mesh);
///save the curvature value
std::vector<ScalarType> K1,K2;
K1.resize(mesh.vert.size());
K2.resize(mesh.vert.size());
for (int j=0;j<mesh.vert.size();j++)
{
VertexType *v=&mesh.vert[j];
if(v->IsD())continue;
K1[j]=v->K1();
K2[j]=v->K2();
}
///then find multiscale curvature directions
vcg::tri::UpdateCurvature<MeshType>::PrincipalDirectionsPCA(mesh,mesh.bbox.Diag()/200.0);
///and save back importance val
for (int j=0;j<mesh.vert.size();j++)
{
VertexType *v=&mesh.vert[j];
if(v->IsD())continue;
v->K1()=K1[j];
v->K2()=K2[j];
}
///set normal according to curvature
for (int j=0;j<mesh.vert.size();j++)
{
VertexType *v=&mesh.vert[j];
if(v->IsD())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<CoordType> Fh0=
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
MeshType::PerFaceAttributeHandle<CoordType> Fh1=
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir1"));
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(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<ScalarType> R0=vcg::RotationMatrix(n0,target_n);
vcg::Matrix33<ScalarType> R1=vcg::RotationMatrix(n1,target_n);
vcg::Matrix33<ScalarType> 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 <class FaceType>
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<ScalarType> R0=vcg::RotationMatrix(n0,target_n);
vcg::Matrix33<ScalarType> 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<FaceType*> &faces)
VertexType &v,
std::vector<FaceType*> &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<FaceType*> faces;
SortedFaces(mesh,v,faces);
for (int i=0;i<faces.size();i++)
@ -413,8 +617,8 @@ namespace vcg {
}
static bool LoadFIELD(MeshType *mesh,
const char *path_vfield,
bool per_vertex=false)
const char *path_vfield,
bool per_vertex=false)
{
FILE *f = fopen(path_vfield,"rt");
if (!f) {

View File

@ -27,40 +27,105 @@
namespace vcg {
namespace tri{
///calculate the BBox in UV space
template <class MeshType>
vcg::Box2<typename MeshType::ScalarType> PerWedgeUVBox(MeshType &m)
class UV_Utils
{
vcg::Box2<typename MeshType::ScalarType> 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<ScalarType> UVCoordType;
public:
///calculate the BBox in UV space
static vcg::Box2<ScalarType> PerWedgeUVBox(MeshType &m)
{
if ((*fi).IsD()) continue;
for (int i=0;i<3;i++)
UVBox.Add((*fi).WT(i).P());
vcg::Box2<ScalarType> 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<ScalarType> PerVertUVBox(MeshType &m)
{
vcg::Box2<ScalarType> 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 <class FaceType>
vcg::Point2<typename FaceType::ScalarType> 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<ScalarType> baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0;
CoordType dir3d=bary3d+dir;
CoordType baryCoordsUV;
vcg::InterpolationParameters<FaceType,ScalarType>(f,dir3d,baryCoordsUV);
vcg::Point2<ScalarType> 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<FaceType,ScalarType>(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<ScalarType> 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<steps;s++)
{
std::vector<int> num(m.vert.size(),0);
std::vector<UVCoordType> 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<m.vert.size();i++)
{
if ((fix_borders)&&(m.vert[i].IsB()))continue;
m.vert[i].T().P()=UVpos[i]/(ScalarType)num[i];
}
}
}
};
} //End Namespace Tri
} // End Namespace vcg
#endif