#include "Model.h"

void Model::init()
{
	//initializes the Model
	mesh = new Mesh(groundTruth, useShortcutEdges, maxLevel, nInitialSamples);

	//if (theInput == CAT || theInput == DOG || theInput == LION || theInput == DOG_WOLF || theInput == HORSE2 || theInput == CAT_DOG || theInput == CAT_WOLF || theInput == WOLF_HORSE2 || theInput == DAVID || theInput == VICTORIA || theInput == MICHEAL || theInput == DAVID_VICTORIA || theInput == MICHAEL_VICTORIA || theInput == DAVID_MICHAEL || (theInput == WOLF_DANCING && source) || (theInput == WOLF_HORSE && source) || (theInput == DOG_HORSE && source))
	//	loadObj2(fName);
	//else
		loadObj(path);

	cout << "Initial mesh has " << (int) mesh->tris.size() << " tris, " << (int) mesh->verts.size() << " verts, "
		 << (int) mesh->edges.size() << " edges\nInitialization done\n\n";
	mesh->updateNormals();

	color = new float[3];
	color[0] = color[1] = color[2] = 0.75f;
	
}

Mesh* Model::getMesh()
{
	return mesh;
}

void Model::loadObj(char* meshFile)
{
	cout << "Mesh initializing (to model in " << meshFile << " file)...\n";

	FILE* fPtr = fopen(meshFile, "r");
	if (fPtr == 0)
		cout << "cannot read " << meshFile << endl;

	char type;	//type of line: vertex line (v) or face line (f)
	float a, b, c;	//for face lines casting these to int will suffice
	bool first = true;
	float minX, minY, minZ, maxX, maxY, maxZ; //bbox to be used in center-of-bbox calculation
	mesh->minEdgeLen = INF;	mesh->maxEdgeLen = -INF; mesh->edgeLenTotal = 0.0f;
	while (fscanf(fPtr, "%c %f %f %f\n", &type, &a, &b, &c) != EOF) //go till the end of file
		if (type == 'v')
		{
			//for a robust duplicateExists check in Mesh.addVertex(), scale up coords just in case
			a *= SCALE_FACTOR;	b *= SCALE_FACTOR;	c *= SCALE_FACTOR;

			//none of verts are removed/duplicated initially 'cos i read .obj
			float* coords = new float[3];
			coords[0] = a;
			coords[1] = b;
			coords[2] = c;
			mesh->addVertexND(coords); //ND: no duplicate check

			//bbox computation
			if ((int) mesh->verts.size() == 1)
			{
				minX = maxX = a;	minY = maxY = b;	minZ = maxZ = c;
			}
			else
			{
				if (a < minX)	minX = a; else if (a > maxX)	maxX = a;
				if (b < minY)	minY = b; else if (b > maxY)	maxY = b;
				if (c < minZ)	minZ = c; else if (c > maxZ)	maxZ = c;
			}
		}
		else //if (type == 'f')
			mesh->addTriangle((int) a - 1, (int) b - 1, (int) c - 1, true); //-1: obj indices start at 1

	float cobX = (minX+maxX) / 2.0f, cobY = (minY+maxY) / 2.0f, cobZ = (minZ+maxZ) / 2.0f;
	cout << "bbox.center: (" << cobX << ", " << cobY << ", " << cobZ << "); "
		 << "bbox.(w,h,d): (" << maxX-minX << ", " << maxY-minY << ", " << maxZ-minZ << ")\n"
		 << "min <= avg <= maxEdgeLen: " << mesh->minEdgeLen << " <= " << mesh->edgeLenTotal/((int) mesh->edges.size()) << " <= " << mesh->maxEdgeLen << "\n";
	fclose(fPtr);
	cout << "Initialization done\n\n";
}
void Model::loadObj2(char* meshFile)
{
	//only difference from loadObj() is this one expects no preceding 'v' and 'f' in lines, and a separator line ("-9 -9 -9") b/w vertices and faces

	cout << "Mesh initializing (to model in " << meshFile << " file)...\n";

	FILE* fPtr = fopen(meshFile, "r");
	if (fPtr == 0)
		cout << "cannot read " << meshFile << endl;

	char type;	//type of line: vertex line (v) or face line (f)
	float a, b, c;	//for face lines casting these to int will suffice
	bool first = true;
	float minX, minY, minZ, maxX, maxY, maxZ; //bbox to be used in center-of-bbox calculation
	mesh->minEdgeLen = INF;	mesh->maxEdgeLen = -INF; mesh->edgeLenTotal = 0.0f;
type = 'v';
	while (fscanf(fPtr, "%f %f %f\n", &a, &b, &c) != EOF) //missing 'v' and 'f' in each line of .obj2 files [dog-wolf case]
		if (type == 'v')
		{
if (a == -9 && b == -9 && c == -9) { type = 'f'; continue; } //my special .obj2 file starts triangles right after -9 -9 -9 line

			//for a robust duplicateExists check in Mesh.addVertex(), scale up coords just in case
			a *= SCALE_FACTOR;	b *= SCALE_FACTOR;	c *= SCALE_FACTOR;

			//none of verts are removed/duplicated initially 'cos i read .obj
			float* coords = new float[3];
			coords[0] = a, coords[1] = b, coords[2] = c;
			mesh->addVertexND(coords); //ND: no duplicate check

			//bbox computation
			if ((int) mesh->verts.size() == 1)
			{
				minX = maxX = a;	minY = maxY = b;	minZ = maxZ = c;
			}
			else
			{
				if (a < minX)	minX = a; else if (a > maxX)	maxX = a;
				if (b < minY)	minY = b; else if (b > maxY)	maxY = b;
				if (c < minZ)	minZ = c; else if (c > maxZ)	maxZ = c;
			}
		}
		else //if (type == 'f')
			mesh->addTriangle((int) a - 1, (int) b - 1, (int) c - 1, true); //-1: obj indices start at 1

	float cobX = (minX+maxX) / 2.0f, cobY = (minY+maxY) / 2.0f, cobZ = (minZ+maxZ) / 2.0f;
	cout << "bbox.center: (" << cobX << ", " << cobY << ", " << cobZ << "); "
		 << "bbox.(w,h,d): (" << maxX-minX << ", " << maxY-minY << ", " << maxZ-minZ << ")\n"
		 << "min <= avg <= maxEdgeLen: " << mesh->minEdgeLen << " <= " << mesh->edgeLenTotal/((int) mesh->edges.size()) << " <= " << mesh->maxEdgeLen << "\n";
	fclose(fPtr);
	cout << "Initialization done\n\n";
}
