major changes
This commit is contained in:
parent
f97f54a89b
commit
5e7f95f94a
vcg/complex/algorithms/parametrization
|
@ -21,6 +21,9 @@
|
||||||
* *
|
* *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <vcg/math/histogram.h>
|
||||||
|
#include <vcg/complex/algorithms/update/curvature.h>
|
||||||
|
|
||||||
#ifndef VCG_TANGENT_FIELD_OPERATORS
|
#ifndef VCG_TANGENT_FIELD_OPERATORS
|
||||||
#define VCG_TANGENT_FIELD_OPERATORS
|
#define VCG_TANGENT_FIELD_OPERATORS
|
||||||
|
|
||||||
|
@ -39,7 +42,180 @@ namespace vcg {
|
||||||
private:
|
private:
|
||||||
static ScalarType Sign(ScalarType a){return (ScalarType)((a>0)?+1:-1);}
|
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:
|
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
|
///fird a tranformation matrix to transform
|
||||||
///the 3D space to 2D tangent space specified
|
///the 3D space to 2D tangent space specified
|
||||||
|
@ -146,21 +322,21 @@ namespace vcg {
|
||||||
CrossVector(mesh,f,axis);
|
CrossVector(mesh,f,axis);
|
||||||
return axis[index];
|
return axis[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
///return the direction of the cross field in 3D
|
///return the direction of the cross field in 3D
|
||||||
static void SetCrossVector(MeshType &mesh,
|
static void SetCrossVector(MeshType &mesh,
|
||||||
const FaceType &f,
|
const FaceType &f,
|
||||||
CoordType dir0,
|
CoordType dir0,
|
||||||
CoordType dir1)
|
CoordType dir1)
|
||||||
{
|
{
|
||||||
bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0");
|
bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0");
|
||||||
assert(CrossDir0);
|
assert(CrossDir0);
|
||||||
bool CrossDir1 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir1");
|
bool CrossDir1 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir1");
|
||||||
assert(CrossDir1);
|
assert(CrossDir1);
|
||||||
MeshType::PerFaceAttributeHandle<CoordType> Fh0=
|
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=
|
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;
|
Fh0[f]=dir0;
|
||||||
Fh1[f]=dir1;
|
Fh1[f]=dir1;
|
||||||
}
|
}
|
||||||
|
@ -189,14 +365,33 @@ namespace vcg {
|
||||||
|
|
||||||
///interpolate cross field with barycentric coordinates
|
///interpolate cross field with barycentric coordinates
|
||||||
static CoordType InterpolateCrossField(const CoordType &t0,
|
static CoordType InterpolateCrossField(const CoordType &t0,
|
||||||
const CoordType &t1,
|
const CoordType &t1,
|
||||||
const CoordType &t2,
|
const CoordType &t2,
|
||||||
const CoordType &n,
|
const CoordType &n0,
|
||||||
const CoordType &bary)
|
const CoordType &n1,
|
||||||
|
const CoordType &n2,
|
||||||
|
const CoordType &target_n,
|
||||||
|
const CoordType &bary)
|
||||||
{
|
{
|
||||||
CoordType trans0=t0;
|
vcg::Matrix33<ScalarType> R0=vcg::RotationMatrix(n0,target_n);
|
||||||
CoordType trans1=K_PI(t1,t0,n);
|
vcg::Matrix33<ScalarType> R1=vcg::RotationMatrix(n1,target_n);
|
||||||
CoordType trans2=K_PI(t2,t0,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();
|
CoordType sum = trans0*bary.X() + trans1 * bary.Y() + trans2 * bary.Z();
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
@ -226,18 +421,27 @@ namespace vcg {
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*///interpolate cross field with barycentric coordinates
|
///interpolate cross field with scalar weight
|
||||||
template <class FaceType>
|
static typename FaceType::CoordType InterpolateCrossFieldLine(const typename FaceType::CoordType &t0,
|
||||||
typename FaceType::CoordType InterpolateCrossField(const typename FaceType::CoordType &t0,
|
const typename FaceType::CoordType &t1,
|
||||||
const typename FaceType::CoordType &t1,
|
const typename FaceType::CoordType &n0,
|
||||||
const typename FaceType::CoordType &n,
|
const typename FaceType::CoordType &n1,
|
||||||
const typename FaceType::ScalarType &weight)
|
const typename FaceType::CoordType &target_n,
|
||||||
|
const typename FaceType::ScalarType &weight)
|
||||||
{
|
{
|
||||||
CoordType trans0=t0;
|
vcg::Matrix33<ScalarType> R0=vcg::RotationMatrix(n0,target_n);
|
||||||
CoordType trans1=K_PI(t1,t0,n);
|
vcg::Matrix33<ScalarType> R1=vcg::RotationMatrix(n1,target_n);
|
||||||
CoordType sum = t0*weight + MyCross::V( t1, t0, n ) * (1.0-weight);
|
CoordType trans0=R0*t0;
|
||||||
return sum;
|
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]
|
///return the difference of two cross field, values between [0,0.5]
|
||||||
|
@ -254,8 +458,8 @@ namespace vcg {
|
||||||
|
|
||||||
///compute the mismatch between 2 faces
|
///compute the mismatch between 2 faces
|
||||||
static int MissMatch(MeshType &mesh,
|
static int MissMatch(MeshType &mesh,
|
||||||
const FaceType &f0,
|
const FaceType &f0,
|
||||||
const FaceType &f1)
|
const FaceType &f1)
|
||||||
{
|
{
|
||||||
CoordType dir0=CrossVector(mesh,f0,0);
|
CoordType dir0=CrossVector(mesh,f0,0);
|
||||||
CoordType dir1=CrossVector(mesh,f1,0);
|
CoordType dir1=CrossVector(mesh,f1,0);
|
||||||
|
@ -274,10 +478,10 @@ namespace vcg {
|
||||||
k=(-(3*i))%4;
|
k=(-(3*i))%4;
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SortedFaces(MeshType &mesh,
|
static void SortedFaces(MeshType &mesh,
|
||||||
VertexType &v,
|
VertexType &v,
|
||||||
std::vector<FaceType*> &faces)
|
std::vector<FaceType*> &faces)
|
||||||
{
|
{
|
||||||
typedef typename VertexType::FaceType FaceType;
|
typedef typename VertexType::FaceType FaceType;
|
||||||
|
|
||||||
|
@ -309,7 +513,7 @@ namespace vcg {
|
||||||
VFI.FlipE();
|
VFI.FlipE();
|
||||||
|
|
||||||
FaceType *next_f=VFI.F();
|
FaceType *next_f=VFI.F();
|
||||||
|
|
||||||
///test if I've finiseh with the face exploration
|
///test if I've finiseh with the face exploration
|
||||||
complete_turn=(next_f==f_init);
|
complete_turn=(next_f==f_init);
|
||||||
/// or if I've just crossed a mismatch
|
/// or if I've just crossed a mismatch
|
||||||
|
@ -371,7 +575,7 @@ namespace vcg {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
static int SimilarDir(CoordType dir[4],
|
static int SimilarDir(CoordType dir[4],
|
||||||
CoordType TestD)
|
CoordType TestD)
|
||||||
{
|
{
|
||||||
int ret=-1;
|
int ret=-1;
|
||||||
ScalarType maxAcc=-1;
|
ScalarType maxAcc=-1;
|
||||||
|
@ -389,14 +593,14 @@ namespace vcg {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsSingular(MeshType &mesh,
|
static bool IsSingular(MeshType &mesh,
|
||||||
VertexType &v,
|
VertexType &v,
|
||||||
int &missmatch)
|
int &missmatch)
|
||||||
{
|
{
|
||||||
typedef typename VertexType::FaceType FaceType;
|
typedef typename VertexType::FaceType FaceType;
|
||||||
///check that is on border..
|
///check that is on border..
|
||||||
if (v.IsB())
|
if (v.IsB())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::vector<FaceType*> faces;
|
std::vector<FaceType*> faces;
|
||||||
SortedFaces(mesh,v,faces);
|
SortedFaces(mesh,v,faces);
|
||||||
for (int i=0;i<faces.size();i++)
|
for (int i=0;i<faces.size();i++)
|
||||||
|
@ -413,8 +617,8 @@ namespace vcg {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadFIELD(MeshType *mesh,
|
static bool LoadFIELD(MeshType *mesh,
|
||||||
const char *path_vfield,
|
const char *path_vfield,
|
||||||
bool per_vertex=false)
|
bool per_vertex=false)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(path_vfield,"rt");
|
FILE *f = fopen(path_vfield,"rt");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
|
|
@ -27,40 +27,105 @@
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri{
|
namespace tri{
|
||||||
|
|
||||||
///calculate the BBox in UV space
|
|
||||||
template <class MeshType>
|
template <class MeshType>
|
||||||
vcg::Box2<typename MeshType::ScalarType> PerWedgeUVBox(MeshType &m)
|
class UV_Utils
|
||||||
{
|
{
|
||||||
vcg::Box2<typename MeshType::ScalarType> UVBox;
|
typedef typename MeshType::ScalarType ScalarType;
|
||||||
typename MeshType::FaceIterator fi;
|
typedef typename MeshType::FaceType FaceType;
|
||||||
for (fi=m.face.begin();fi!=m.face.end();fi++)
|
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;
|
vcg::Box2<ScalarType> UVBox;
|
||||||
for (int i=0;i<3;i++)
|
FaceIterator fi;
|
||||||
UVBox.Add((*fi).WT(i).P());
|
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
|
///transform curvature to UV space
|
||||||
template <class FaceType>
|
static UVCoordType Coord3DtoUV(FaceType &f,const CoordType &dir)
|
||||||
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;
|
||||||
///then transform to UV
|
UVCoordType baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0;
|
||||||
CoordType bary3d=(f.P(0)+f.P(1)+f.P(2))/3.0;
|
CoordType dir3d=bary3d+dir;
|
||||||
vcg::Point2<ScalarType> baryUV=(f.WT(0).P()+f.WT(1).P()+f.WT(2).P())/3.0;
|
CoordType baryCoordsUV;
|
||||||
CoordType dir3d=bary3d+dir;
|
vcg::InterpolationParameters<FaceType,ScalarType>(f,dir3d,baryCoordsUV);
|
||||||
CoordType baryCoordsUV;
|
UVCoordType dirUV=baryCoordsUV.X()*f.WT(0).P()+
|
||||||
vcg::InterpolationParameters<FaceType,ScalarType>(f,dir3d,baryCoordsUV);
|
baryCoordsUV.Y()*f.WT(1).P()+
|
||||||
vcg::Point2<ScalarType> dirUV=baryCoordsUV.X()*f.WT(0).P()+
|
baryCoordsUV.Z()*f.WT(2).P()-baryUV;
|
||||||
baryCoordsUV.Y()*f.WT(1).P()+
|
dirUV.Normalize();
|
||||||
baryCoordsUV.Z()*f.WT(2).P()-baryUV;
|
return dirUV;
|
||||||
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
|
} // End Namespace vcg
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue