//
//    File: obj_mesh.cc
//
//    (C) 2006-2008 Toby Breckon / Helmut Cantzler
//
//    Licensed under the terms of the Lesser General Public License.
//

#include "obj_mesh.h"

int OBJMesh::read(FILE *f, int (*updateProgress)(int pos),
		  void (*setTotal)(int size))
{
  list<Triangle*> *shapeTriangles;
  list<Vertex*> *shapeVertices;
  vector<Vertex*> vertexIndex;
  vector<int> faceIndices;
  Triangle *tri;
  Vertex *v;
  char type;
  int p;
  float x, y, z;
	
  fseek(f, 0, SEEK_END);
  (*setTotal)(ftell(f));
  fseek(f, 0, SEEK_SET);

  shapeTriangles = new list<Triangle*>;
  shapeVertices = new list<Vertex*>;

  while ((type=fgetc(f)) != EOF)
  {
    switch (type)
      {
	case '#': // Comment
	  do    // Reads till end of the line
	    {
	      type=fgetc(f);
	    }
	  while (type != EOF && type != '\n');
	  break;

	case 'v': // Vertex
		
	  // check it is a vertex of "v" and not "vt" or "vn"
	
	  type=fgetc(f); 
	  if (type == ' '){
	    if (fscanf(f,"%f %f %f\n",&x,&y,&z) != 3)
	      {
		FILE_ERROR(f, "OBJ file format error: v");
		return 1;
	      }
		
	    v = new Vertex(x,y,z);
	    addVertex(v);
		
	    // save in a vector for the triangles and shape
	    vertexIndex.push_back(v);
	  }
	  break;

	case 'f': // Polygon with n vertices
	
	  faceIndices.clear();

	  // read vertex indices of the current face until end of line

	  do
	  {
	    if (fscanf(f," %d", &p) != 1)
	      break;

	    faceIndices.push_back(p);

	    do    // Reads till next space
	      { type=fgetc(f); }
	    while (type != EOF && type != ' ' && type != '\n');
	  }
	  while (type != '\n');

	  // build normal triangle

	  if (faceIndices.size() == 3)
	  {
	    if (faceIndices[0] < 1 || faceIndices[1] < 1 || faceIndices[2] < 1 ||
		faceIndices[0] > verNr || faceIndices[1] > verNr || faceIndices[2] > verNr)
	    {
	      FILE_ERROR(f, "OBJ file format error: wrong vertex index");
	      return 2;
	    }

	    tri = new Triangle(vertexIndex[ faceIndices[0]-1 ], vertexIndex[ faceIndices[1]-1 ], 
			       vertexIndex[ faceIndices[2]-1 ]);
	    addTriangle(tri);
	    shapeTriangles->push_back(tri);

	  }

	  // build triangles from polygons

	  if (faceIndices.size() > 3)
	  {
	    for (p=1; p < faceIndices.size()-1; p++)
	    {
	      if (faceIndices[0] < 1 || faceIndices[p] < 1 || faceIndices[p+1] < 1 ||
		  faceIndices[0] > verNr || faceIndices[p] > verNr || faceIndices[p+1] > verNr)
	      {
		FILE_ERROR(f, "OBJ file format error: wrong vertex index");
		return 2;
	      }

	      tri = new Triangle(vertexIndex[ faceIndices[0]-1 ], vertexIndex[ faceIndices[p]-1 ],
				 vertexIndex[ faceIndices[p+1]-1 ], POLYGON_TRIANGLE);
	      addTriangle(tri);
	      shapeTriangles->push_back(tri);

	    }
	  }

	  break;

	default:
	  // skip lines starting with all all other chars	
 		
	  do    // Reads till end of the line
	    {
	      type=fgetc(f);
	    }
	  while (type != EOF && type != '\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 OBJMesh::write(FILE *f, const char *comment)
{
  int n;
  list<Triangle*>::iterator it;
  list<Vertex*>::iterator iv;
  Vertex v;

  fprintf(f, "# produced by mview OBJ exporter\n");
  fprintf(f, "# %s\n", comment);
  fprintf(f, "\ng main\n");
	
  n=0;    // vertices
  for (iv=vertices->begin(); iv != vertices->end(); iv++)
    {
      calcOriginalCoordinates(*iv, &v);
      fprintf(f,"v %f %f %f\n", v.x(), v.y(), v.z());
      (*iv)->number=++n;
    }

  // triangles
  for (it=triangles->begin(); it != triangles->end(); it++)
    fprintf(f,"f %d %d %d\n", (*it)->vertices[0]->number,
	    (*it)->vertices[1]->number, (*it)->vertices[2]->number);
}
