Updated the some of the importers to the double/float managmaent. Now by default ascii files are read as double and if necessary downcasted to float.

This commit is contained in:
Paolo Cignoni 2014-06-27 08:51:31 +00:00
parent 87e2599d27
commit c02fd854f7
3 changed files with 456 additions and 450 deletions

View File

@ -56,7 +56,8 @@ class ImporterNVM
public: public:
typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::VertexPointer VertexPointer;
typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::ScalarType ScalarType;
typedef typename OpenMeshType::CoordType CoordType;
typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::VertexType VertexType;
typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::FaceType FaceType;
typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::VertexIterator VertexIterator;
@ -76,20 +77,20 @@ static void readline(FILE *fp, char *line, int max=1000){
static bool ReadHeader(FILE *fp,unsigned int &num_cams){ static bool ReadHeader(FILE *fp,unsigned int &num_cams){
char line[1000]; char line[1000];
readline(fp, line); readline(fp, line);
if( (line[0]=='\0') || (0!=strcmp("NVM_V3 ", line)) ) return false; if( (line[0]=='\0') || (0!=strcmp("NVM_V3 ", line)) ) return false;
readline(fp, line); readline(fp, line);
readline(fp, line); if(line[0]=='\0') return false; readline(fp, line); if(line[0]=='\0') return false;
sscanf(line, "%d", &num_cams); sscanf(line, "%d", &num_cams);
return true; return true;
} }
static bool ReadHeader(const char * filename,unsigned int &/*num_cams*/, unsigned int &/*num_points*/){ static bool ReadHeader(const char * filename,unsigned int &/*num_cams*/, unsigned int &/*num_points*/){
FILE *fp = fopen(filename, "r"); FILE *fp = fopen(filename, "r");
if(!fp) return false; if(!fp) return false;
ReadHeader(fp); ReadHeader(fp);
fclose(fp); fclose(fp);
return true; return true;
} }
@ -115,12 +116,12 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
vcg::Point4f R; vcg::Point4f R;
vcg::Point3f t; vcg::Point3f t;
readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%s %f %f %f %f %f %f %f %f %f", name, &f, &(R[0]), &(R[1]), &(R[2]), &(R[3]), &(t[0]), &(t[1]), &(t[2]), &k1); readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%s %f %f %f %f %f %f %f %f %f", name, &f, &(R[0]), &(R[1]), &(R[2]), &(R[3]), &(t[0]), &(t[1]), &(t[2]), &k1);
std::string n(name); std::string n(name);
image_filenames.push_back(n); image_filenames.push_back(n);
/*readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &f, &k1, &k2); /*readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &f, &k1, &k2);
readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(R[0]), &(R[1]), &(R[2])); R[3] = 0; readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(R[0]), &(R[1]), &(R[2])); R[3] = 0;
readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(R[4]), &(R[5]), &(R[6])); R[7] = 0; readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(R[4]), &(R[5]), &(R[6])); R[7] = 0;
@ -130,35 +131,35 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
//vcg::Matrix44f mat = vcg::Matrix44<vcg::Shotf::ScalarType>::Construct<float>(R); //vcg::Matrix44f mat = vcg::Matrix44<vcg::Shotf::ScalarType>::Construct<float>(R);
vcg::Quaternion<float> qfrom; qfrom.Import(R); vcg::Quaternion<ScalarType> qfrom; qfrom.Import(R);
vcg::Matrix44f mat; qfrom.ToMatrix(mat); vcg::Matrix44<ScalarType> mat; qfrom.ToMatrix(mat);
/*vcg::Matrix33f Rt = vcg::Matrix33f( vcg::Matrix44f(mat), 3); /*vcg::Matrix33f Rt = vcg::Matrix33f( vcg::Matrix44f(mat), 3);
Rt.Transpose(); Rt.Transpose();
vcg::Point3f pos = Rt * vcg::Point3f(t[0], t[1], t[2]);*/ vcg::Point3f pos = Rt * vcg::Point3f(t[0], t[1], t[2]);*/
mat[1][0]=-mat[1][0]; mat[1][0]=-mat[1][0];
mat[1][1]=-mat[1][1]; mat[1][1]=-mat[1][1];
mat[1][2]=-mat[1][2]; mat[1][2]=-mat[1][2];
mat[2][0]=-mat[2][0]; mat[2][0]=-mat[2][0];
mat[2][1]=-mat[2][1]; mat[2][1]=-mat[2][1];
mat[2][2]=-mat[2][2]; mat[2][2]=-mat[2][2];
shots[i].Extrinsics.SetTra(vcg::Point3<vcg::Shotf::ScalarType>::Construct<float>(t[0],t[1],t[2])); shots[i].Extrinsics.SetTra(CoordType(t[0],t[1],t[2]));
shots[i].Extrinsics.SetRot(mat); shots[i].Extrinsics.SetRot(mat);
shots[i].Intrinsics.FocalMm = f/100.0f; shots[i].Intrinsics.FocalMm = f/100.0f;
shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably
shots[i].Intrinsics.k[1] = 0.0;//k2; shots[i].Intrinsics.k[1] = 0.0;//k2;
shots[i].Intrinsics.PixelSizeMm = vcg::Point2f(0.01,0.01); shots[i].Intrinsics.PixelSizeMm = vcg::Point2<ScalarType>(0.01,0.01);
QImageReader sizeImg(QString::fromStdString(image_filenames[i])); QImageReader sizeImg(QString::fromStdString(image_filenames[i]));
QSize size=sizeImg.size(); QSize size=sizeImg.size();
shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height()); shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height());
shots[i].Intrinsics.CenterPx[0] = (int)((double)shots[i].Intrinsics.ViewportPx[0]/2.0f); shots[i].Intrinsics.CenterPx[0] = (int)((double)shots[i].Intrinsics.ViewportPx[0]/2.0f);
shots[i].Intrinsics.CenterPx[1] = (int)((double)shots[i].Intrinsics.ViewportPx[1]/2.0f); shots[i].Intrinsics.CenterPx[1] = (int)((double)shots[i].Intrinsics.ViewportPx[1]/2.0f);
} }
readline(fp, line); readline(fp, line);
readline(fp, line); if(line[0]=='\0') return false; readline(fp, line); if(line[0]=='\0') return false;
@ -192,21 +193,21 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
static bool ReadImagesFilenames(const char * filename,std::vector<std::string> &image_filenames) static bool ReadImagesFilenames(const char * filename,std::vector<std::string> &image_filenames)
{ {
FILE * fp = fopen(filename,"r"); FILE * fp = fopen(filename,"r");
if (!fp) return false; if (!fp) return false;
else else
{ {
char line[1000], name[1000]; char line[1000], name[1000];
while(!feof(fp)){ while(!feof(fp)){
readline(fp, line, 1000); readline(fp, line, 1000);
if(line[0] == '\0') continue; //ignore empty lines (in theory, might happen only at end of file) if(line[0] == '\0') continue; //ignore empty lines (in theory, might happen only at end of file)
sscanf(line, "%s", name); sscanf(line, "%s", name);
std::string n(name); std::string n(name);
image_filenames.push_back(n); image_filenames.push_back(n);
} }
} }
fclose(fp); fclose(fp);
return true; return true;
} }
}; // end class }; // end class

View File

@ -62,6 +62,7 @@ public:
typedef typename OpenMeshType::VertexPointer VertexPointer; typedef typename OpenMeshType::VertexPointer VertexPointer;
typedef typename OpenMeshType::ScalarType ScalarType; typedef typename OpenMeshType::ScalarType ScalarType;
typedef typename OpenMeshType::CoordType CoordType;
typedef typename OpenMeshType::VertexType VertexType; typedef typename OpenMeshType::VertexType VertexType;
typedef typename OpenMeshType::FaceType FaceType; typedef typename OpenMeshType::FaceType FaceType;
typedef typename OpenMeshType::VertexIterator VertexIterator; typedef typename OpenMeshType::VertexIterator VertexIterator;
@ -85,11 +86,11 @@ static bool ReadHeader(FILE *fp,unsigned int &num_cams, unsigned int &num_points
} }
static bool ReadHeader(const char * filename,unsigned int &/*num_cams*/, unsigned int &/*num_points*/){ static bool ReadHeader(const char * filename,unsigned int &/*num_cams*/, unsigned int &/*num_points*/){
FILE *fp = fopen(filename, "r"); FILE *fp = fopen(filename, "r");
if(!fp) return false; if(!fp) return false;
ReadHeader(fp); ReadHeader(fp);
fclose(fp); fclose(fp);
return true; return true;
} }
@ -98,7 +99,8 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
const char * filename,const char * filename_images, CallBackPos *cb=0) const char * filename,const char * filename_images, CallBackPos *cb=0)
{ {
unsigned int num_cams,num_points; unsigned int num_cams,num_points;
typedef typename vcg::Matrix44<ScalarType> Matrix44x;
typedef typename vcg::Matrix33<ScalarType> Matrix33x;
FILE *fp = fopen(filename,"r"); FILE *fp = fopen(filename,"r");
if(!fp) return false; if(!fp) return false;
ReadHeader(fp, num_cams, num_points); ReadHeader(fp, num_cams, num_points);
@ -123,32 +125,32 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(t[0]), &(t[1]), &(t[2])); readline(fp, line); if(line[0]=='\0') return false; sscanf(line, "%f %f %f", &(t[0]), &(t[1]), &(t[2]));
vcg::Matrix44f mat = vcg::Matrix44<vcg::Shotf::ScalarType>::Construct<float>(R); Matrix44x mat = Matrix44x::Construct(Matrix44f(R));
vcg::Matrix33f Rt = vcg::Matrix33f( vcg::Matrix44f(mat), 3); Matrix33x Rt = Matrix33x( Matrix44x(mat), 3);
Rt.Transpose(); Rt.Transpose();
vcg::Point3f pos = Rt * vcg::Point3f(t[0], t[1], t[2]); CoordType pos = Rt * CoordType(t[0], t[1], t[2]);
shots[i].Extrinsics.SetTra(vcg::Point3<vcg::Shotf::ScalarType>::Construct<float>(-pos[0],-pos[1],-pos[2])); shots[i].Extrinsics.SetTra(CoordType(-pos[0],-pos[1],-pos[2]));
shots[i].Extrinsics.SetRot(mat); shots[i].Extrinsics.SetRot(mat);
shots[i].Intrinsics.FocalMm = f; shots[i].Intrinsics.FocalMm = f;
shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably shots[i].Intrinsics.k[0] = 0.0;//k1; To be uncommented when distortion is taken into account reliably
shots[i].Intrinsics.k[1] = 0.0;//k2; shots[i].Intrinsics.k[1] = 0.0;//k2;
shots[i].Intrinsics.PixelSizeMm = vcg::Point2f(1,1); shots[i].Intrinsics.PixelSizeMm = vcg::Point2<ScalarType>(1,1);
QSize size; QSize size;
QImageReader sizeImg(QString::fromStdString(image_filenames[i])); QImageReader sizeImg(QString::fromStdString(image_filenames[i]));
if(sizeImg.size()==QSize(-1,-1)) if(sizeImg.size()==QSize(-1,-1))
{ {
QImageReader sizeImg(QString::fromStdString(qPrintable(path_im)+image_filenames[i])); QImageReader sizeImg(QString::fromStdString(qPrintable(path_im)+image_filenames[i]));
size=sizeImg.size(); size=sizeImg.size();
} }
else else
size=sizeImg.size(); size=sizeImg.size();
shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height()); shots[i].Intrinsics.ViewportPx = vcg::Point2i(size.width(),size.height());
shots[i].Intrinsics.CenterPx[0] = (int)((double)shots[i].Intrinsics.ViewportPx[0]/2.0f); shots[i].Intrinsics.CenterPx[0] = (int)((double)shots[i].Intrinsics.ViewportPx[0]/2.0f);
shots[i].Intrinsics.CenterPx[1] = (int)((double)shots[i].Intrinsics.ViewportPx[1]/2.0f); shots[i].Intrinsics.CenterPx[1] = (int)((double)shots[i].Intrinsics.ViewportPx[1]/2.0f);
//AddIntrinsics(shots[i], std::string(filename_images_path).append(image_filenames[i]).c_str()); //AddIntrinsics(shots[i], std::string(filename_images_path).append(image_filenames[i]).c_str());
} }
@ -157,9 +159,9 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
typename OpenMeshType::VertexIterator vi = vcg::tri::Allocator<OpenMeshType>::AddVertices(m,num_points); typename OpenMeshType::VertexIterator vi = vcg::tri::Allocator<OpenMeshType>::AddVertices(m,num_points);
for(uint i = 0; i < num_points;++i,++vi){ for(uint i = 0; i < num_points;++i,++vi){
float x,y,z; double x,y,z;
unsigned int r,g,b,i_cam, key_sift,n_corr; unsigned int r,g,b,i_cam, key_sift,n_corr;
fscanf(fp,"%f %f %f ",&x,&y,&z); fscanf(fp,"%lf %lf %lf ",&x,&y,&z);
(*vi).P() = vcg::Point3<typename OpenMeshType::ScalarType>(x,y,z); (*vi).P() = vcg::Point3<typename OpenMeshType::ScalarType>(x,y,z);
fscanf(fp,"%d %d %d ",&r,&g,&b); fscanf(fp,"%d %d %d ",&r,&g,&b);
(*vi).C() = vcg::Color4b(r,g,b,255); (*vi).C() = vcg::Color4b(r,g,b,255);
@ -180,34 +182,34 @@ static int Open( OpenMeshType &m, std::vector<Shot<ScalarType> > & shots,
static bool ReadImagesFilenames(const char * filename,std::vector<std::string> &image_filenames) static bool ReadImagesFilenames(const char * filename,std::vector<std::string> &image_filenames)
{ {
FILE * fp = fopen(filename,"r"); FILE * fp = fopen(filename,"r");
if (!fp) return false; if (!fp) return false;
else else
{ {
char line[1000], name[1000]; char line[1000], name[1000];
while(!feof(fp)){ while(!feof(fp)){
readline(fp, line, 1000); readline(fp, line, 1000);
if(line[0] == '\0') continue; //ignore empty lines (in theory, might happen only at end of file) if(line[0] == '\0') continue; //ignore empty lines (in theory, might happen only at end of file)
sscanf(line, "%s", name); sscanf(line, "%s", name);
std::string n(name); std::string n(name);
image_filenames.push_back(n); image_filenames.push_back(n);
} }
} }
fclose(fp); fclose(fp);
return true; return true;
} }
static bool AddIntrinsics(vcg::Shotf &shot, const char * image_file) static bool AddIntrinsics(vcg::Shotf &shot, const char * image_file)
{ {
::ResetJpgfile(); ::ResetJpgfile();
FILE * pFile = fopen(image_file, "rb"); FILE * pFile = fopen(image_file, "rb");
int ret = ::ReadJpegSections (pFile, READ_METADATA); int ret = ::ReadJpegSections (pFile, READ_METADATA);
fclose(pFile); fclose(pFile);
if(ret==0) return false; if(ret==0) return false;
shot.Intrinsics.ViewportPx = vcg::Point2i(ImageInfo.Width, ImageInfo.Height); shot.Intrinsics.ViewportPx = vcg::Point2i(ImageInfo.Width, ImageInfo.Height);
shot.Intrinsics.CenterPx = vcg::Point2f(float(ImageInfo.Width/2.0), float(ImageInfo.Height/2.0)); shot.Intrinsics.CenterPx = vcg::Point2f(float(ImageInfo.Width/2.0), float(ImageInfo.Height/2.0));
return true; return true;
} }
}; // end class }; // end class

View File

@ -8,7 +8,7 @@
* \ * * \ *
* All rights reserved. * * All rights reserved. *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
@ -34,412 +34,415 @@
namespace vcg { namespace vcg {
namespace tri { namespace tri {
namespace io { namespace io {
/** /**
This class encapsulate a filter for importing ptx meshes. This class encapsulate a filter for importing ptx meshes.
*/ */
template <class OpenMeshType>
class ImporterPTX
{
public:
typedef typename OpenMeshType::VertexPointer VertexPointer;
typedef typename OpenMeshType::ScalarType ScalarType;
typedef typename OpenMeshType::VertexType VertexType;
typedef typename OpenMeshType::FaceType FaceType;
typedef typename OpenMeshType::VertexIterator VertexIterator;
typedef typename OpenMeshType::FaceIterator FaceIterator;
class Info //ptx file info
{
public:
Info() template <class OpenMeshType>
{ class ImporterPTX
mask = 0; {
meshnum = 0; public:
anglecull = true; typedef typename OpenMeshType::VertexPointer VertexPointer;
angle = 89; typedef typename OpenMeshType::ScalarType ScalarType;
savecolor = true; typedef typename OpenMeshType::VertexType VertexType;
pointcull = true; typedef typename OpenMeshType::FaceType FaceType;
pointsonly = false; typedef typename OpenMeshType::VertexIterator VertexIterator;
switchside = false; typedef typename OpenMeshType::FaceIterator FaceIterator;
flipfaces = false; typedef typename OpenMeshType::CoordType CoordType;
} typedef typename vcg::Matrix44<ScalarType> Matrix44x;
/// a bit mask describing the field preesnt in the ply file class Info //ptx file info
int mask; {
public:
/// index of mesh to be imported Info()
int meshnum; {
mask = 0;
meshnum = 0;
anglecull = true;
angle = 89;
savecolor = true;
pointcull = true;
pointsonly = false;
switchside = false;
flipfaces = false;
}
/// if true use angle cull /// a bit mask describing the field preesnt in the ply file
bool anglecull; int mask;
/// culling angle, if angle culling is selected
float angle;
/// if true, remove invalid points /// index of mesh to be imported
bool pointcull; int meshnum;
/// if true, only keeps points /// if true use angle cull
bool pointsonly; bool anglecull;
/// culling angle, if angle culling is selected
float angle;
/// if true, color if saved. if no color is present, reflectancy is used instead /// if true, remove invalid points
bool savecolor; bool pointcull;
/// switch row-columns /// if true, only keeps points
bool switchside; bool pointsonly;
/// flip faces
bool flipfaces;
}; // end ptx file info class /// if true, color if saved. if no color is present, reflectancy is used instead
bool savecolor;
/// switch row-columns
bool switchside;
/// flip faces
bool flipfaces;
}; // end ptx file info class
/// Standard call for knowing the meaning of an error code /// Standard call for knowing the meaning of an error code
static const char *ErrorMsg(int error) static const char *ErrorMsg(int error)
{ {
static const char * ptx_error_msg[] = static const char * ptx_error_msg[] =
{ {
"No errors", "No errors",
"Can't open file", "Can't open file",
"Header not found", "Header not found",
"Eof in header", "Eof in header",
"Format not found", "Format not found",
"Syntax error on header", "Syntax error on header",
}; };
if(error>6 || error<0) return "Unknown error"; if(error>6 || error<0) return "Unknown error";
else return ptx_error_msg[error]; else return ptx_error_msg[error];
}; };
/// skip ONE range map inside the ptx file, starting from current position /// skip ONE range map inside the ptx file, starting from current position
/// returns true if skipped, false if failed/eof /// returns true if skipped, false if failed/eof
static bool skipmesh(FILE* fp, CallBackPos *cb=NULL) static bool skipmesh(FILE* fp, CallBackPos *cb=NULL)
{ {
int colnum; int colnum;
int rownum; int rownum;
int skiplines; int skiplines;
char linebuf; char linebuf;
if(feof(fp)) return false; if(feof(fp)) return false;
// getting mesh size; // getting mesh size;
fscanf(fp,"%i\n",&colnum); fscanf(fp,"%i\n",&colnum);
fscanf(fp,"%i\n",&rownum); fscanf(fp,"%i\n",&rownum);
if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false; if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
if(feof(fp)) return false; if(feof(fp)) return false;
// have to skip (col * row) lines plus 8 lines for the header // have to skip (col * row) lines plus 8 lines for the header
skiplines = (colnum * rownum) + 8; skiplines = (colnum * rownum) + 8;
for(int ii=0; ii<skiplines; ii++) for(int ii=0; ii<skiplines; ii++)
{ {
fread(&linebuf,1,1,fp); fread(&linebuf,1,1,fp);
while(linebuf != '\n') fread(&linebuf,1,1,fp); while(linebuf != '\n') fread(&linebuf,1,1,fp);
} }
if(cb) cb( 100, "Skipped preamble"); if(cb) cb( 100, "Skipped preamble");
return true; return true;
} }
///Standard call that reading a mesh ///Standard call that reading a mesh
static int Open( OpenMeshType &m, const char * filename, Info importparams, CallBackPos *cb=NULL) static int Open( OpenMeshType &m, const char * filename, Info importparams, CallBackPos *cb=NULL)
{ {
FILE *fp; FILE *fp;
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if(fp == NULL) return false; if(fp == NULL) return false;
m.Clear(); m.Clear();
m.vn=0; m.vn=0;
m.fn=0; m.fn=0;
// if not exporting first one, skip meshes until desired one // if not exporting first one, skip meshes until desired one
if (importparams.meshnum>0) if (importparams.meshnum>0)
for (int i=0; i!=importparams.meshnum; ++i) for (int i=0; i!=importparams.meshnum; ++i)
if(!skipmesh(fp, cb)) if(!skipmesh(fp, cb))
return 1; return 1;
if (!readPTX( m, fp, importparams, cb)) if (!readPTX( m, fp, importparams, cb))
{ {
m.Clear(); m.Clear();
return 1; return 1;
} }
return 0; return 0;
} }
///Call that load a mesh ///Call that load a mesh
static bool readPTX( OpenMeshType &m, FILE *fp, Info importparams, CallBackPos *cb=NULL) static bool readPTX( OpenMeshType &m, FILE *fp, Info importparams, CallBackPos *cb=NULL)
{ {
int numtokens; int numtokens;
int colnum; int colnum;
int rownum; int rownum;
float xx,yy,zz; // position double xx,yy,zz; // position
float rr,gg,bb; // color float rr,gg,bb; // color
float rf; // reflectance float rf; // reflectance
Matrix44f currtrasf; Matrix44d currtrasf;
bool hascolor; bool hascolor;
bool savecolor = importparams.savecolor && VertexType::HasColor(); bool savecolor = importparams.savecolor && VertexType::HasColor();
bool switchside = importparams.switchside; bool switchside = importparams.switchside;
int total = 50; int total = 50;
if (importparams.pointsonly) total = 100; if (importparams.pointsonly) total = 100;
char linebuf[256]; char linebuf[256];
fscanf(fp,"%i\n",&colnum);
fscanf(fp,"%i\n",&rownum);
if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
// initial 4 lines [still don't know what is this :) :)]
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
// now the transformation matrix
if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false;
if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false;
if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false;
if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false;
//now the real data begins
// first line, we should know if the format is
// XX YY ZZ RF
// or it is
// XX YY ZZ RF RR GG BB
// read the entire first line and then count the spaces. it's rude but it works :)
int ii=0;
fread(&(linebuf[ii++]),1,1,fp);
while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
linebuf[ii-1] = '\0'; // terminate the string
numtokens=1;
for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
if(numtokens == 4) hascolor = false;
else if(numtokens == 7) hascolor = true;
else return false;
// PTX transformation matrix is transposed
currtrasf.transposeInPlace();
// allocating vertex space
int vn = rownum*colnum;
VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
m.vn = vn;
m.bbox.SetNull();
// parse the first line.... fscanf(fp,"%i\n",&colnum);
if(hascolor) fscanf(fp,"%i\n",&rownum);
{
printf("\n hascolor ");
sscanf(linebuf,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
}
else
{
printf("\n no color ");
sscanf(linebuf,"%f %f %f %f", &xx, &yy, &zz, &rf);
}
//addthefirstpoint
(*vi).P()[0]=xx;
(*vi).P()[1]=yy;
(*vi).P()[2]=zz;
if(VertexType::HasQuality()) if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
{ // initial 4 lines [still don't know what is this :) :)]
(*vi).Q()=rf; if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
} if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
// now the transformation matrix
if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false;
if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false;
if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false;
if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false;
if(savecolor) //now the real data begins
// first line, we should know if the format is
// XX YY ZZ RF
// or it is
// XX YY ZZ RF RR GG BB
// read the entire first line and then count the spaces. it's rude but it works :)
int ii=0;
fread(&(linebuf[ii++]),1,1,fp);
while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
linebuf[ii-1] = '\0'; // terminate the string
numtokens=1;
for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
if(numtokens == 4) hascolor = false;
else if(numtokens == 7) hascolor = true;
else return false;
// PTX transformation matrix is transposed
currtrasf.transposeInPlace();
// allocating vertex space
int vn = rownum*colnum;
VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
m.vn = vn;
m.bbox.SetNull();
// parse the first line....
if(hascolor)
{
printf("\n hascolor ");
sscanf(linebuf,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
}
else
{
printf("\n no color ");
sscanf(linebuf,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
}
//addthefirstpoint
(*vi).P()[0]=xx;
(*vi).P()[1]=yy;
(*vi).P()[2]=zz;
if(VertexType::HasQuality())
{
(*vi).Q()=rf;
}
if(savecolor)
{
if(hascolor)
{ {
if(hascolor) (*vi).C()[0]=rr;
{ (*vi).C()[1]=gg;
(*vi).C()[0]=rr; (*vi).C()[2]=bb;
(*vi).C()[1]=gg; } else {
(*vi).C()[2]=bb; (*vi).C()[0]=rf*255;
} else { (*vi).C()[1]=rf*255;
(*vi).C()[0]=rf*255; (*vi).C()[2]=rf*255;
(*vi).C()[1]=rf*255; }
(*vi).C()[2]=rf*255; }
} vi++;
}
vi++;
if(switchside) std::swap(rownum,colnum); if(switchside) std::swap(rownum,colnum);
// now for each line until end of mesh (row*col)-1 // now for each line until end of mesh (row*col)-1
for(ii=0; ii<((rownum*colnum)-1); ii++) for(ii=0; ii<((rownum*colnum)-1); ii++)
{ {
if(cb && (ii%100)==0) cb((ii*total)/vn, "Vertex Loading"); if(cb && (ii%100)==0) cb((ii*total)/vn, "Vertex Loading");
// read the stream // read the stream
if(hascolor) if(hascolor)
fscanf(fp,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); fscanf(fp,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
else else
fscanf(fp,"%f %f %f %f", &xx, &yy, &zz, &rf); fscanf(fp,"%f %f %f %f", &xx, &yy, &zz, &rf);
// add the point // add the point
(*vi).P()[0]=xx; (*vi).P()[0]=xx;
(*vi).P()[1]=yy; (*vi).P()[1]=yy;
(*vi).P()[2]=zz; (*vi).P()[2]=zz;
if(tri::HasPerVertexQuality(m)) (*vi).Q()=rf;
if(hascolor && savecolor) if(tri::HasPerVertexQuality(m)) (*vi).Q()=rf;
{
(*vi).C()[0]=rr;
(*vi).C()[1]=gg;
(*vi).C()[2]=bb;
}
else if(!hascolor && savecolor)
{
(*vi).C()[0]=rf*255;
(*vi).C()[1]=rf*255;
(*vi).C()[2]=rf*255;
}
vi++; if(hascolor && savecolor)
} {
(*vi).C()[0]=rr;
(*vi).C()[1]=gg;
(*vi).C()[2]=bb;
}
else if(!hascolor && savecolor)
{
(*vi).C()[0]=rf*255;
(*vi).C()[1]=rf*255;
(*vi).C()[2]=rf*255;
}
vi++;
}
if(! importparams.pointsonly)
{
// now i can triangulate
int trinum = (rownum-1) * (colnum-1) * 2;
typename OpenMeshType::FaceIterator fi= Allocator<OpenMeshType>::AddFaces(m,trinum);
int v0i,v1i,v2i, t;
t=0;
for(int rit=0; rit<rownum-1; rit++)
for(int cit=0; cit<colnum-1; cit++)
{
t++;
if(cb) cb(50 + (t*50)/(rownum*colnum),"PTX Mesh Loading");
v0i = (rit ) + ((cit ) * rownum);
v1i = (rit+1) + ((cit ) * rownum);
v2i = (rit ) + ((cit+1) * rownum);
// upper tri
(*fi).V(2) = &(m.vert[v0i]);
(*fi).V(1) = &(m.vert[v1i]);
(*fi).V(0) = &(m.vert[v2i]);
fi++;
v0i = (rit+1) + ((cit ) * rownum);
v1i = (rit+1) + ((cit+1) * rownum);
v2i = (rit ) + ((cit+1) * rownum);
// lower tri
(*fi).V(2) = &(m.vert[v0i]);
(*fi).V(1) = &(m.vert[v1i]);
(*fi).V(0) = &(m.vert[v2i]);
fi++;
}
}
printf("Loaded %i vert\n",m.vn);
// remove unsampled points
if(importparams.pointcull)
{
if(cb) cb(40,"PTX Mesh Loading - remove invalid vertices");
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
{
if((*vi).P() == CoordType(0.0, 0.0, 0.0))
Allocator<OpenMeshType>::DeleteVertex(m,*vi);
}
if(! importparams.pointsonly) if(! importparams.pointsonly)
{ {
// now i can triangulate if(cb) cb(60,"PTX Mesh Loading - remove invalid faces");
int trinum = (rownum-1) * (colnum-1) * 2; for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
typename OpenMeshType::FaceIterator fi= Allocator<OpenMeshType>::AddFaces(m,trinum);
int v0i,v1i,v2i, t;
t=0;
for(int rit=0; rit<rownum-1; rit++)
for(int cit=0; cit<colnum-1; cit++)
{
t++;
if(cb) cb(50 + (t*50)/(rownum*colnum),"PTX Mesh Loading");
v0i = (rit ) + ((cit ) * rownum);
v1i = (rit+1) + ((cit ) * rownum);
v2i = (rit ) + ((cit+1) * rownum);
// upper tri
(*fi).V(2) = &(m.vert[v0i]);
(*fi).V(1) = &(m.vert[v1i]);
(*fi).V(0) = &(m.vert[v2i]);
fi++;
v0i = (rit+1) + ((cit ) * rownum);
v1i = (rit+1) + ((cit+1) * rownum);
v2i = (rit ) + ((cit+1) * rownum);
// lower tri
(*fi).V(2) = &(m.vert[v0i]);
(*fi).V(1) = &(m.vert[v1i]);
(*fi).V(0) = &(m.vert[v2i]);
fi++;
}
}
printf("Loaded %i vert\n",m.vn);
// remove unsampled points
if(importparams.pointcull)
{
if(cb) cb(40,"PTX Mesh Loading - remove invalid vertices");
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
{
if((*vi).P() == Point3f(0.0, 0.0, 0.0))
Allocator<OpenMeshType>::DeleteVertex(m,*vi);
}
if(! importparams.pointsonly)
{
if(cb) cb(60,"PTX Mesh Loading - remove invalid faces");
for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
{
if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) )
Allocator<OpenMeshType>::DeleteFace(m,*fi);
}
}
}
float limitCos = cos( math::ToRad(importparams.angle) );
printf("Loaded %i vert\n",m.vn);
if(importparams.pointsonly)
{ // Compute Normals and radius for points
// Compute the four edges around each point
// Some edges can be null (boundary and invalid samples)
if(cb) cb(85,"PTX Mesh Loading - computing vert normals");
for(int rit=0; rit<rownum; rit++)
{ {
int ritL = std::max(rit-1,0); if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) )
int ritR = std::min(rit+1,rownum-1); Allocator<OpenMeshType>::DeleteFace(m,*fi);
for(int cit=0; cit<colnum; cit++)
{
int citT = std::max(cit-1,0);
int citB = std::min(cit+1,colnum-1);
int v0 = (rit ) + ((cit ) * rownum);
if(m.vert[v0].IsD()) continue;
int vL = (ritL) + ((cit ) * rownum);
int vR = (ritR) + ((cit) * rownum);
int vT = (rit ) + ((citT ) * rownum);
int vB = (rit ) + ((citB) * rownum);
Point3f v0p=m.vert[v0].P();
Point3f vLp(0,0,0),vRp(0,0,0),vTp(0,0,0),vBp(0,0,0); // Compute the 4 edges around the vertex.
if(!m.vert[vL].IsD()) vLp=(m.vert[vL].P()-v0p).Normalize();
if(!m.vert[vR].IsD()) vRp=(m.vert[vR].P()-v0p).Normalize();
if(!m.vert[vT].IsD()) vTp=(m.vert[vT].P()-v0p).Normalize();
if(!m.vert[vB].IsD()) vBp=(m.vert[vB].P()-v0p).Normalize();
float r=0;
int rc=0; Point3f v0pn = Normalize(v0p);
// Skip edges that are too steep
// Compute the four normalized vector orthogonal to each pair of consecutive edges.
Point3f vLTn = (vLp ^ vTp).Normalize();
Point3f vTRn = (vTp ^ vRp).Normalize();
Point3f vRBn = (vRp ^ vBp).Normalize();
Point3f vBLn = (vBp ^ vLp).Normalize();
// Compute an average Normal skipping null normals and normals that are too steep.
// Compute also the sum of non null edge lenght to compute the radius
Point3f N(0,0,0);
if((vLTn*v0pn)>limitCos) { N+=vLTn; r += Distance(m.vert[vL].P(),v0p)+Distance(m.vert[vT].P(),v0p); rc++; }
if((vTRn*v0pn)>limitCos) { N+=vTRn; r += Distance(m.vert[vT].P(),v0p)+Distance(m.vert[vR].P(),v0p); rc++; }
if((vRBn*v0pn)>limitCos) { N+=vRBn; r += Distance(m.vert[vR].P(),v0p)+Distance(m.vert[vB].P(),v0p); rc++; }
if((vBLn*v0pn)>limitCos) { N+=vBLn; r += Distance(m.vert[vB].P(),v0p)+Distance(m.vert[vL].P(),v0p); rc++; }
m.vert[v0].N()=-N;
if(tri::HasPerVertexRadius(m)) m.vert[v0].R() = r/(rc*2.0f);
// Isolated points has null normal. Delete them please.
if(m.vert[v0].N() == Point3f(0,0,0)) Allocator<OpenMeshType>::DeleteVertex(m,m.vert[v0]);
}
} }
} }
else }
// eliminate high angle triangles
float limitCos = cos( math::ToRad(importparams.angle) );
printf("Loaded %i vert\n",m.vn);
if(importparams.pointsonly)
{ // Compute Normals and radius for points
// Compute the four edges around each point
// Some edges can be null (boundary and invalid samples)
if(cb) cb(85,"PTX Mesh Loading - computing vert normals");
for(int rit=0; rit<rownum; rit++)
{ {
if(importparams.flipfaces) int ritL = std::max(rit-1,0);
tri::Clean<OpenMeshType>::FlipMesh(m); int ritR = std::min(rit+1,rownum-1);
if(importparams.anglecull) for(int cit=0; cit<colnum; cit++)
{ {
if(cb) cb(85,"PTX Mesh Loading - remove steep faces"); int citT = std::max(cit-1,0);
tri::UpdateNormal<OpenMeshType>::PerFaceNormalized(m); int citB = std::min(cit+1,colnum-1);
for(FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++) int v0 = (rit ) + ((cit ) * rownum);
if(!(*fi).IsD())
{ if(m.vert[v0].IsD()) continue;
Point3f raggio = -((*fi).P(0) + (*fi).P(1) + (*fi).P(2)) / 3.0;
int vL = (ritL) + ((cit ) * rownum);
int vR = (ritR) + ((cit) * rownum);
int vT = (rit ) + ((citT ) * rownum);
int vB = (rit ) + ((citB) * rownum);
CoordType v0p=m.vert[v0].P();
CoordType vLp(0,0,0),vRp(0,0,0),vTp(0,0,0),vBp(0,0,0); // Compute the 4 edges around the vertex.
if(!m.vert[vL].IsD()) vLp=(m.vert[vL].P()-v0p).Normalize();
if(!m.vert[vR].IsD()) vRp=(m.vert[vR].P()-v0p).Normalize();
if(!m.vert[vT].IsD()) vTp=(m.vert[vT].P()-v0p).Normalize();
if(!m.vert[vB].IsD()) vBp=(m.vert[vB].P()-v0p).Normalize();
float r=0;
int rc=0; CoordType v0pn = Normalize(v0p);
// Skip edges that are too steep
// Compute the four normalized vector orthogonal to each pair of consecutive edges.
CoordType vLTn = (vLp ^ vTp).Normalize();
CoordType vTRn = (vTp ^ vRp).Normalize();
CoordType vRBn = (vRp ^ vBp).Normalize();
CoordType vBLn = (vBp ^ vLp).Normalize();
// Compute an average Normal skipping null normals and normals that are too steep.
// Compute also the sum of non null edge lenght to compute the radius
CoordType N(0,0,0);
if((vLTn*v0pn)>limitCos) { N+=vLTn; r += Distance(m.vert[vL].P(),v0p)+Distance(m.vert[vT].P(),v0p); rc++; }
if((vTRn*v0pn)>limitCos) { N+=vTRn; r += Distance(m.vert[vT].P(),v0p)+Distance(m.vert[vR].P(),v0p); rc++; }
if((vRBn*v0pn)>limitCos) { N+=vRBn; r += Distance(m.vert[vR].P(),v0p)+Distance(m.vert[vB].P(),v0p); rc++; }
if((vBLn*v0pn)>limitCos) { N+=vBLn; r += Distance(m.vert[vB].P(),v0p)+Distance(m.vert[vL].P(),v0p); rc++; }
m.vert[v0].N()=-N;
if(tri::HasPerVertexRadius(m)) m.vert[v0].R() = r/(rc*2.0f);
// Isolated points has null normal. Delete them please.
if(m.vert[v0].N() == CoordType(0,0,0)) Allocator<OpenMeshType>::DeleteVertex(m,m.vert[v0]);
}
}
}
else
// eliminate high angle triangles
{
if(importparams.flipfaces)
tri::Clean<OpenMeshType>::FlipMesh(m);
if(importparams.anglecull)
{
if(cb) cb(85,"PTX Mesh Loading - remove steep faces");
tri::UpdateNormal<OpenMeshType>::PerFaceNormalized(m);
for(FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
if(!(*fi).IsD())
{
CoordType raggio = -((*fi).P(0) + (*fi).P(1) + (*fi).P(2)) / 3.0;
raggio.Normalize(); raggio.Normalize();
if((raggio.dot((*fi).N())) < limitCos) if((raggio.dot((*fi).N())) < limitCos)
Allocator<OpenMeshType>::DeleteFace(m,*fi); Allocator<OpenMeshType>::DeleteFace(m,*fi);
} }
// deleting unreferenced vertices only if we are interested in faces... // deleting unreferenced vertices only if we are interested in faces...
tri::Clean<OpenMeshType>::RemoveUnreferencedVertex(m); tri::Clean<OpenMeshType>::RemoveUnreferencedVertex(m);
}
} }
}
Matrix44x tr; tr.Import(currtrasf);
tri::UpdatePosition<OpenMeshType>::Matrix(m,currtrasf,true);
tri::Allocator<OpenMeshType>::CompactVertexVector(m);
tri::UpdateBounding<OpenMeshType>::Box(m);
if(cb) cb(100,"PTX Mesh Loading finished!");
return true;
}
tri::UpdatePosition<OpenMeshType>::Matrix(m,currtrasf,true); }; // end class
tri::Allocator<OpenMeshType>::CompactVertexVector(m);
tri::UpdateBounding<OpenMeshType>::Box(m);
if(cb) cb(100,"PTX Mesh Loading finish!");
return true;
}
}; // end class
} // end Namespace tri } // end Namespace tri
} // end Namespace io } // end Namespace io