// PatchMeshObject.cpp: implementation of the PatchMeshObject class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "CryViewer.h"
#include "PatchMeshObject.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
PatchMeshObject::PatchMeshObject()
{
	vertices	=NULL;
	patches		=NULL;
	propstr		=NULL;
	links		=NULL;
	uvs			=NULL;
	bones		=NULL;
	texPatches	=NULL;
	nLinks		=NULL;
	links		=NULL;
	BoneNameTable = NULL;

}

PatchMeshObject::~PatchMeshObject()
{
	if(propstr)		free(propstr);
	if(vertices)	free(vertices);
	if(patches)		free(patches);

}

bool PatchMeshObject::Load(FILE *f, long pos)
{
	if(fseek(f,pos,SEEK_SET)) return true;

	int res=fread(&chunk,sizeof(chunk),1,f);
	if(res!=1) return true;

	//read prop
	if(chunk.PropStrLen)
	{
		propstr=(char*)calloc(chunk.PropStrLen+1,1);
		assert(propstr);
		res=fread(propstr,chunk.PropStrLen,1,f);
		if(res!=1) return true;
	}

	//read verts
	vertices=(CryPoint3*)calloc(sizeof(CryPoint3),chunk.nVerts);
	assert(vertices);
	res=fread(vertices,sizeof(CryPoint3),chunk.nVerts,f);
	if(res!=chunk.nVerts) return true;

	//read faces
	patches=(PatchItem*)calloc(sizeof(PatchItem),chunk.nPatches);
	assert(patches);
	for(int i=0;i<chunk.nPatches;i++)
	{
		res=fread(&(patches[i].Type),sizeof(int),1,f);
		if(res!=1) return true;

		int readcount=(patches[i].Type == 3)?12:16;
		res=fread(&(patches[i].idx),sizeof(int),readcount,f);
		if(res!=readcount) return true;
	};

	//read tverts
	if(chunk.nTVerts)
	{
		uvs=(CryUV*)calloc(sizeof(CryUV),chunk.nTVerts);
		assert(uvs);
		res=fread(uvs,sizeof(CryUV),chunk.nTVerts,f);
		if(res!=chunk.nTVerts) return true;

		//read Tfaces
		texPatches=(CryTexPatch*)calloc(chunk.nPatches,sizeof(CryTexPatch));
		assert(texPatches);

		res=fread(texPatches,sizeof(CryTexPatch),chunk.nPatches,f);
		if(res!=chunk.nPatches) return true;
	}

	//read Links
	if(chunk.HasBoneInfo)
	{
		nLinks=(int *)calloc(sizeof(int),chunk.nVerts);
		assert(nLinks);

		links=(CryLink **)calloc(sizeof(CryLink *),chunk.nVerts);
		assert(links);

		for(int i=0;i<chunk.nVerts;i++)
		{
			int res=fread(nLinks+i,sizeof(int),1,f);
			if(res!=1) return true;

			char s[256];
			sprintf(s,"\nnLinks for vertex %4d = %4d",i,nLinks[i]);
			OutputDebugString(s);

			links[i]=(CryLink *)calloc(sizeof(CryLink),nLinks[i]);
			assert(links[i]);

			res=fread(links[i],sizeof(CryLink),nLinks[i],f);
			if(res!=nLinks[i]) return true;

			for(int j=0;j<nLinks[i];j++)
			{
				sprintf(s,"(Blend=%f) ",links[i][j].Blending);
				OutputDebugString(s);
			}
		}
	}

	return false;
}

RECT PatchMeshObject::Paint(HDC hdc, CryMatrix &tm, bool dispwire, bool dispvert)
{
	if(dispwire)
	{
		for(int i=0;i<chunk.nPatches;i++)
		{
			int count=(patches[i].Type==3) ? 12 : 16;
			CryPoint3 a[16];
			PatchItem &patch=patches[i];
			for(int j=0;j<count;j++) a[j]=vertices[patch.idx[j]]*tm;

			int cevrecount=(patches[i].Type==3) ? 9 : 12;
			
			if(patches[i].Type==3)
			{
				MoveToEx(hdc,a[0].x, a[0].y, NULL);
				for(int j=1;j<12;j++) LineTo(hdc,  a[j].x, a[j].y);
				LineTo(hdc,a[0].x, a[0].y);


			}
			else
			{
				MoveToEx(hdc,a[0].x, a[0].y, NULL);
				for(int j=1;j<12;j++) LineTo(hdc,  a[j].x, a[j].y);
				LineTo(hdc,a[0].x, a[0].y);

			}
		}
	}

	CRect rec;
	rec.SetRectEmpty();
	rec.top=1000000;
	rec.bottom = -1000000;
	rec.left = 1000000;
	rec.right=-1000000;

	for(int i=0;i<chunk.nVerts;i++)
	{
		CryPoint3 pp=vertices[i]*tm;

		if(dispvert)
		{
			//point
			SetPixel(hdc,pp.x, pp.y, RGB(0,255,0));
		}

		rec.top		=min(rec.top, pp.y);
		rec.bottom	=max(rec.bottom, pp.y);
		rec.left	=min(rec.left,pp.x);
		rec.right	=max(rec.right,pp.x);
	}

	return rec;

}

void PatchMeshObject::ConstructBoneList(int nAnimBones, NAME_ENTITY *AnimBoneNameTable, Bone *rootbone)
{
	if(!nBones)		return;
	if(!nAnimBones) return;

	bones=(Bone **)calloc(sizeof(Bone *), nBones);
	assert(bones);

	for(int i=0;i<nBones;i++)
	{
		int AnimBoneID=-1;
		NAME_ENTITY *gent=BoneNameTable+i;
		for(int j=0;j<nAnimBones;j++)
		{
			NAME_ENTITY *aent=AnimBoneNameTable+j;
			if(!strcmp(gent->name, aent->name))
			{
				AnimBoneID = j;
				break;
			}
		}

		if(AnimBoneID != -1)
		{
			bones[i]=rootbone->FindBone(AnimBoneID);
		}
		else
		{
			MessageBox(NULL,"Bone not found in the animation file!",gent->name,MB_OK);
		}
	}
}

void PatchMeshObject::Deform()
{
	if(!bones) return;

	for(int i=0;i<chunk.nVerts;i++)
	{
		CryPoint3 p;
		p.x=p.y=p.z=0.0f;

		for(int j=0;j<nLinks[i];j++)
		{
			CryLink *link	= links[i]+j;
			Bone	*bone	= bones[link->BoneID];	

			p+=(link->offset * bone->cache_mat) * link->Blending;
		}

		vertices[i]=p;
	}
}

void PatchMeshObject::SetBoneNameList(int count, NAME_ENTITY *names)
{
	if(BoneNameTable) free(BoneNameTable);
	BoneNameTable=(NAME_ENTITY *) calloc(sizeof(NAME_ENTITY),count);
	assert(BoneNameTable);

	memcpy(BoneNameTable,names,count*sizeof(NAME_ENTITY));
	nBones=count;
}
*/