2011-10-05 18:17:40 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* VCGLib o o *
|
|
|
|
* Visual and Computer Graphics Library o o *
|
|
|
|
* _ O _ *
|
|
|
|
* Copyright(C) 2004 \/)\/ *
|
|
|
|
* Visual Computing Lab /\/| *
|
|
|
|
* ISTI - Italian National Research Council | *
|
|
|
|
* \ *
|
|
|
|
* All rights reserved. *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
|
|
* for more details. *
|
|
|
|
* *
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef VCG_TANGENT_FIELD_OPERATORS
|
|
|
|
#define VCG_TANGENT_FIELD_OPERATORS
|
|
|
|
|
|
|
|
namespace vcg {
|
|
|
|
namespace tri{
|
2012-01-23 14:09:38 +01:00
|
|
|
|
2011-10-05 18:17:40 +02:00
|
|
|
template <class MeshType>
|
|
|
|
class CrossField
|
|
|
|
{
|
|
|
|
typedef typename MeshType::FaceType FaceType;
|
|
|
|
typedef typename MeshType::VertexType VertexType;
|
|
|
|
typedef typename MeshType::CoordType CoordType;
|
|
|
|
typedef typename MeshType::ScalarType ScalarType;
|
|
|
|
typedef typename MeshType::PerFaceAttributeHandle<CoordType> PerFaceAttributeHandle;
|
|
|
|
|
|
|
|
private:
|
|
|
|
static ScalarType Sign(ScalarType a){return (ScalarType)((a>0)?+1:-1);}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
///fird a tranformation matrix to transform
|
|
|
|
///the 3D space to 2D tangent space specified
|
|
|
|
///by the cross field (where Z=0)
|
2012-01-23 14:09:38 +01:00
|
|
|
static vcg::Matrix33<ScalarType> TransformationMatrix(MeshType &mesh,const FaceType &f)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
|
|
|
typedef typename FaceType::CoordType CoordType;
|
|
|
|
typedef typename FaceType::ScalarType ScalarType;
|
|
|
|
|
|
|
|
bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0");
|
|
|
|
assert(CrossDir0);
|
2012-01-23 14:09:38 +01:00
|
|
|
PerFaceAttributeHandle Fh0= vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
///transform to 3d
|
|
|
|
CoordType axis0=Fh0[&f];
|
2012-01-23 14:09:38 +01:00
|
|
|
CoordType axis1=axis0^f.cN();
|
|
|
|
CoordType axis2=f.cN();
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
vcg::Matrix33<ScalarType> Trans;
|
|
|
|
|
|
|
|
///it must have right orientation cause of normal
|
|
|
|
Trans[0][0]=axis0[0];
|
|
|
|
Trans[0][1]=axis0[1];
|
|
|
|
Trans[0][2]=axis0[2];
|
|
|
|
Trans[1][0]=axis1[0];
|
|
|
|
Trans[1][1]=axis1[1];
|
|
|
|
Trans[1][2]=axis1[2];
|
|
|
|
Trans[2][0]=axis2[0];
|
|
|
|
Trans[2][1]=axis2[1];
|
|
|
|
Trans[2][2]=axis2[2];
|
|
|
|
|
|
|
|
/////then find the inverse
|
2012-01-23 14:09:38 +01:00
|
|
|
return (Trans);
|
2011-10-05 18:17:40 +02:00
|
|
|
//f.InvTrans=Inverse(f.Trans);
|
|
|
|
}
|
|
|
|
|
|
|
|
///transform a given angle from UV (wrt the cross field)
|
|
|
|
///to a 3D direction
|
|
|
|
static CoordType AngleToVect(const FaceType &f,const ScalarType &angle)
|
|
|
|
{
|
|
|
|
///find 2D vector
|
|
|
|
vcg::Point2<ScalarType> axis2D=vcg::Point2<ScalarType>(cos(angle),sin(angle));
|
|
|
|
CoordType axis3D=CoordType(axis2D.X(),axis2D.Y(),0);
|
|
|
|
vcg::Matrix33<ScalarType> Trans=TransformationMatrix(f);
|
|
|
|
vcg::Matrix33<ScalarType> InvTrans=Inverse(Trans);
|
|
|
|
///then transform
|
|
|
|
return (InvTrans*axis3D);
|
|
|
|
}
|
|
|
|
|
|
|
|
///find an angle with respect to a given face by a given vector
|
|
|
|
///in 3D space, it must be projected and normalized with respect to face's normal
|
2012-01-23 14:09:38 +01:00
|
|
|
static ScalarType VectToAngle(MeshType &mesh,const FaceType &f,const CoordType &vect3D)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
vcg::Matrix33<ScalarType> Trans=TransformationMatrix(mesh,f);
|
2011-10-05 18:17:40 +02:00
|
|
|
///trensform the vector to the reference frame by rotating it
|
|
|
|
CoordType vect_transf=Trans*vect3D;
|
|
|
|
|
|
|
|
///then put to zero to the Z coordinate
|
|
|
|
vcg::Point2<ScalarType> axis2D=vcg::Point2<ScalarType>(vect_transf.X(),vect_transf.Y());
|
|
|
|
axis2D.Normalize();
|
|
|
|
|
|
|
|
///then find the angle with respact to axis 0
|
|
|
|
ScalarType alpha=atan2(axis2D.Y(),axis2D.X()); ////to sum up M_PI?
|
|
|
|
if (alpha<0)
|
|
|
|
alpha=(2*M_PI+alpha);
|
|
|
|
if (alpha<0)
|
|
|
|
alpha=0;
|
|
|
|
return alpha;
|
|
|
|
}
|
2012-01-23 14:09:38 +01:00
|
|
|
|
2011-11-01 19:41:54 +01:00
|
|
|
///return the direction of the cross field in 3D
|
|
|
|
///given a first direction
|
|
|
|
static void CrossVector(const CoordType &dir0,
|
2012-01-23 14:09:38 +01:00
|
|
|
const CoordType &norm,
|
|
|
|
CoordType axis[4])
|
2011-11-01 19:41:54 +01:00
|
|
|
{
|
|
|
|
axis[0]=dir0;
|
|
|
|
axis[1]=norm^axis[0];
|
|
|
|
axis[2]=-axis[0];
|
|
|
|
axis[3]=-axis[1];
|
|
|
|
}
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
///return the direction of the cross field in 3D
|
|
|
|
static void CrossVector(MeshType &mesh,
|
|
|
|
const FaceType &f,
|
|
|
|
CoordType axis[4])
|
|
|
|
{
|
|
|
|
bool CrossDir0 = vcg::tri::HasPerFaceAttribute(mesh,"CrossDir0");
|
|
|
|
assert(CrossDir0);
|
|
|
|
MeshType::PerFaceAttributeHandle<CoordType> Fh0=
|
|
|
|
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir0"));
|
2011-11-01 19:41:54 +01:00
|
|
|
CoordType dir0=Fh0[&f];
|
|
|
|
CrossVector(dir0,f.cN(),axis);
|
2011-10-05 18:17:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///return a specific direction given an integer 0..3
|
|
|
|
///considering the reference direction of the cross field
|
2011-10-19 11:02:27 +02:00
|
|
|
static CoordType CrossVector(MeshType &mesh,
|
2012-01-23 14:09:38 +01:00
|
|
|
const FaceType &f,
|
|
|
|
const int &index)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
2011-10-19 11:02:27 +02:00
|
|
|
assert((index>=0)&&(index<4));
|
2011-10-05 18:17:40 +02:00
|
|
|
CoordType axis[4];
|
2011-10-19 11:02:27 +02:00
|
|
|
CrossVector(mesh,f,axis);
|
2011-10-05 18:17:40 +02:00
|
|
|
return axis[index];
|
|
|
|
}
|
2012-01-23 14:09:38 +01:00
|
|
|
|
|
|
|
///return the direction of the cross field in 3D
|
|
|
|
static void SetCrossVector(MeshType &mesh,
|
|
|
|
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"));
|
|
|
|
MeshType::PerFaceAttributeHandle<CoordType> Fh1=
|
|
|
|
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(mesh,std::string("CrossDir1"));
|
|
|
|
Fh0[f]=dir0;
|
|
|
|
Fh1[f]=dir1;
|
|
|
|
}
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
///rotate a given vector from a face to another
|
|
|
|
///vector is expressend in 3d coordinates
|
2012-01-23 14:09:38 +01:00
|
|
|
static CoordType Rotate(const FaceType &f0,const FaceType &f1,const CoordType &dir3D)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
|
|
|
CoordType N0=f0.cN();
|
|
|
|
CoordType N1=f1.cN();
|
|
|
|
|
|
|
|
///find the rotation matrix that maps between normals
|
|
|
|
vcg::Matrix33<ScalarType> rotation=vcg::RotationMatrix(N0,N1);
|
|
|
|
CoordType rotated=rotation*dir3D;
|
|
|
|
return rotated;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns the 90 deg rotation of a (around n) most similar to target b
|
|
|
|
static CoordType K_PI(const CoordType &a, const CoordType &b, const CoordType &n)
|
|
|
|
{
|
|
|
|
CoordType c = (a^n).normalized();
|
|
|
|
ScalarType scorea = a*b;
|
|
|
|
ScalarType scorec = c*b;
|
|
|
|
if (fabs(scorea)>=fabs(scorec)) return a*Sign(scorea); else return c*Sign(scorec);
|
|
|
|
}
|
|
|
|
|
|
|
|
///interpolate cross field with barycentric coordinates
|
|
|
|
static CoordType InterpolateCrossField(const CoordType &t0,
|
2012-01-23 14:09:38 +01:00
|
|
|
const CoordType &t1,
|
|
|
|
const CoordType &t2,
|
|
|
|
const CoordType &n,
|
|
|
|
const CoordType &bary)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
|
|
|
CoordType trans0=t0;
|
|
|
|
CoordType trans1=K_PI(t1,t0,n);
|
|
|
|
CoordType trans2=K_PI(t2,t0,n);
|
|
|
|
CoordType sum = trans0*bary.X() + trans1 * bary.Y() + trans2 * bary.Z();
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
///interpolate cross field with barycentric coordinates using normalized weights
|
|
|
|
static typename typename CoordType InterpolateCrossField(const std::vector<CoordType> &TangVect,
|
|
|
|
const std::vector<ScalarType> &Weight,
|
|
|
|
const std::vector<CoordType> &Norms,
|
|
|
|
const typename CoordType &BaseNorm,
|
|
|
|
const typename CoordType &BaseDir)
|
|
|
|
{
|
|
|
|
typedef typename FaceType::CoordType CoordType;
|
|
|
|
typedef typename FaceType::ScalarType ScalarType;
|
|
|
|
|
|
|
|
CoordType sum = CoordType(0,0,0);
|
|
|
|
for (int i=0;i<TangVect.size();i++)
|
|
|
|
{
|
|
|
|
CoordType N1=Norms[i];
|
|
|
|
///find the rotation matrix that maps between normals
|
|
|
|
vcg::Matrix33<ScalarType> rotation=vcg::RotationMatrix(N1,BaseNorm);
|
|
|
|
CoordType rotated=rotation*TangVect[i];
|
|
|
|
CoordType Tdir=K_PI(rotated,BaseDir,BaseNorm);
|
|
|
|
Tdir.Normalize();
|
|
|
|
sum+=(Tdir*Weight[i]);
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
sum.Normalize();
|
2011-10-05 18:17:40 +02:00
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
2011-10-19 11:02:27 +02:00
|
|
|
/*///interpolate cross field with barycentric coordinates
|
2011-10-05 18:17:40 +02:00
|
|
|
template <class FaceType>
|
|
|
|
typename FaceType::CoordType InterpolateCrossField(const typename FaceType::CoordType &t0,
|
2012-01-23 14:09:38 +01:00
|
|
|
const typename FaceType::CoordType &t1,
|
|
|
|
const typename FaceType::CoordType &n,
|
|
|
|
const typename FaceType::ScalarType &weight)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
CoordType trans0=t0;
|
|
|
|
CoordType trans1=K_PI(t1,t0,n);
|
|
|
|
CoordType sum = t0*weight + MyCross::V( t1, t0, n ) * (1.0-weight);
|
|
|
|
return sum;
|
2011-10-19 11:02:27 +02:00
|
|
|
}*/
|
2012-01-23 14:09:38 +01:00
|
|
|
|
|
|
|
|
2011-10-19 11:02:27 +02:00
|
|
|
///return the difference of two cross field, values between [0,0.5]
|
|
|
|
template <class FaceType>
|
|
|
|
typename FaceType::ScalarType DifferenceCrossField(const typename FaceType::CoordType &t0,
|
|
|
|
const typename FaceType::CoordType &t1,
|
|
|
|
const typename FaceType::CoordType &n)
|
|
|
|
{
|
|
|
|
CoordType trans0=t0;
|
|
|
|
CoordType trans1=K_PI(t1,t0,n);
|
|
|
|
ScalarType diff = 1-fabs(trans0*trans1);
|
|
|
|
return diff;
|
2011-10-05 18:17:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///compute the mismatch between 2 faces
|
2012-01-23 14:09:38 +01:00
|
|
|
static int MissMatch(MeshType &mesh,
|
|
|
|
const FaceType &f0,
|
|
|
|
const FaceType &f1)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
CoordType dir0=CrossVector(mesh,f0,0);
|
|
|
|
CoordType dir1=CrossVector(mesh,f1,0);
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
CoordType dir1Rot=Rotate(f1,f0,dir1);
|
|
|
|
dir1Rot.Normalize();
|
|
|
|
|
2012-01-23 14:09:38 +01:00
|
|
|
ScalarType angle_diff=VectToAngle(mesh,f0,dir1Rot);
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
ScalarType step=M_PI/2.0;
|
|
|
|
int i=(int)floor((angle_diff/step)+0.5);
|
2012-01-23 14:09:38 +01:00
|
|
|
int k=0;
|
2011-10-05 18:17:40 +02:00
|
|
|
if (i>=0)
|
|
|
|
k=i%4;
|
|
|
|
else
|
|
|
|
k=(-(3*i))%4;
|
|
|
|
return k;
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
|
2012-01-23 14:09:38 +01:00
|
|
|
static void SortedFaces(MeshType &mesh,
|
|
|
|
VertexType &v,
|
|
|
|
std::vector<FaceType*> &faces)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
|
|
|
typedef typename VertexType::FaceType FaceType;
|
2012-01-23 14:09:38 +01:00
|
|
|
|
|
|
|
///check that is not on border..
|
|
|
|
assert (!v.IsB());
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
///get first face sharing the edge
|
|
|
|
FaceType *f_init=v.VFp();
|
|
|
|
int edge_init=v.VFi();
|
|
|
|
|
|
|
|
///and initialize the pos
|
|
|
|
vcg::face::Pos<FaceType> VFI(f_init,edge_init);
|
|
|
|
bool complete_turn=false;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
FaceType *curr_f=VFI.F();
|
2012-01-23 14:09:38 +01:00
|
|
|
faces.push_back(curr_f);
|
|
|
|
|
2011-10-05 18:17:40 +02:00
|
|
|
int curr_edge=VFI.E();
|
|
|
|
|
|
|
|
///assert that is not a border edge
|
|
|
|
assert(curr_f->FFp(curr_edge)!=curr_f);
|
|
|
|
|
2012-01-23 14:09:38 +01:00
|
|
|
/*///find the current missmatch
|
|
|
|
missmatch+=(curr_f,const FaceType &f1);*/
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
///continue moving
|
|
|
|
VFI.FlipF();
|
|
|
|
VFI.FlipE();
|
|
|
|
|
|
|
|
FaceType *next_f=VFI.F();
|
2012-01-23 14:09:38 +01:00
|
|
|
|
2011-10-05 18:17:40 +02:00
|
|
|
///test if I've finiseh with the face exploration
|
|
|
|
complete_turn=(next_f==f_init);
|
|
|
|
/// or if I've just crossed a mismatch
|
|
|
|
}while (!complete_turn);
|
|
|
|
}
|
2012-01-23 14:09:38 +01:00
|
|
|
|
|
|
|
/////this function return true if a
|
|
|
|
/////given vertex is a singular vertex by
|
|
|
|
/////moving around i n a roder wai and accounting for
|
|
|
|
/////missmatches.. it requires VF topology
|
|
|
|
/////this function return true if a
|
|
|
|
/////given vertex is a singular vertex by
|
|
|
|
/////moving around i n a roder wai and accounting for
|
|
|
|
/////missmatches
|
|
|
|
//static bool IsSingular(MeshType &mesh,
|
|
|
|
// VertexType &v,
|
|
|
|
// int &missmatch)
|
|
|
|
//{
|
|
|
|
// typedef typename VertexType::FaceType FaceType;
|
|
|
|
// ///check that is on border..
|
|
|
|
// if (v.IsB())
|
|
|
|
// return false;
|
|
|
|
|
|
|
|
// ///get first face sharing the edge
|
|
|
|
// FaceType *f_init=v.VFp();
|
|
|
|
// int edge_init=v.VFi();
|
|
|
|
|
|
|
|
// //int missmatch=0;
|
|
|
|
// missmatch=0;
|
|
|
|
// ///and initialize the pos
|
|
|
|
// vcg::face::Pos<FaceType> VFI(f_init,edge_init);
|
|
|
|
// bool complete_turn=false;
|
|
|
|
// do
|
|
|
|
// {
|
|
|
|
// FaceType *curr_f=VFI.F();
|
|
|
|
// int curr_edge=VFI.E();
|
|
|
|
|
|
|
|
// ///assert that is not a border edge
|
|
|
|
// assert(curr_f->FFp(curr_edge)!=curr_f);
|
|
|
|
|
|
|
|
// /*///find the current missmatch
|
|
|
|
// missmatch+=(curr_f,const FaceType &f1);*/
|
|
|
|
|
|
|
|
// ///continue moving
|
|
|
|
// VFI.FlipF();
|
|
|
|
// VFI.FlipE();
|
|
|
|
|
|
|
|
// FaceType *next_f=VFI.F();
|
|
|
|
//
|
|
|
|
// ///find the current missmatch
|
|
|
|
// missmatch+=MissMatch(mesh,*curr_f,*next_f);
|
|
|
|
|
|
|
|
// ///test if I've finiseh with the face exploration
|
|
|
|
// complete_turn=(next_f==f_init);
|
|
|
|
// /// or if I've just crossed a mismatch
|
|
|
|
// }while (!complete_turn);
|
|
|
|
// missmatch=missmatch%4;
|
|
|
|
// return(missmatch!=0);
|
|
|
|
//}
|
|
|
|
|
|
|
|
static int SimilarDir(CoordType dir[4],
|
|
|
|
CoordType TestD)
|
2011-10-05 18:17:40 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
int ret=-1;
|
|
|
|
ScalarType maxAcc=-1;
|
|
|
|
for (int i=0;i<4;i++)
|
|
|
|
{
|
|
|
|
ScalarType testAcc=fabs(dir[i]*TestD);
|
|
|
|
if (testAcc>maxAcc)
|
|
|
|
{
|
|
|
|
maxAcc=testAcc;
|
|
|
|
ret=i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(ret!=-1);
|
|
|
|
return ret;
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
|
2012-01-23 14:09:38 +01:00
|
|
|
static bool IsSingular(MeshType &mesh,
|
|
|
|
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);
|
2011-10-19 11:02:27 +02:00
|
|
|
for (int i=0;i<faces.size();i++)
|
2012-01-23 14:09:38 +01:00
|
|
|
{
|
|
|
|
FaceType *curr_f=faces[i];
|
|
|
|
FaceType *next_f=faces[(i+1)%faces.size()];
|
|
|
|
|
|
|
|
///find the current missmatch
|
|
|
|
missmatch+=MissMatch(mesh,*curr_f,*next_f);
|
|
|
|
|
|
|
|
}
|
|
|
|
missmatch=missmatch%4;
|
|
|
|
return(missmatch!=0);
|
2011-10-05 18:17:40 +02:00
|
|
|
}
|
|
|
|
|
2012-01-23 14:09:38 +01:00
|
|
|
static bool LoadFIELD(MeshType *mesh,
|
|
|
|
const char *path_vfield,
|
|
|
|
bool per_vertex=false)
|
2011-10-19 11:02:27 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
FILE *f = fopen(path_vfield,"rt");
|
|
|
|
if (!f) {
|
|
|
|
//if (errorMsg) sprintf(errorMsg,"Cannot Open File :(");
|
|
|
|
return false;
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
{
|
2012-01-23 14:09:38 +01:00
|
|
|
char word[512]; word[0]=0;
|
|
|
|
fscanf(f,"%s",word);
|
|
|
|
char c=0;
|
|
|
|
if (word[0]=='#') {
|
|
|
|
// skip comment line
|
|
|
|
while (fscanf(f,"%c",&c)!=EOF) if (c=='\n') break;
|
|
|
|
} else {
|
|
|
|
//if (errorMsg) sprintf(errorMsg,"The VField file should start with a comment");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
int nnv = -1;
|
|
|
|
if (fscanf(f,"%d",&nnv)!=1) {
|
|
|
|
// number of vertices not read. Skip another line (ffield file?) and try again.
|
|
|
|
while (fscanf(f,"%c",&c)!=EOF) if (c=='\n') break; // skip
|
|
|
|
fscanf(f,"%d",&nnv);
|
|
|
|
}
|
|
|
|
int targetnum=mesh->fn;
|
|
|
|
if (per_vertex)
|
|
|
|
targetnum=mesh->vn;
|
|
|
|
if (nnv != (int)targetnum)
|
|
|
|
{
|
|
|
|
//if (errorMsg) sprintf(errorMsg,"Wrong element number. Found: %d. Expected: %d.",nnv,mesh->vn);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (fscanf(f,"%c",&c)!=EOF) if (c=='\n') break; // skip
|
|
|
|
// skip strange string line
|
|
|
|
while (fscanf(f,"%c",&c)!=EOF) if (c=='\n') break;
|
|
|
|
for (int i=0; i<nnv; i++){
|
|
|
|
vcg::Point3d u,v;
|
|
|
|
int a,b;
|
|
|
|
if (fscanf(f,
|
|
|
|
"%d %d %lf %lf %lf %lf %lf %lf",
|
|
|
|
&a,&b,
|
|
|
|
&(v.X()),&(v.Y()),&(v.Z()),
|
|
|
|
&(u.X()),&(u.Y()),&(u.Z())
|
|
|
|
)!=8) {
|
|
|
|
//if (errorMsg) sprintf(errorMsg,"Format error reading vertex n. %d",i);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
//node[i]->TF().Import(u);
|
|
|
|
if (per_vertex)
|
|
|
|
{
|
|
|
|
mesh->vert[i].PD1()=u;
|
|
|
|
mesh->vert[i].PD2()=v;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FaceType *f=&mesh->face[i];
|
|
|
|
SetCrossVector(*mesh,*f,u,v);
|
|
|
|
}
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
}
|
2012-01-23 14:09:38 +01:00
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*void GetWeights(TriMeshType *mesh,
|
|
|
|
const std::vector<FaceType*> &faces,
|
|
|
|
std::vector<ScalarType> &weights)
|
|
|
|
{
|
|
|
|
weights.clear();
|
|
|
|
MeshType::PerFaceAttributeHandle<ScalarType> Fh0 FHRVal=
|
|
|
|
vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<ScalarType>(mesh,std::string("CrossVal"));
|
|
|
|
|
|
|
|
for (int i=0;i<faces.size();i++)
|
|
|
|
weights.push_back(FHRVal[faces[i]]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetTangDir(TriMeshType *mesh,
|
|
|
|
const std::vector<FaceType*> &faces,
|
|
|
|
std::vector<CoordType> &dir0,
|
|
|
|
std::vector<CoordType> &dir1)
|
|
|
|
{
|
|
|
|
dir0.clear();
|
|
|
|
dir1.clear();
|
|
|
|
MeshType::PerFaceAttributeHandle<CoordType> FHDir0=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(test_mesh,std::string("CrossDir0"));
|
|
|
|
MeshType::PerFaceAttributeHandle<CoordType> FHDir1=vcg::tri::Allocator<MeshType>::GetPerFaceAttribute<CoordType>(test_mesh,std::string("CrossDir1"));
|
|
|
|
for (int i=0;i<faces.size();i++)
|
|
|
|
{
|
|
|
|
dir0.push_back(FHDir0[faces[i]]);
|
|
|
|
dir1.push_back(FHDir1[faces[i]]);
|
|
|
|
}
|
2011-10-19 11:02:27 +02:00
|
|
|
}*/
|
2011-10-05 18:17:40 +02:00
|
|
|
|
|
|
|
};///end class
|
|
|
|
} //End Namespace Tri
|
|
|
|
} // End Namespace vcg
|
|
|
|
#endif
|