major changes
This commit is contained in:
parent
f97f54a89b
commit
5e7f95f94a
|
@ -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) {
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue