/**************************************************************************** * MeshLab o o * * An extendible mesh processor o o * * _ O _ * * Copyright(C) 2005, 2006 \/)\/ * * 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. * * * ****************************************************************************/ /**************************************************************************** History $Log: meshio.cpp,v $ *****************************************************************************/ #include #include "io_tri.h" #include #include #include #include using namespace vcg; bool parseTRI(const std::string &filename, CMeshO &m); void TriIOPlugin::initPreOpenParameter(const QString &format, const QString &/*fileName*/, RichParameterSet & parlst) { if(format.toUpper() == tr("ASC")) { parlst.addParam(new RichInt("rowToSkip",0,"Header Row to be skipped","The number of lines that must be skipped at the beginning of the file.")); parlst.addParam(new RichBool("triangulate", true, "Grid triangulation", "if true it assumes that the points are arranged in a complete xy grid and it tries to perform a naive height field triangulation of the input data. Lenght of the lines is detected automatically by searching x jumps. If the input point cloud data is not arranged as a xy regular height field, no triangles are created.")); } } bool TriIOPlugin::open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet &parlst, CallBackPos *cb, QWidget *) { if(formatName.toUpper() == tr("TRI")) { mask |= vcg::tri::io::Mask::IOM_WEDGTEXCOORD; m.Enable(mask); return parseTRI(qUtf8Printable(fileName), m.cm); } if(formatName.toUpper() == tr("ASC")) { mask |= vcg::tri::io::Mask::IOM_VERTQUALITY; m.Enable(mask); bool triangulate = parlst.getBool("triangulate"); int rowToSkip = parlst.getInt("rowToSkip"); int result = tri::io::ImporterASC::Open(m.cm, qUtf8Printable(fileName),cb,triangulate,rowToSkip); if (result != 0) // all the importers return 0 on success { errorMessage = QString("Failed to open:")+fileName; return false; } return true; } return false; } bool TriIOPlugin::save(const QString &, const QString &, MeshModel &, const int, const RichParameterSet &, vcg::CallBackPos *, QWidget *) { assert(0); return false; } /* returns the list of the file's type which can be imported */ QList TriIOPlugin::importFormats() const { QList formatList; formatList << Format("TRI (photogrammetric reconstructions)", tr("TRI")) << Format("ASC (ascii triplets of points)", tr("ASC")); return formatList; } /* returns the list of the file's type which can be exported */ QList TriIOPlugin::exportFormats() const { QList formatList; return formatList; } /* returns the mask on the basis of the file's type. otherwise it returns 0 if the file format is unknown */ void TriIOPlugin::GetExportMaskCapability(QString &, int &capability, int &defaultBits) const { capability=defaultBits=0; return; } static inline void readbeOne(void * ptr,unsigned int sz,FILE* f) { unsigned char* array = new unsigned char[sz]; fread(array,sz,1,f); for(unsigned int i = 0; i < sz; ++i) { memcpy((unsigned char *)(ptr)+i,&array[sz-1-i],1); } delete [] array; } size_t readOtherE(void * ptr,unsigned int sz,unsigned int cpt,FILE* f) { for (unsigned int i = 0; i < cpt; ++i) { readbeOne((unsigned char *)(ptr)+i*sz, sz, f); } return cpt*sz; } int readHeader(FILE* fp, bool &TRIInverseBytes, int &numPoints, int &numFaces) { // Determine byte ordering unsigned short byteOrder; fread(&byteOrder,sizeof(short),1,fp); if (byteOrder==0x4c45 || byteOrder==0x4542) { TRIInverseBytes=true; } else if (byteOrder==0x454c || byteOrder==0x4245) { TRIInverseBytes=false; } else { return 1; } // Get number of points and faces if (TRIInverseBytes) { readOtherE(&numPoints,sizeof(int),1,fp); readOtherE(&numFaces,sizeof(int),1,fp); } else { fread(&numPoints,sizeof(int),1,fp); fread(&numFaces,sizeof(int),1,fp); } // advance pointer ?? char s[4]; fread(s,sizeof(char),4,fp); printf("extara is %s (%d)\n", s, *(int*)(&s[0])); return 0; } static int readPoint(FILE* fp, bool TRIInverseBytes, float &x,float &y, float &z) { if (TRIInverseBytes) { //printf("!!! Warning : not implemented\n"); readOtherE(&x,sizeof(float),1,fp); readOtherE(&y,sizeof(float),1,fp); readOtherE(&z,sizeof(float),1,fp); } else { fread(&x,sizeof(float),1,fp); fread(&y,sizeof(float),1,fp); fread(&z,sizeof(float),1,fp); } return 0; } static int readTexel(FILE* fp, bool TRIInverseBytes, float &s, float &t) { if (TRIInverseBytes) { //printf("!!! Warning : not implemented\n"); readOtherE(&s,sizeof(float),1,fp); readOtherE(&t,sizeof(float),1,fp); } else { fread(&s,sizeof(float),1,fp); fread(&t,sizeof(float),1,fp); } return 0; } static int readFace(FILE *fp, bool TRIInverseBytes, int &p1, int &p2, int &p3) { if (TRIInverseBytes) { //printf("!!! Warning : not implemented\n"); readOtherE(&p1,sizeof(int),1,fp); readOtherE(&p2,sizeof(int),1,fp); readOtherE(&p3,sizeof(int),1,fp); } else { fread(&p1,sizeof(int),1,fp); fread(&p2,sizeof(int),1,fp); fread(&p3,sizeof(int),1,fp); } return 0; } bool parseTRI(const std::string &filename, CMeshO &m) { FILE *fp = fopen(filename.c_str(), "rb"); if (!fp) { return false; } int err = 0; // Read header info int numPoints, numFaces; bool TRIInverseBytes; err |= readHeader(fp, TRIInverseBytes, numPoints, numFaces); if (err) { // Error::setError("Error parsing .tri\n"); fclose(fp); return 1; } qDebug("Reading a mesh of %i vert and %i faces",numPoints,numFaces); tri::Allocator::AddVertices(m,numPoints); tri::Allocator::AddFaces(m,numFaces); // Read points float x, y, z; for (int i = 0; i < numPoints; ++i) { err = readPoint(fp, TRIInverseBytes, x, y, z); m.vert[i].P()=Point3m(x, y, z); } if (err) { //Error::setError("Error parsing .tri\n"); fclose(fp); return false; } // Read faces int p1, p2, p3; for (int i = 0; i < numFaces; ++i) { err |= readFace(fp, TRIInverseBytes, p1, p2, p3); assert(p1>=0 && p1=0 && p2=0 && p3