// Mesh.cpp: implementation of the CMesh class.
//
//////////////////////////////////////////////////////////////////////

#include "Mesh.h"

#include "MeshFace.h"

#include "OpenGL.h"

#include "..\Common\FileStream.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMesh::CMesh()
{
	m_pszClassName = "CMesh";

	///////////////////////////////////////////////////////////////////////////
	m_pVertices = NULL;
	m_pBones = NULL;

	m_pMeshFaces = NULL;
	m_pVector = NULL;

	m_pTransform = NULL;
}

CMesh::~CMesh()
{
	Destroy();
}

void CMesh::Destroy()
{
	if (m_pVector)
	{
		delete [] m_pVector;
		m_pVector = NULL;
	}

	if (m_pBones)
	{
		delete [] m_pBones;
		m_pBones = NULL;
	}

	if (m_pVertices)
	{
		delete [] m_pVertices;
		m_pVertices = NULL;
	}
	
	if (m_pMeshFaces)
	{
		delete [] m_pMeshFaces;
		m_pMeshFaces = NULL;
	}

	CUnknown::Destroy();
}

bool CMesh::Read(CFileStream* lpStream)
{
	CFileStream* pStream = lpStream;

	char szName[80];
	pStream->ReadString(szName);
	if (!CUnknown::Create(szName))
		return false;

	///////////////////////////////////////////////////////////////////////////////////////////////
	pStream->Read(&m_dwNumVertices, sizeof(DWORD), 1);
	m_pVertices = new VERTEX [m_dwNumVertices];
	if (!m_pVertices)
		return false;

	pStream->Read(m_pVertices, sizeof(VERTEX), m_dwNumVertices);

	///////////////////////////////////////////////////////////////////////////////////////////////
	m_pBones = new int [m_dwNumVertices];
	if (!m_pBones)
		return false;

	pStream->Read(m_pBones, sizeof(int), m_dwNumVertices);

	///////////////////////////////////////////////////////////////////////////////////////////////
	m_pVector = new VECTOR3D [m_dwNumVertices];
	if (!m_pVector)
		return false;

	LPVECTOR3D pVector   = m_pVector;
	LPVERTEX pVertices = m_pVertices;

	for (int i = 0; i < (int) m_dwNumVertices; i ++)
	{
		pVector->x = pVertices->x;
		pVector->y = pVertices->y;
		pVector->z = pVertices->z;

		pVector   ++;
		pVertices ++;
	}

	///////////////////////////////////////////////////////////////////////////////////////////////
	pStream->Read(&m_dwNumMeshFaces, sizeof(DWORD), 1);
	m_pMeshFaces = new CMeshFace [m_dwNumMeshFaces];
	if (!m_pMeshFaces)
		return false;

	CMeshFace* pMeshFace = m_pMeshFaces;
	for (int j = 0; j < (int) m_dwNumMeshFaces; j ++)
	{
		pMeshFace->Read(pStream);
		pMeshFace ++;
	}
	
	return true;
}

void CMesh::Render()
{
	glInterleavedArrays(GL_T2F_N3F_V3F, 0, m_pVertices);

	//if (glLockArraysEXT)
	//	glLockArraysEXT(0, m_dwNumVertices);

	CMeshFace* pMeshFace = m_pMeshFaces;
	for (int i = 0; i < (int) m_dwNumMeshFaces; i ++)
	{
		pMeshFace->Render();
		pMeshFace ++;
	}

	//if (glUnlockArraysEXT)
	//	glUnlockArraysEXT();
}

void CMesh::Update()
{
	///////////////////////////////////////////////////////////////////////////////////////////////
	LPVECTOR3D pVector   = m_pVector;
	LPVERTEX pVertices = m_pVertices;
	int*	 pBone     = m_pBones;

	for (int i=0; i<(int) m_dwNumVertices; i++)
	{
		LPMATRIX pTransform = (LPMATRIX) m_pTransform + (*pBone);

		pVertices->x = pVector->x * pTransform->_00 + 
					   pVector->y * pTransform->_01 + 
					   pVector->z * pTransform->_02 + pTransform->_03;
		pVertices->y = pVector->x * pTransform->_10 + 
					   pVector->y * pTransform->_11 + 
					   pVector->z * pTransform->_12 + pTransform->_13;
		pVertices->z = pVector->x * pTransform->_20 + 
					   pVector->y * pTransform->_21 + 
					   pVector->z * pTransform->_22 + pTransform->_23;
		
		pBone ++;

		pVector   ++;
		pVertices ++;
	}
}
