
#include "GameFrameSky.h"
#include "GameFrameCamera.h"

CGFSky::CGFSky()
{
	GFParent = NULL;
	NumLibraryIndices = 0;
	LibraryIndices = NULL;
	RenderFlags = 0;
	Reset();
}

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

void CGFSky::Initialize(GameFrame *gfparent, list<int> &obj_lib_indices)
{
	list<int>::iterator index = obj_lib_indices.begin();

	Reset();
	GFParent = gfparent;

	NumLibraryIndices = (int) obj_lib_indices.size();
	LibraryIndices = new int[NumLibraryIndices];
	
	for(int i=0; i<NumLibraryIndices; i++)
	{
		LibraryIndices[i] = (*index);
		index++;
	}

	RenderFlags = 0;
}

void CGFSky::Reset(void)
{
	FrictionDrag = 0;
	X = Y = Z = 0;
	XVec = YVec = ZVec = 0;
	Yaw = Pitch = Roll = 0;
	YawVec = PitchVec = RollVec = 0;
	Up_Vector = D3DXVECTOR3(0,1,0);
	Right_Vector = D3DXVECTOR3(1,0,0);
	Look_Vector = D3DXVECTOR3(0,0,1);
}

void CGFSky::Destroy(void)
{
	GFParent = NULL;
	Camera = NULL;
	NumLibraryIndices = 0;
	SAFE_DELETE_ARRAY(LibraryIndices);
	RenderFlags = 0;
}

void CGFSky::LatchToCamera(CGFCamera *camera)
{
	Camera = camera;
}

void CGFSky::SetRenderFlags(DWORD flags)
{
	RenderFlags = flags;
}

void CGFSky::Move(DWORD type, float speed)
{
	if(type & ENTITY_FORWARD)
	{
		X += speed * Look_Vector.x;
		Y += speed * Look_Vector.y;
		Z += speed * Look_Vector.z;
	}
	else
	if(type & ENTITY_RIGHT)
	{
		X += speed * Right_Vector.x;
		Y += speed * Right_Vector.y;
		Z += speed * Right_Vector.z;
	}
	else
	if(type & ENTITY_UP)
	{
		X += speed * Up_Vector.x;
		Y += speed * Up_Vector.y;
		Z += speed * Up_Vector.z;
	}
}

void CGFSky::Rotate(DWORD type, float speed)
{
	if(type & ENTITY_YAW)
	{
		Yaw += speed;
	}
	else
	if(type & ENTITY_PITCH)
	{
		Pitch += speed;
	}
	else
	if(type & ENTITY_ROLL)
	{
		Roll += speed;
	}
}

void CGFSky::Update(void)
{
	X += XVec;
	Y += YVec;
	Z += ZVec;
	Yaw += YawVec;
	Pitch += PitchVec;
	Roll += RollVec;

	if(FrictionDrag != 0)
	{
		if(XVec < -.0001f) XVec += FrictionDrag; 
		else
		if(XVec >  .0001f) XVec -= FrictionDrag;

		if(YVec < -.0001f) YVec += FrictionDrag;
		else
		if(YVec >  .0001f) YVec -= FrictionDrag;

		if(ZVec < -.0001f) ZVec += FrictionDrag;
		else
		if(ZVec >  .0001f) ZVec -= FrictionDrag;

		if(YawVec    <  -.0001f) YawVec   += FrictionDrag;  
		else
		if(YawVec    >   .0001f) YawVec   -= FrictionDrag;

		if(PitchVec  <  -.0001f) PitchVec += FrictionDrag;
		else
		if(PitchVec  >   .0001f) PitchVec -= FrictionDrag;

		if(RollVec   <  -.0001f) RollVec  += FrictionDrag;
		else
		if(RollVec   >   .0001f) RollVec  -= FrictionDrag;
	}
}

int CGFSky::Render(void)
{
	if((NumLibraryIndices <= 0) || (LibraryIndices == NULL) || (GFParent == NULL)) return 0;

	if(Camera != NULL) 
	{
		X = Camera->X;
		Y = Camera->Y;
		Z = Camera->Z;
	}

	D3DXMATRIX YawMat, PitchMat, RollMat;
	D3DXMATRIX TransMat;
	D3DXMATRIX WorldMat;

	Up_Vector = D3DXVECTOR3(0,1,0);
	Right_Vector = D3DXVECTOR3(1,0,0);
	Look_Vector = D3DXVECTOR3(0,0,1);

	D3DXMatrixRotationAxis(&YawMat, &Up_Vector, Yaw);
	D3DXVec3TransformCoord(&Look_Vector, &Look_Vector, &YawMat);
	D3DXVec3TransformCoord(&Right_Vector, &Right_Vector, &YawMat);

	D3DXMatrixRotationAxis(&PitchMat, &Right_Vector, Pitch);
	D3DXVec3TransformCoord(&Look_Vector, &Look_Vector, &PitchMat);
	D3DXVec3TransformCoord(&Up_Vector, &Up_Vector, &PitchMat);

	D3DXMatrixRotationAxis(&RollMat, &Look_Vector, Roll);
	D3DXVec3TransformCoord(&Up_Vector, &Up_Vector, &RollMat);
	D3DXVec3TransformCoord(&Right_Vector, &Right_Vector, &RollMat);

	D3DXMatrixTranslation(&TransMat, X, Y, Z);
	D3DXMatrixIdentity(&WorldMat);

	D3DXMatrixMultiply(&WorldMat, &RollMat, &TransMat);
	D3DXMatrixMultiply(&WorldMat, &PitchMat, &WorldMat);
	D3DXMatrixMultiply(&WorldMat, &YawMat, &WorldMat);


	const OBJNODE *tmp_node = GFParent->ObjectLib[LibraryIndices[0]];
	int index = tmp_node->VertexLibraryIndex;
	
	//All objects within the same entity must be in the same VB and have the same FVF
	GFParent->D3DDevice->SetStreamSource(0, GFParent->VertexLib[index], GFParent->VertexLib.GetSize(index));
	GFParent->D3DDevice->SetVertexShader(GFParent->VertexLib.GetFVF(index));
	GFParent->D3DDevice->SetTransform(D3DTS_WORLD, &WorldMat);

	for(int i=0; i<NumLibraryIndices; i++)
	{
		tmp_node = GFParent->ObjectLib[LibraryIndices[i]];

		if(RenderFlags & RENDER_TEXTURED)
		{
			index = tmp_node->TextureLibraryIndex;
			if(index != -1)
			{
				GFParent->D3DDevice->SetTexture(0, GFParent->TextureLib[index]);
			}
		}

		if(RenderFlags & RENDER_LIT)
		{
			index = tmp_node->MaterialLibraryIndex;
			if(index != -1)
			{
				GFParent->D3DDevice->SetMaterial(&(GFParent->MaterialLib[index]));
			}
		}

		GFParent->D3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE);
		GFParent->D3DDevice->DrawPrimitive(tmp_node->PrimitiveType, tmp_node->StartVertex, tmp_node->PrimitiveCount);
		GFParent->D3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE);

		if(RenderFlags & RENDER_TEXTURED)
		{
			GFParent->D3DDevice->SetTexture(0, NULL);
		}
	}

	return 1;
}
