//	
//	Asura_PlatformRenderGlass.cpp
//	
//	Created by Andrew Weinkove - 15/04/2004
//	
//	Copyright (C) 2002 Rebellion, All Rights Reserved.
//	
//	PSP Glass rendering implementation
//	

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"
#include "Entity/Glass/Asura_ClientEntity_Glass.h"

#include "Camera/Asura_Camera.h"
#include "Core/Asura_Timers.h"
#include "Debugging/Asura_Assert.h"
#include "Rendering/Asura_Render.h"

#include "Rendering/Asura_PSP_Graphics.h"
#include "Rendering/Asura_PSP_TextureManagement.h"
#include <kernel.h>

struct Asura_PSP_RenderGlass_Vertex
{
	// fully 32bit - 24 bytes
	float			m_fU;
	float			m_fV;
	unsigned		m_uColour;
	float			m_afPosition[3];
};

const int iASURA_PSP_MAX_NUMBER_GLASS_VERTICES = 96; // Max of 24 panes of glass.
const int iASURA_PSP_GLASS_VERTEX_FORMAT = SCEGU_TEXTURE_FLOAT | SCEGU_VERTEX_FLOAT | SCEGU_COLOR_PF8888;
static Asura_PSP_RenderGlass_Vertex s_apxGlassVertices[iASURA_PSP_MAX_NUMBER_GLASS_VERTICES] __attribute__ ((aligned(16)));

static u_int s_uLastFrameStamp = 0;
static u_int s_uGlassVerticesUsedThisFrame = 0;

// (AW - 07/10/05) - Glass renderer. Pretty inefficient, but should suffice as long as we don't start rendering loads
// of glass. May cause clipping issues if trying to draw large panes near the camera.
void Asura_ClientEntity_Glass::Platform_Render( unsigned uCamVisFlags )
{
	// Reset the vertices counter if necessary
	if (Asura_Timers::GetFrameNumber() != s_uLastFrameStamp)
	{
		s_uLastFrameStamp = Asura_Timers::GetFrameNumber();
		s_uGlassVerticesUsedThisFrame = 0;
	}
	else if (s_uGlassVerticesUsedThisFrame + 4 > iASURA_PSP_MAX_NUMBER_GLASS_VERTICES)
	{
		Asura_Assert(false, "Ran out of vertices to draw glass with");
		return;
	}
	// Setup camera settings.
	Asura_Assert(Asura_Camera::GetNumberOfCameras() == 1, "Glass renderer assumes 1 camera");
	Asura_Camera::SetCameraIndex(0);
	Asura_Render::ApplyCameraSettings();

	// Setup render states.
	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_SINGLE_PASS);
	Asura_PSP_Graphics::SetMaterialType( ASURA_PSP_GRAPHICS_MATERIALTYPE_ENV );
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(false);
	Asura_PSP_TextureManagement::RequestTextureIndex(m_iTextureIndex);
	Asura_Render::CurrentStates.RequestCullMode(ASURA_CULLMODE_NONE);
	Asura_PSP_Graphics::SetUseColourDoubling(false);
	Asura_PSP_Graphics::SetUseLighting(false);
	Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_NORMAL);
	Asura_Render::CurrentStates.RequestZBufferCompareMode(ASURA_ZBUFFERCMP_LESSEQUAL);


	// Setup vertices.
	Asura_PSP_RenderGlass_Vertex* pxGlassVertices = &s_apxGlassVertices[s_uGlassVerticesUsedThisFrame];
	Asura_Vector_3 axVertices[4];
	axVertices[0] = m_xPane.CornerPosition;
	axVertices[1] = m_xPane.CornerPosition + (Asura_Vector_3(m_xPane.Dimensions.x, 0.0f, 0.0f) * m_xPane.Orientation);
	axVertices[2] = m_xPane.CornerPosition + (Asura_Vector_3(0.0f, m_xPane.Dimensions.y, 0.0f) * m_xPane.Orientation);
	axVertices[3] = m_xPane.CornerPosition + (Asura_Vector_3(m_xPane.Dimensions.x, m_xPane.Dimensions.y, 0.0f) * m_xPane.Orientation);

	u_int uColourABGR = ((m_uColour & 0x00ff0000) >> 16) | ((m_uColour & 0x000000ff) << 16) | (m_uColour & 0xff00ff00);
	for (int i=0;i<4;i++)
	{
		pxGlassVertices[i].m_afPosition[0] = axVertices[i].x;
		pxGlassVertices[i].m_afPosition[1] = axVertices[i].y;
		pxGlassVertices[i].m_afPosition[2] = axVertices[i].z;
		pxGlassVertices[i].m_uColour = uColourABGR;
		if (m_iTextureIndex != ASURA_TEXTURE_NONE)
		{
			Asura_Assert( m_afU && m_afV, "" );
			pxGlassVertices[i].m_fU = m_afU[i];
			pxGlassVertices[i].m_fV = m_afV[i];
		}
	}

	// Render strip
	sceKernelDcacheWritebackAll();
	
	GUM_DrawArray
	(
		SCEGU_PRIM_TRIANGLE_STRIP, 
		iASURA_PSP_GLASS_VERTEX_FORMAT,
		4, 
		NULL, 
		pxGlassVertices
	);

	// Update counters
	s_uGlassVerticesUsedThisFrame += 4;
#if defined ASURA_RENDER_TTYPES
	Asura_Render::AddToTrianglesRendered(2,1,ASURA_RENDER_TTYPE_GLS);
#else
	Asura_Render::AddToTrianglesRendered(2);
#endif
}

