//
// File: ply_mesh.cc
//
// (C) 2000-2008 Helmut Cantzler / Toby Breckon
//
// Licensed under the terms of the Lesser General Public License.
//
#include <string.h>
#include <stdlib.h>
#include "ply_mesh.h"
int PLYMesh::read(FILE *f, int (*updateProgress)(int pos),
void (*setTotal)(int size))
{
list<Triangle*> *shapeTriangles;
list<Vertex*> *shapeVertices;
vector<Vertex*> vertexIndex;
int p1, p2, p3, i, vNr, pNr;
char nr;
float x, y, z;
Triangle *tri;
Vertex *v;
char buffer[101];
vNr = pNr = 0;
fseek(f, 0, SEEK_END);
(*setTotal)(ftell(f));
fseek(f, 0, SEEK_SET);
// READ IN HEADER
while (fgetc(f) != '\n') // Reads all of the 1st line
;
// read the remainder of the header
// - interested in 3 parts only
// - format
// - number of vertices
// - number of polygons
fscanf(f,"%100s ", buffer);
while (strcasecmp(buffer, "end_header") != 0){
if (strcasecmp(buffer, "format") == 0){
fscanf(f,"%100s ", buffer);
if (strcasecmp(buffer, "ascii") != 0){
FILE_ERROR(f,
"PLY file format error: PLY ASCII support only.");
return 3;
}
} else if (strcasecmp(buffer, "element") == 0){
fscanf(f,"%100s ", buffer);
if (strcasecmp(buffer, "vertex") == 0){
fscanf(f,"%100s", buffer);
vNr = atoi(buffer);
} else if (strcasecmp(buffer, "face") == 0){
fscanf(f,"%100s", buffer);
pNr = atoi(buffer);
}
}
fscanf(f,"%100s ", buffer);
}
shapeTriangles = new list<Triangle*>;
shapeVertices = new list<Vertex*>;
// READ IN VERTICES
for (i=0; i < vNr; i++) // Reads the vertices
{
if (fscanf(f,"%f %f %f",&x,&y,&z) != 3)
{
FILE_ERROR(f, "PLY file format error: vertex list");
return 3;
}
while (fgetc(f) != '\n'); // Read till end of the line
// to skip texture/colour values
v = new Vertex(x,y,z);
addVertex(v);
// save in a vector for the triangles and shape
vertexIndex.push_back(v);
if ((*updateProgress)(ftell(f)))
return 90;
}
// READ IN POLYGONS
while ((0 < pNr) && (!(feof(f))))
{
fscanf(f,"%c", &nr);
switch (nr)
{
case '2':
if (fscanf(f,"%d %d\n", &p1, &p2) != 2)
{
FILE_ERROR(f, "PLY file format error: polygon 2");
return 6;
}
addEdge(new Edge(vertexIndex[p1], vertexIndex[p2]));
pNr--;
break;
case '3':
if (fscanf(f,"%d %d %d\n", &p1, &p2, &p3) != 3)
{
FILE_ERROR(f, "PLY file format error: polygon 3");
return 7;
}
if ((p1 >= verNr) || (p2 >= verNr) || (p3 >= verNr)){
FILE_ERROR(f, "PLY file format error: vertex index out of range");
return 8;
} else {
tri = new Triangle(vertexIndex[p1], vertexIndex[p2],
vertexIndex[p3]);
addTriangle(tri);
pNr--;
}
// save in a list for the shape
shapeTriangles->push_back(tri);
break;
case ' ':
case '\t':
case '\n':
// skip leading whitespace characters
break;
default:
// skip any lines that that we are not interested in
// (i.e. don't begin with the cases above)
// e.g. N vertex polygons of form "N v1 v2...vN" on the line
do
{
nr=fgetc(f);
}
while ((!(feof(f))) && nr != '\n');
break;
}
if ((*updateProgress)(ftell(f)))
return 90;
}
// copy the vertices of this shape over
shapeVertices->insert(shapeVertices->begin(),
vertexIndex.begin(), vertexIndex.end());
shapes->push_back(new Shape(shapeTriangles, shapeVertices));
return 0;
}
void PLYMesh::write(FILE *f, const char *comment)
{
int n;
list<Triangle*>::iterator it;
list<Vertex*>::iterator iv;
Vertex v;
fprintf(f, "ply\n");
fprintf(f, "format ascii 1.0\n");
fprintf(f, "comment %s\n", comment);
fprintf(f, "element vertex %i\n", verNr);
fprintf(f, "property float x\n");
fprintf(f, "property float y\n");
fprintf(f, "property float z\n");
fprintf(f, "element face %i\n", triNr);
fprintf(f, "property list uchar int vertex_indices\n");
fprintf(f, "end_header\n");
n=0; // vertices
for (iv=vertices->begin(); iv != vertices->end(); iv++)
{
calcOriginalCoordinates(*iv, &v);
fprintf(f,"%f %f %f\n", v.x(), v.y(), v.z());
(*iv)->number=++n;
}
// triangles
for (it=triangles->begin(); it != triangles->end(); it++)
fprintf(f,"3 %d %d %d\n", ((*it)->vertices[0]->number - 1),
((*it)->vertices[1]->number - 1), ((*it)->vertices[2]->number) - 1);
}