#include "ThMD2Object.h"
using namespace Th;
#include <fstream>
//-------------------------------------------------------------

IMPLEMENT_STATIC_RTTI_MEMBER(MD2Object,Geometry)
IMPLEMENT_IS_DERIVED_FROM(MD2Object)
//-------------------------------------------------------------

MD2Object::MD2Object()
	:
	Geometry(), m_akFrames(NULL), m_akTriangle(NULL)
{
}
//-------------------------------------------------------------

MD2Object::MD2Object(const String& rkFilename)
	:	
	Geometry()
{
	if (LoadObject(rkFilename) != true)
		assert(false);
}
//-------------------------------------------------------------

MD2Object::~MD2Object()
{
	if (m_akFrames != NULL)
		delete[] m_akFrames;

	if (m_akTriangle != NULL)
		delete[] m_akTriangle;

	if (m_akTextureCoords != NULL)
		delete[] m_akTextureCoords;
}
//-------------------------------------------------------------

bool MD2Object::LoadObject(const String& rkFilename)
{
	//Loads the file given as parameter


	//Load file

	std::ifstream kFile;
	kFile.open(rkFilename, std::ios::binary | std::ios::in);
	if (!kFile)
	{kFile.close();	return false;}
	
	//Loading header

	kFile.read((char *)&m_kHeader, sizeof(MD2Header));

	//Check magic number

	if (m_kHeader.iMagic != 0x32504449 ||m_kHeader.iVersion != 8)
		{kFile.close();	return false;} //wrong magic number

	
	//Load the frames

	kFile.seekg(m_kHeader.iOffsetFrames, std::ios::beg); //seek to start

	m_akFrames = new char[m_kHeader.iFrameSize * m_kHeader.iNumFrames];
	kFile.read((char *)m_akFrames, m_kHeader.iFrameSize * m_kHeader.iNumFrames);

	//Read in to vertex array

	m_akVertex = new Vector3[m_kHeader.iNumFrames*m_kHeader.iNumVertices];
	for (int i = 0; i < m_kHeader.iNumFrames; i++)
	{
		for (int j = 0; j < m_kHeader.iNumVertices; j++)
		{
			int iVertexIndex = i*m_kHeader.iNumVertices+j; 
			int iFrameIndex = i*m_kHeader.iFrameSize;
			m_akVertex[iVertexIndex].x = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[0]);
			m_akVertex[iVertexIndex].y = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[1]);
			m_akVertex[iVertexIndex].z = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[2]);
			
			m_akVertex[iVertexIndex].x *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[0];
			m_akVertex[iVertexIndex].y *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[1];
			m_akVertex[iVertexIndex].z *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[2];

			//scale them:

			m_akVertex[iVertexIndex].x += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[0];
			m_akVertex[iVertexIndex].y += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[1];
			m_akVertex[iVertexIndex].z += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[2];
		}
	}

	//Read triangles

	m_akTriangle = new MD2Triangle[m_kHeader.iNumTriangles];
	kFile.seekg(m_kHeader.iOffsetTriangles, std::ios::beg);
	kFile.read((char *)m_akTriangle, m_kHeader.iNumTriangles * sizeof(MD2Triangle));

	//Read texture coordinates

	m_akTextureCoords = new MD2TextureCoord[m_kHeader.iNumTexCoords];
	kFile.seekg(m_kHeader.iOffsetTexCoords, std::ios::beg);
	kFile.read((char *)m_akTextureCoords, sizeof(MD2TextureCoord)*m_kHeader.iNumTexCoords);

	//Build bounding volume

	m_kModelBound.ComputeFromData(m_akVertex, m_kHeader.iNumVertices);

	kFile.close(); //close up nicely

	return true;
}
//-------------------------------------------------------------

void MD2Object::Draw(Renderer &rkRenderer)
{
	Geometry::Draw(rkRenderer);
	rkRenderer.Render(this);
}
//-------------------------------------------------------------

const MD2Object::MD2Header& MD2Object::Header() const
{
	return m_kHeader;
}
//-------------------------------------------------------------

const MD2Object::MD2Triangle* MD2Object::Triangles() const
{
	return m_akTriangle;
}
//-------------------------------------------------------------

const MD2Object::MD2TextureCoord* MD2Object::TextureCoords() const
{
	return m_akTextureCoords;
}
//-------------------------------------------------------------