mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-16 17:44:36 +00:00
qUtf8Printable is better to deal with special characters. also in QT documentation it is said is better when logging strings. However, we use it also to store filenames and text-based ID, if we only use one, and not alternating between qUtf8Printable and qPrintable, thins should be smoother, but since it is a project-wide change, it is potentially DANGEROUS, NOT YET FULLY TESTED
335 lines
10 KiB
C++
Executable File
335 lines
10 KiB
C++
Executable File
/****************************************************************************
|
|
* 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 <Qt>
|
|
|
|
#include "io_tri.h"
|
|
|
|
#include <wrap/io_trimesh/import_asc.h>
|
|
#include <wrap/io_trimesh/export.h>
|
|
|
|
#include <QMessageBox>
|
|
#include <QFileDialog>
|
|
|
|
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<CMeshO>::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<MeshIOInterface::Format> TriIOPlugin::importFormats() const
|
|
{
|
|
QList<Format> 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<MeshIOInterface::Format> TriIOPlugin::exportFormats() const
|
|
{
|
|
QList<Format> 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<CMeshO>::AddVertices(m,numPoints);
|
|
tri::Allocator<CMeshO>::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<numPoints);
|
|
assert(p2>=0 && p2<numPoints);
|
|
assert(p3>=0 && p3<numPoints);
|
|
|
|
m.face[i].V(0)= &m.vert[p1];
|
|
m.face[i].V(1)= &m.vert[p2];
|
|
m.face[i].V(2)= &m.vert[p3];
|
|
}
|
|
|
|
QString texPNG(filename.c_str());
|
|
texPNG = texPNG.left(texPNG.length()-3)+"PNG";
|
|
QImage texturePNG;
|
|
texturePNG.load(texPNG);
|
|
if(!texturePNG.isNull())
|
|
{
|
|
qDebug("Image Loaded %s has %i keys",qUtf8Printable(texPNG),texturePNG.textKeys().size());
|
|
QString infoPNG=texturePNG.text("uv");
|
|
if(!infoPNG.isNull())
|
|
{
|
|
m.textures.push_back(qUtf8Printable(texPNG));
|
|
qDebug("Loading texture %s",qUtf8Printable(texPNG));
|
|
QStringList numList = infoPNG.split(" ", QString::SkipEmptyParts);
|
|
qDebug("Found %i numbers for %i faces",numList.size(),numFaces);
|
|
for (int i = 0; i < numFaces ; ++i)
|
|
{
|
|
for(int j=0;j<3;++j)
|
|
{
|
|
float s=(numList.at(i*6+j*2+0).toInt())/float(texturePNG.width());
|
|
float t=(numList.at(i*6+j*2+1).toInt())/float(texturePNG.height());
|
|
m.face[i].WT(j).U()=s;
|
|
m.face[i].WT(j).V()=1.0-t;
|
|
m.face[i].WT(j).N()=0;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
QString texJPG(filename.c_str());
|
|
texJPG = texJPG.left(texJPG.length()-3)+"JPG";
|
|
QImage textureJPG;
|
|
textureJPG.load(texJPG);
|
|
if(textureJPG.isNull())
|
|
return false;
|
|
|
|
if (!feof(fp) ) {
|
|
char texCode[4];
|
|
bool floatFlag=false;
|
|
|
|
fread(texCode,sizeof(char),4,fp);
|
|
qDebug("TexString code is '%s' (int:%d) (float:%f)\n", texCode, *(int*)(&texCode[0]), *(float*)(&texCode[0]));
|
|
|
|
if(feof(fp)){
|
|
qDebug("Premature end of file");
|
|
return false;
|
|
}
|
|
|
|
if(texCode==QString("TC00")) floatFlag=false;
|
|
|
|
m.textures.push_back(qUtf8Printable(texJPG));
|
|
qDebug("Loading texture %s",qUtf8Printable(texJPG));
|
|
|
|
for (int i = 0; i < numFaces ; ++i)
|
|
{
|
|
if(feof(fp)){
|
|
qDebug("Premature end of file after reading %i tex faces",i);
|
|
return false;
|
|
}
|
|
float s,t;
|
|
short ss,ts;
|
|
for(int j=0;j<3;++j)
|
|
{
|
|
if(floatFlag){
|
|
fread(&s,sizeof(float),1,fp);
|
|
fread(&t,sizeof(float),1,fp);
|
|
} else {
|
|
fread(&ss,sizeof(short),1,fp);
|
|
fread(&ts,sizeof(short),1,fp);
|
|
s=ss/float(textureJPG.width());
|
|
t=ts/float(textureJPG.height());
|
|
}
|
|
|
|
m.face[i].WT(j).U()=s;
|
|
m.face[i].WT(j).V()=1.0-t;
|
|
m.face[i].WT(j).N()=0;
|
|
}
|
|
}
|
|
} // if ! eof
|
|
fclose(fp);
|
|
|
|
if (err) return false;
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
MESHLAB_PLUGIN_NAME_EXPORTER(TriIOPlugin)
|