You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
13 KiB
385 lines
13 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2016 \/)\/ * |
|
* 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 __VCGLIB_IMPORTERFIELD |
|
#define __VCGLIB_IMPORTERFIELD |
|
#include <vcg/complex/algorithms/parametrization/tangent_field_operators.h> |
|
|
|
namespace vcg { |
|
namespace tri { |
|
namespace io { |
|
|
|
/** |
|
This class encapsulate a filter for opening field formats |
|
*/ |
|
template <class MeshType> |
|
class ImporterFIELD |
|
{ |
|
typedef typename MeshType::ScalarType ScalarType; |
|
typedef typename MeshType::FaceType FaceType; |
|
typedef typename MeshType::VertexType VertexType; |
|
typedef typename MeshType::CoordType CoordType; |
|
|
|
public: |
|
|
|
static bool LoadGrad(MeshType &mesh, |
|
const char *path) |
|
{ |
|
FILE *f = fopen(path,"rt"); |
|
if (!f) |
|
{ |
|
return false; |
|
} |
|
int numF; |
|
fscanf(f,"%d\n",&numF); |
|
assert(numF==mesh.fn); |
|
char skipstr[200]; |
|
//int readed0; |
|
for (int i=0;i<9;i++) |
|
fscanf(f,"%s",&skipstr[0]); |
|
|
|
for (int i=0;i<mesh.fn;i++) |
|
{ |
|
int i0=-1; |
|
int i1=-1; |
|
int i2=-1; |
|
double u0,v0,u1,v1,u2,v2; |
|
int readed1=fscanf(f,"%d %d %d %lf %lf %lf %lf %lf %lf",&i0,&i1,&i2,&u0,&v0,&u1,&v1,&u2,&v2); |
|
assert(readed1==9); |
|
vcg::Point2<ScalarType> UV[3]; |
|
UV[0]= vcg::Point2<ScalarType>(u0,v0); |
|
UV[1]= vcg::Point2<ScalarType>(u1,v1); |
|
UV[2]= vcg::Point2<ScalarType>(u2,v2); |
|
CoordType dir1; |
|
CoordType dir2; |
|
vcg::tri::CrossField<MeshType>::GradientToCross(mesh.face[i],UV[0],UV[1],UV[2],dir1,dir2); |
|
dir1.Normalize(); |
|
dir2.Normalize(); |
|
mesh.face[i].PD1()=dir1; |
|
mesh.face[i].PD2()=dir2; |
|
} |
|
fclose(f); |
|
return true; |
|
} |
|
|
|
static bool LoadNDF(MeshType &mesh, |
|
const char *path) |
|
{ |
|
FILE *f = fopen(path,"rt"); |
|
if (!f) |
|
{ |
|
fflush(stdout); |
|
return false; |
|
} |
|
|
|
char skipstr[200]; |
|
//int readed0; |
|
do{ |
|
|
|
fscanf(f,"%s\n",&skipstr[0]); |
|
printf("%s\n",skipstr); |
|
}while(strcmp(skipstr,"[Pjumps]")!=0); |
|
|
|
// fscanf(f,"%s\"",skipstr); |
|
// printf("%s\n",skipstr); |
|
fseek(f, 7, SEEK_CUR); |
|
char final[1]; |
|
do{ |
|
int period; |
|
fscanf(f,"%d;",&period); |
|
printf("%d\n",period); |
|
fscanf(f,"%c",&final); |
|
fseek(f, -1, SEEK_CUR); |
|
//printf("%s\n",&final[0]); |
|
}while(strcmp(final,"\"")!=0); |
|
|
|
// printf("%s\n",skipstr); |
|
fflush(stdout); |
|
for (int i=0;i<mesh.fn;i++) |
|
{ |
|
int i0=-1; |
|
int i1=-1; |
|
int i2=-1; |
|
double u0,v0,u1,v1,u2,v2; |
|
int readed1=fscanf(f,"%d %d %d %lf %lf %lf %lf %lf %lf",&i0,&i1,&i2,&u0,&v0,&u1,&v1,&u2,&v2); |
|
assert(readed1==9); |
|
vcg::Point2<ScalarType> UV[3]; |
|
UV[0]= vcg::Point2<ScalarType>(u0,v0); |
|
UV[1]= vcg::Point2<ScalarType>(u1,v1); |
|
UV[2]= vcg::Point2<ScalarType>(u2,v2); |
|
CoordType dir1; |
|
CoordType dir2; |
|
vcg::tri::CrossField<MeshType>::GradientToCross(mesh.face[i],UV[0],UV[1],UV[2],dir1,dir2); |
|
dir1.Normalize(); |
|
dir2.Normalize(); |
|
mesh.face[i].PD1()=dir1; |
|
mesh.face[i].PD2()=dir2; |
|
} |
|
fclose(f); |
|
return true; |
|
} |
|
|
|
///load a field on the mesh, it could be a vfield file (per vertex) |
|
///or an ffield file (per face) |
|
static bool LoadFFIELD(MeshType &mesh, |
|
const char *path, |
|
bool per_vertex=false) |
|
{ |
|
|
|
FILE *f = fopen(path,"rt"); |
|
if (!f) |
|
{ |
|
return false; |
|
} |
|
{ |
|
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 |
|
{ |
|
return false; |
|
} |
|
while (fscanf(f,"%c",&c)!=EOF) if (c=='\n') break; |
|
int nnv = -1; |
|
if (fscanf(f,"%d",&nnv)!=1) |
|
{ |
|
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; |
|
} |
|
|
|
if( per_vertex && !HasPerVertexCurvatureDir(mesh)) throw vcg::MissingComponentException("PerVertexCurvatureDir"); |
|
if(!per_vertex && !HasPerFaceCurvatureDir(mesh)) throw vcg::MissingComponentException("PerFaceCurvatureDir"); |
|
|
|
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::Point3<float> u,v; |
|
float a,b; |
|
if (fscanf(f, |
|
"%f %f %f %f %f %f %f %f", |
|
&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; |
|
} |
|
|
|
u.Normalize(); |
|
v.Normalize(); |
|
|
|
if (per_vertex) |
|
{ |
|
mesh.vert[i].PD1().Import(u); |
|
mesh.vert[i].PD2().Import(v); |
|
} |
|
else |
|
{ |
|
mesh.face[i].PD1().Import(u); |
|
mesh.face[i].PD2().Import(v); |
|
} |
|
} |
|
} |
|
fclose(f); |
|
return true; |
|
} |
|
|
|
///Load a 4 rosy format file as used by |
|
///Interactive Visualization of Rotational Symmetry Fields on Surfaces |
|
///Jonathan Palacios and Eugene Zhang |
|
static bool Load4ROSY(MeshType &mesh, |
|
const char *path) |
|
{ |
|
FILE *f = fopen(path,"rt"); |
|
if (!f) |
|
{ |
|
return false; |
|
} |
|
int num,symm; |
|
fscanf(f,"%d",&num); |
|
assert(num==mesh.fn); |
|
fscanf(f,"%d\n",&symm); |
|
assert(symm==4); |
|
for (int i=0;i<num;i++) |
|
{ |
|
float dirX,dirY,dirZ; |
|
fscanf(f,"%f %f %f \n",&dirX,&dirY,&dirZ); |
|
mesh.face[i].PD1()=CoordType(dirX,dirY,dirZ); |
|
mesh.face[i].PD2()=mesh.face[i].PD1()^mesh.face[i].N(); |
|
mesh.face[i].PD1().Normalize(); |
|
mesh.face[i].PD2().Normalize(); |
|
} |
|
fclose(f); |
|
return true; |
|
} |
|
|
|
|
|
static bool LoadSeamsMMFromOBJ(MeshType &mesh,std::string PathOBJ) |
|
{ |
|
///per face per edge of mmatch in the solver |
|
typename MeshType::template PerFaceAttributeHandle<vcg::Point3i> Handle_MMatch; |
|
///seam per face |
|
typename MeshType::template PerFaceAttributeHandle<vcg::Point3<bool> > Handle_Seams; |
|
|
|
bool HasHandleMMatch=vcg::tri::HasPerFaceAttribute(mesh,std::string("MissMatch")); |
|
if (!HasHandleMMatch) |
|
Handle_MMatch = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<vcg::Point3i>(mesh,std::string("MissMatch")); |
|
else |
|
Handle_MMatch = vcg::tri::Allocator<MeshType>::template FindPerFaceAttribute<vcg::Point3i>(mesh,std::string("MissMatch")); |
|
|
|
bool HasHandleSeams=vcg::tri::HasPerFaceAttribute(mesh,std::string("Seams")); |
|
if (!HasHandleSeams) |
|
Handle_Seams=vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<vcg::Point3<bool> >(mesh,std::string("Seams")); |
|
else |
|
Handle_Seams=vcg::tri::Allocator<MeshType>::template FindPerFaceAttribute<vcg::Point3<bool> >(mesh,std::string("Seams")); |
|
|
|
FILE *f = fopen(PathOBJ.c_str(),"rt"); |
|
if (!f) |
|
return false; |
|
|
|
for (unsigned int i=0;i<mesh.face.size();i++) |
|
{ |
|
for (int j=0;j<3;j++) |
|
{ |
|
Handle_Seams[i][j]=false; |
|
Handle_MMatch[i][j]=0; |
|
} |
|
} |
|
|
|
while (!feof(f)) |
|
{ |
|
|
|
int f_int,v_int,rot; |
|
int readed=fscanf(f,"sm %d %d %d\n",&f_int,&v_int,&rot); |
|
///skip lines |
|
if (readed==0) |
|
{ |
|
char buff[200]; |
|
fscanf(f,"%s\n",&buff[0]); |
|
} |
|
else ///add the actual seams |
|
{ |
|
VertexType *v=&mesh.vert[v_int-1]; |
|
FaceType *f0=&mesh.face[f_int-1]; |
|
int e0=-1; |
|
if (f0->V(0)==v)e0=0; |
|
if (f0->V(1)==v)e0=1; |
|
if (f0->V(2)==v)e0=2; |
|
e0=(e0+2)%3; |
|
assert(e0!=-1); |
|
FaceType *f1; |
|
int e1; |
|
f1=f0->FFp(e0); |
|
e1=f0->FFi(e0); |
|
Handle_Seams[f0][e0]=true; |
|
Handle_Seams[f1][e1]=true; |
|
|
|
Handle_MMatch[f0][e0]=rot; |
|
int rot1; |
|
if (rot==0)rot1=0; |
|
if (rot==1)rot1=3; |
|
if (rot==2)rot1=2; |
|
if (rot==3)rot1=1; |
|
Handle_MMatch[f1][e1]=rot1; |
|
} |
|
} |
|
//printf("NEED %d LINES\n",i); |
|
return true; |
|
} |
|
|
|
|
|
//Load a 4 rosy format file as pair of angles |
|
static bool Load2AngleFace(MeshType &mesh, |
|
const char *path) |
|
{ |
|
FILE *f = fopen(path,"rt"); |
|
if (f==NULL)return false; |
|
int num; |
|
fscanf(f,"#%d param_field\n",&num); |
|
if (num!=mesh.face.size())return false; |
|
for (unsigned int i=0;i<mesh.face.size();i++) |
|
{ |
|
float alpha1,alpha2; |
|
int index; |
|
fscanf(f,"%d %f %f \n",&index,&alpha1,&alpha2); |
|
vcg::tri::CrossField<MeshType>::AnglesToCrossField(mesh.face[i],(ScalarType)alpha1,(ScalarType)alpha2,1); |
|
} |
|
fclose(f); |
|
return true; |
|
} |
|
|
|
static bool LoadCSVField(MeshType &mesh, |
|
const std::string &field_1, |
|
const std::string &field_2, |
|
bool Normalize=true) |
|
{ |
|
FILE *f1=NULL; |
|
FILE *f2=NULL; |
|
f1=fopen(field_1.c_str(),"rt"); |
|
if(f1==NULL)return false; |
|
f2=fopen(field_2.c_str(),"rt"); |
|
if(f2==NULL)return false; |
|
for (size_t i=0;i<mesh.face.size();i++) |
|
{ |
|
float Xdir,Ydir,Zdir; |
|
fscanf(f1,"%f,%f,%f\n",&Xdir,&Ydir,&Zdir); |
|
mesh.face[i].PD1()=CoordType(Xdir,Ydir,Zdir); |
|
//std::cout<<Xdir<<" "<<Ydir<<std::endl; |
|
fscanf(f2,"%f,%f,%f\n",&Xdir,&Ydir,&Zdir); |
|
mesh.face[i].PD2()=CoordType(Xdir,Ydir,Zdir); |
|
//set the quality as force Value |
|
if (Normalize) |
|
{ |
|
mesh.face[i].PD1().Normalize(); |
|
mesh.face[i].PD2().Normalize(); |
|
} |
|
} |
|
|
|
//then color by quality |
|
fclose(f1); |
|
fclose(f2); |
|
return true; |
|
} |
|
|
|
}; // end class |
|
|
|
|
|
|
|
} // end namespace tri |
|
} // end namespace io |
|
} // end namespace vcg |
|
|
|
#endif |
|
|
|
|