#include "StdAfx.h"
#include ".\modobject.h"

CModObject::CModObject(INode *_node, TimeValue _time)
{

	m_ValidObj = false;
	ObjectState os = _node->EvalWorldState(_time);

	TriObject *triObject = (TriObject *)os.obj->ConvertToType(_time, triObjectClassID);
	Mesh &mesh = triObject->GetMesh();
	m_mesh = &mesh;

	Mtl*	material = _node->GetMtl();
	m_nbrVrtx = 0;

	if (material == NULL)
	{
		assert(0);
		return;
	}
	m_nbrIds  = material->NumSubMtls();

	m_nbrFaces = mesh.getNumFaces();

	assert(m_nbrFaces < 65530);
	assert(mesh.getNumVerts() < 65530);

	if ((m_nbrIds == 0) ||
		(m_nbrFaces == 0) ||
		(mesh.getNumVerts() == 0))
	{
		assert(0);
		return;
	}

	strcpy(m_name,_node->GetName());

	for (int i = 0; i < m_nbrIds; i++)
	{
		Mtl* sub  = material->GetSubMtl(i);
		if (sub)		
		{
			CModElem * elem;
			elem = new CModElem(sub->GetName(), sub);
			m_elements.push_back(elem);
		}
	}
	
	// test with & without
	m_mesh->buildNormals();
	
	for (int i = 0; i < m_nbrFaces; i++) {
		Face face     = mesh.faces[i];
		TVFace tvFace = mesh.tvFace[i];
		unsigned long UV0, UV1, UV2, V0,V1,V2;
		MtlID elemIdx = face.getMatID();
		UV0 = AddUV(elemIdx, mesh.tVerts[tvFace.t[0]].x, mesh.tVerts[tvFace.t[0]].y);
		UV1 = AddUV(elemIdx, mesh.tVerts[tvFace.t[1]].x, mesh.tVerts[tvFace.t[1]].y);
		UV2 = AddUV(elemIdx, mesh.tVerts[tvFace.t[2]].x, mesh.tVerts[tvFace.t[2]].y);
		V0 = AddVerxt(face.v[0]);
		V1 = AddVerxt(face.v[1]);
		V2 = AddVerxt(face.v[2]);

		Point3 FaceNormal = m_mesh->getFaceNormal(i); 
		//FaceNormal.Normalize();
		if ((V0 != V1) &&
			(V0 != V2) &&
			(V2 != V1))
		{
			AddFace(elemIdx, V0, V1, V2, UV0, UV1, UV2, FaceNormal.x, FaceNormal.y, FaceNormal.z);
		}

	}

	m_nbrVrtx = (unsigned long)m_Vertxs.size();
	m_ValidObj = true;
}

unsigned long CModObject::AddVerxt(DWORD _index)
{
	Point3 vert;
	Point3 norm;

	vert = m_mesh->verts[_index];
	norm = m_mesh->getRVert(_index).rn.getNormal();
	

	CVrtx myVect(vert.x,vert.y,vert.z,norm.x,norm.y,norm.z);

	std::vector <CVrtx>::iterator Iter;
	unsigned long i = 0;
	for ( Iter = m_Vertxs.begin( ); Iter != m_Vertxs.end( ); Iter++ )
	{
		if (*Iter == myVect)
			return i;
		i++;
	}

	m_Vertxs.push_back(myVect);
	return i;
}

CModObject::~CModObject(void)
{
	std::vector <CModElem*>::iterator Iter;
	for ( Iter = m_elements.begin( ); Iter != m_elements.end( ); Iter++ )
	{
		delete *Iter;
	}
	m_elements.clear();
	m_Vertxs.clear();
}

CModElem::CModElem(char* _name, Mtl* _material)
{
	strcpy(m_name,_name);
	m_material = _material;
}

bool CVrtx::operator==(const CVrtx& rSrc) const{

	if( (abs(x - rSrc.x) < 0.001) && 
		(abs(y - rSrc.y) < 0.001)  && 
		(abs(z - rSrc.z) < 0.001) )
		return true;
	else
		return false;

}
void CModObject::AddFace(MtlID _ElemIndex, 
						 unsigned long _i, unsigned long _j, unsigned long _k,
						 unsigned long _iUV, unsigned long _jUV, unsigned long _kUV,
						 float _nx, float _ny, float _nz)
{
	m_elements[_ElemIndex]->m_Faces.push_back(CFace(_i,_j,_k, _iUV, _jUV, _kUV, _nx, _ny, _nz));
}
unsigned long CModObject::AddUV(MtlID _ElemIndex, float _u, float _v)
{
	unsigned long i = 0;
	CModElem * elem = m_elements[_ElemIndex];
	std::vector <CUV>::iterator IterUV;

	for (IterUV = elem->m_UVs.begin(); IterUV < elem->m_UVs.end(); IterUV ++)
	{
		if (*IterUV == CUV(_u,_v))
			return i;
		i++;
	}

	elem->m_UVs.push_back(CUV(_u,_v));
	return i;
}
CFace::CFace(unsigned long _I,unsigned long _J,unsigned long _K,
			 unsigned long _IUV,unsigned long _JUV,unsigned long _KUV,
			 float _nx, float _ny, float _nz)
{
	I=_I; J=_J; K=_K;
	IUV=_IUV; JUV=_JUV; KUV=_KUV;
	nx = _nx; ny = _ny; nz = _nz;
}
bool CUV::operator==(const CUV& rSrc) const
{
	if( (U == rSrc.U) && 
		(V == rSrc.V))
		return true;
	else
		return false;
}

CUV::CUV(float _U,float _V)
{
	U=_U; V=_V;
}