// X3DEffectPlane.cpp: implementation of the CX3DEffectPlane class.
//
//////////////////////////////////////////////////////////////////////

#include "X3DEffect.h"
#include "X3DEffectPlane.h"
#include "SceneManager.h"
#include "GMMemory.h"

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

CX3DEffectPlane::CX3DEffectPlane()
{
	m_dwSrcBlending = D3DBLEND_SRCALPHA;
	m_dwDestBlending = D3DBLEND_ONE;

	m_bTexAni = FALSE;

	m_lpVertices = NULL;
	m_lpVerticesBlend = NULL;
}

CX3DEffectPlane::~CX3DEffectPlane()
{
	//if(m_lpVerticesBlend) { m_lpVerticesBlend->Release(); m_lpVerticesBlend = NULL; }
	//if(m_lpVertices) { m_lpVertices->Release(); m_lpVertices = NULL; }
	if(m_lpVerticesBlend) { 
		if(CSceneManager::ms_pBufferPools)
			CSceneManager::ms_pBufferPools->UnRef(Caldron::Scene::D3DBUFFEROBJ_VERTEX,m_lpVerticesBlend);
		else
			m_lpVerticesBlend->Release(); 
		m_lpVerticesBlend = NULL; 
	}
	if(m_lpVertices) { 
		if(CSceneManager::ms_pBufferPools)
			CSceneManager::ms_pBufferPools->UnRef(Caldron::Scene::D3DBUFFEROBJ_VERTEX,m_lpVertices);
		else
			m_lpVertices->Release(); 
		m_lpVertices = NULL; 
	}


}

void CX3DEffectPlane::Create(unsigned long dwStartFrame, unsigned long dwEndFrame)
{
	m_dwStartFrame = dwStartFrame;
	m_dwEndFrame = dwEndFrame;
}

BOOL CX3DEffectPlane::CreateBuffer(void)
{
	if(m_lpVerticesBlend) { 
		CSceneManager::ms_pBufferPools->UnRef(Caldron::Scene::D3DBUFFEROBJ_VERTEX,m_lpVerticesBlend);
		//m_lpVerticesBlend->Release(); 
		m_lpVerticesBlend = NULL; 
	}
	if(m_lpVertices) { 
		CSceneManager::ms_pBufferPools->UnRef(Caldron::Scene::D3DBUFFEROBJ_VERTEX,m_lpVertices);
	//	m_lpVertices->Release(); 
		m_lpVertices = NULL; 
	}
//	m_lpVertices = CSceneManager::ms_pBufferPools->GetVertexBuffer(4 * sizeof(LVertex),LVERTEXFVF,true);
//	m_lpVerticesBlend = CSceneManager::ms_pBufferPools->GetVertexBuffer(4 * sizeof(LVertex),LVERTEXFVF,true);
	m_lpVertices = CSceneManager::ms_pBufferPools->GetVertexBuffer(4 * sizeof(LVertex),LVERTEXFVF,false);
	m_lpVerticesBlend = CSceneManager::ms_pBufferPools->GetVertexBuffer(4 * sizeof(LVertex),LVERTEXFVF,false);

/*
	if(m_lpVerticesBlend) { m_lpVerticesBlend->Release(); m_lpVerticesBlend = NULL; }
	if(m_lpVertices) { m_lpVertices->Release(); m_lpVertices = NULL; }

	m_lpD3DDevice->CreateVertexBuffer( 4 * sizeof(LVertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, LVERTEXFVF, D3DPOOL_DEFAULT, &m_lpVertices );
	m_lpD3DDevice->CreateVertexBuffer( 4 * sizeof(LVertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, LVERTEXFVF, D3DPOOL_DEFAULT, &m_lpVerticesBlend );
*/
	return TRUE;
}

void CX3DEffectPlane::Render(void)
{
	if(!m_bVisibility)
		return;
	if(m_lpVertices == NULL) return;

	matrix matWorld;
	matWorld.MakeIdent();
	quaternion *quatAxis = ((CX3DEffect *)m_lpLocalEffect)->GetAxis();
	if(quatAxis) { z3d::MatrixRotationQuaternion(matWorld, (*quatAxis)); }
	if(((CX3DEffect *)m_lpLocalEffect)->GetCenter())
	{
		vector3 *vecTemp = ((CX3DEffect *)m_lpLocalEffect)->GetCenter();
		matWorld._41 = vecTemp->x;
		matWorld._42 = vecTemp->y;
		matWorld._43 = vecTemp->z;
	}
	m_lpD3DDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX *)&matWorld);
	m_lpD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
	m_lpD3DDevice->SetTexture(0, GetTexture());
	m_lpD3DDevice->SetRenderState(D3DRS_SRCBLEND, m_dwSrcBlending);
	m_lpD3DDevice->SetRenderState(D3DRS_DESTBLEND, m_dwDestBlending);
	m_lpD3DDevice->SetStreamSource(0, m_lpVertices, sizeof(LVertex));
	m_lpD3DDevice->SetVertexShader(LVERTEXFVF);
	m_lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	if(m_bTexAni)
	{
		m_lpD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		m_lpD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
		m_lpD3DDevice->SetStreamSource(0, m_lpVerticesBlend, sizeof(LVertex));
		m_lpD3DDevice->SetVertexShader(LVERTEXFVF);
		m_lpD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
	}
}

BOOL CX3DEffectPlane::Interpolation(float fFrame)
{

///////////////////////////////////////////////////////////////////////////////////
	if(!m_lstCenter.Interpolation(fFrame, m_vecCenter)) return FALSE;
	if(!m_lstAxis.InterpolationQ(fFrame, m_quatAxis)) return FALSE;

	if(!m_lstWidth.Interpolation(fFrame, m_fWidth)) return FALSE;
	if(!m_lstHeight.Interpolation(fFrame, m_fHeight)) return FALSE;
	if(m_Scale[0] != 1.0f) {
		m_fWidth *=m_Scale[0];
		m_fHeight *=m_Scale[0];
		m_vecCenter.x *=m_Scale[0];
		m_vecCenter.z *=m_Scale[0];
		m_vecCenter.y *=(m_Scale[0]);
	}

	if(!m_lstColor.InterpolationC(fFrame, m_lColor)) return FALSE;
	if(m_bTexAni)
	{
		if(!m_lstTexFrame.Interpolation(fFrame, m_fTexFrame)) return FALSE;
	} else
	{
		if(!m_lstStartU.Interpolation(fFrame, m_fStartU)) return FALSE;
		if(!m_lstStartV.Interpolation(fFrame, m_fStartV)) return FALSE;
		if(!m_lstTileU.Interpolation(fFrame, m_fTileU)) return FALSE;
		if(!m_lstTileV.Interpolation(fFrame, m_fTileV)) return FALSE;
	}
///////////////////////////////////////////////////////////////////////////////////

	if(m_bVisibility) {
		

		{
	///////////////////////////////////////////////////////////////////////////////////
			LVertex *pVertices, *pVerticesBlend;
//			if(FAILED( m_lpVertices->Lock( 0, 4 * sizeof(LVertex), (unsigned char **)&pVertices, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK) ) ) return FALSE;
//			if(FAILED( m_lpVerticesBlend->Lock( 0, 4 * sizeof(LVertex), (unsigned char **)&pVerticesBlend, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK) ) ) return FALSE;
			if(FAILED( m_lpVertices->Lock( 0, 0, (unsigned char **)&pVertices, 0) ) ) return FALSE;
			if(FAILED( m_lpVerticesBlend->Lock( 0, 0, (unsigned char **)&pVerticesBlend, 0) ) ) return FALSE;

			float f1, f2;
			float fStartU, fStartV, fEndU, fEndV;
			float fStartBU, fStartBV, fEndBU, fEndBV;
			if(m_bTexAni)
			{
				f1 = (((long)m_fTexFrame) % 4) * 0.25;
				f2 = (((long)m_fTexFrame) / 4) * 0.25;
				fStartU = f1;
				fStartV = f2;
				fEndU = f1 + 0.25f;
				fEndV = f2 + 0.25f;

				f1 = (((long)ceilf(m_fTexFrame)) % 4) * 0.25;
				f2 = (((long)ceilf(m_fTexFrame)) / 4) * 0.25;
				fStartBU = f1;
				fStartBV = f2;
				fEndBU = f1 + 0.25f;
				fEndBV = f2 + 0.25f;
			} else
			{
				fStartBU = fStartU = m_fStartU;
				fStartBV = fStartV = m_fStartV;
				fEndBU = fEndU = m_fTileU;
				fEndBV = fEndV = m_fTileV;
			}

			pVertices[0].v = vector3(-(m_fWidth / 2), 0,  (m_fHeight / 2));
			pVertices[1].v = vector3( (m_fWidth / 2), 0,  (m_fHeight / 2));
			pVertices[2].v = vector3(-(m_fWidth / 2), 0, -(m_fHeight / 2));
			pVertices[3].v = vector3( (m_fWidth / 2), 0, -(m_fHeight / 2));

			z3d::VectorRotate(pVertices[0].v, pVertices[0].v, m_quatAxis);
			z3d::VectorRotate(pVertices[1].v, pVertices[1].v, m_quatAxis);
			z3d::VectorRotate(pVertices[2].v, pVertices[2].v, m_quatAxis);
			z3d::VectorRotate(pVertices[3].v, pVertices[3].v, m_quatAxis);

	/*		quaternion *quatAxis = ((CX3DEffect *)m_lpLocalEffect)->GetAxis();
			if(quatAxis)
			{
				z3d::VectorRotate(pVertices[0].v, pVertices[0].v, (*quatAxis));
				z3d::VectorRotate(pVertices[1].v, pVertices[1].v, (*quatAxis));
				z3d::VectorRotate(pVertices[2].v, pVertices[2].v, (*quatAxis));
				z3d::VectorRotate(pVertices[3].v, pVertices[3].v, (*quatAxis));
			}

			pVerticesBlend[0].v = pVertices[0].v += m_vecCenter + (*((CX3DEffect *)m_lpLocalEffect)->GetCenter());
			pVerticesBlend[1].v = pVertices[1].v += m_vecCenter + (*((CX3DEffect *)m_lpLocalEffect)->GetCenter());
			pVerticesBlend[2].v = pVertices[2].v += m_vecCenter + (*((CX3DEffect *)m_lpLocalEffect)->GetCenter());
			pVerticesBlend[3].v = pVertices[3].v += m_vecCenter + (*((CX3DEffect *)m_lpLocalEffect)->GetCenter());*/
			pVerticesBlend[0].v = pVertices[0].v += m_vecCenter;
			pVerticesBlend[1].v = pVertices[1].v += m_vecCenter;
			pVerticesBlend[2].v = pVertices[2].v += m_vecCenter;
			pVerticesBlend[3].v = pVertices[3].v += m_vecCenter;

			pVertices[0].tu = fStartU;					pVertices[0].tv = fStartV;
			pVertices[1].tu = fEndU;					pVertices[1].tv = fStartV;
			pVertices[2].tu = fStartU;					pVertices[2].tv = fEndV;
			pVertices[3].tu = fEndU;					pVertices[3].tv = fEndV;
			pVerticesBlend[0].tu = fStartBU;			pVerticesBlend[0].tv = fStartBV;
			pVerticesBlend[1].tu = fEndBU;			pVerticesBlend[1].tv = fStartBV;
			pVerticesBlend[2].tu = fStartBU;			pVerticesBlend[2].tv = fEndBV;
			pVerticesBlend[3].tu = fEndBU;			pVerticesBlend[3].tv = fEndBV;
	///////////////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////////////
			pVertices[0].diff = pVertices[1].diff = pVertices[2].diff = pVertices[3].diff = m_lColor;
			pVerticesBlend[0].diff = pVerticesBlend[1].diff = pVerticesBlend[2].diff = pVerticesBlend[3].diff = m_lColor;
			if(m_bTexAni)
			{
				pVertices[3].diff.a *= (floorf(m_fTexFrame + 1.0f) - m_fTexFrame);
				pVertices[0].diff.a = pVertices[1].diff.a = pVertices[2].diff.a = pVertices[3].diff.a;
				pVerticesBlend[3].diff.a *= (m_fTexFrame - floorf(m_fTexFrame));
				pVerticesBlend[0].diff.a = pVerticesBlend[1].diff.a = pVerticesBlend[2].diff.a = pVerticesBlend[3].diff.a;
			}
			pVertices[0].spec = pVertices[1].spec = pVertices[2].spec = pVertices[3].spec = color(0xFF, 0xFF, 0xFF, 0xFF);
			pVerticesBlend[0].spec = pVerticesBlend[1].spec = pVerticesBlend[2].spec = pVerticesBlend[3].spec = color(0xFF, 0xFF, 0xFF, 0xFF);
	///////////////////////////////////////////////////////////////////////////////////
			m_lpVerticesBlend->Unlock();
			m_lpVertices->Unlock();
		}
	}
	return TRUE;
}

void CX3DEffectPlane::Load(FILE *fp, const char *strOriginalPath)
{
	fread(&m_bTexAni, 4, 1, fp);
	fread(&m_dwSrcBlending, 4, 1, fp);
	fread(&m_dwDestBlending, 4, 1, fp);
	m_lstAxis.Load(fp, m_quatAxis);
	m_lstCenter.Load(fp, m_vecCenter);
	m_lstColor.Load(fp, m_lColor);
	m_lstWidth.Load(fp, m_fWidth);
	m_lstHeight.Load(fp, m_fHeight);
	m_lstStartU.Load(fp, m_fStartU);
	m_lstStartV.Load(fp, m_fStartV);
	m_lstTileU.Load(fp, m_fTileU);
	m_lstTileV.Load(fp, m_fTileV);
	m_lstTexFrame.Load(fp, m_fTexFrame);
	if(m_Scale[0] != 1.0f) {
		m_vecCenter.x *=m_Scale[0];
		m_vecCenter.z *=m_Scale[0];
		m_vecCenter.y *=(m_Scale[0]);

		m_fWidth *=m_Scale[0];
		m_fHeight *=m_Scale[0];
	}
}

void CX3DEffectPlane::Save(FILE *fp, const char *strOriginalPath)
{
	fwrite(&m_bTexAni, 4, 1, fp);
	fwrite(&m_dwSrcBlending, 4, 1, fp);
	fwrite(&m_dwDestBlending, 4, 1, fp);
	m_lstAxis.Save(fp);
	m_lstCenter.Save(fp);
	m_lstColor.Save(fp);
	m_lstWidth.Save(fp);
	m_lstHeight.Save(fp);
	m_lstStartU.Save(fp);
	m_lstStartV.Save(fp);
	m_lstTileU.Save(fp);
	m_lstTileV.Save(fp);
	m_lstTexFrame.Save(fp);
}
