Newer
Older
Import / research / 3d-z-maps / mview-0.3.3 / mview / ply_mesh.cpp
//
//    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);
}