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;
@ -77,19 +78,19 @@ 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

@ -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 template <class OpenMeshType>
{ class ImporterPTX
public: {
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;
typedef typename OpenMeshType::CoordType CoordType;
typedef typename vcg::Matrix44<ScalarType> Matrix44x;
Info() class Info //ptx file info
{ {
mask = 0; public:
meshnum = 0;
anglecull = true;
angle = 89;
savecolor = true;
pointcull = true;
pointsonly = false;
switchside = false;
flipfaces = false;
}
/// a bit mask describing the field preesnt in the ply file Info()
int mask; {
mask = 0;
meshnum = 0;
anglecull = true;
angle = 89;
savecolor = true;
pointcull = true;
pointsonly = false;
switchside = false;
flipfaces = false;
}
/// index of mesh to be imported /// a bit mask describing the field preesnt in the ply file
int meshnum; int mask;
/// if true use angle cull /// index of mesh to be imported
bool anglecull; int meshnum;
/// culling angle, if angle culling is selected
float angle;
/// if true, remove invalid points /// if true use angle cull
bool pointcull; bool anglecull;
/// culling angle, if angle culling is selected
float angle;
/// if true, only keeps points /// if true, remove invalid points
bool pointsonly; bool pointcull;
/// if true, color if saved. if no color is present, reflectancy is used instead /// if true, only keeps points
bool savecolor; bool pointsonly;
/// switch row-columns /// if true, color if saved. if no color is present, reflectancy is used instead
bool switchside; bool savecolor;
/// flip faces
bool flipfaces;
}; // end ptx file info class /// 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",&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;
// initial 4 lines [still don't know what is this :) :)] // 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,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false; if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
// now the transformation matrix // 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,"%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,"%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,"%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,"%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,"%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,"%f %f %f %f\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,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;
//now the real data begins //now the real data begins
// first line, we should know if the format is // first line, we should know if the format is
// XX YY ZZ RF // XX YY ZZ RF
// or it is // or it is
// XX YY ZZ RF RR GG BB // XX YY ZZ RF RR GG BB
// read the entire first line and then count the spaces. it's rude but it works :) // read the entire first line and then count the spaces. it's rude but it works :)
int ii=0; int ii=0;
fread(&(linebuf[ii++]),1,1,fp); fread(&(linebuf[ii++]),1,1,fp);
while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false; while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
linebuf[ii-1] = '\0'; // terminate the string linebuf[ii-1] = '\0'; // terminate the string
numtokens=1; numtokens=1;
for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++; for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
if(numtokens == 4) hascolor = false; if(numtokens == 4) hascolor = false;
else if(numtokens == 7) hascolor = true; else if(numtokens == 7) hascolor = true;
else return false; else return false;
// PTX transformation matrix is transposed // PTX transformation matrix is transposed
currtrasf.transposeInPlace(); currtrasf.transposeInPlace();
// allocating vertex space // allocating vertex space
int vn = rownum*colnum; int vn = rownum*colnum;
VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn); VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
m.vn = vn; m.vn = vn;
m.bbox.SetNull(); m.bbox.SetNull();
// parse the first line.... // parse the first line....
if(hascolor) if(hascolor)
{ {
printf("\n hascolor "); printf("\n hascolor ");
sscanf(linebuf,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb); sscanf(linebuf,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
} }
else else
{ {
printf("\n no color "); printf("\n no color ");
sscanf(linebuf,"%f %f %f %f", &xx, &yy, &zz, &rf); sscanf(linebuf,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
} }
//addthefirstpoint //addthefirstpoint
(*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(VertexType::HasQuality()) if(VertexType::HasQuality())
{ {
(*vi).Q()=rf; (*vi).Q()=rf;
} }
if(savecolor) 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(tri::HasPerVertexQuality(m)) (*vi).Q()=rf;
if(hascolor && savecolor) if(hascolor && savecolor)
{ {
(*vi).C()[0]=rr; (*vi).C()[0]=rr;
(*vi).C()[1]=gg; (*vi).C()[1]=gg;
(*vi).C()[2]=bb; (*vi).C()[2]=bb;
} }
else if(!hascolor && savecolor) else if(!hascolor && savecolor)
{ {
(*vi).C()[0]=rf*255; (*vi).C()[0]=rf*255;
(*vi).C()[1]=rf*255; (*vi).C()[1]=rf*255;
(*vi).C()[2]=rf*255; (*vi).C()[2]=rf*255;
} }
vi++; 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