//////////////////////////////////////////////////////////////////////////////
//
// Asura_Chunk_ResourceFile_PS3_Environment.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header.
#include "Asura_Chunk_ResourceFile_PS3_Environment.h"

// Engine independent.
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Core/Asura_Material_System.h"
#include "Core/Asura_MaterialResponse_System.h"

// Engine platform-specific.
#include "Rendering/Asura_PS3_EnvironmentRenderer.h"
#include "Rendering/Asura_PS3_Graphics.h"
#include "Rendering/Asura_PS3_GCM_IndexBuffer.h"
#include "Rendering/Asura_PS3_GCM_VertexBuffer.h"
#include "Rendering/Shaders/Asura_PS3_GCM_ShadersLibrary.h"
#include "Rendering/Asura_PS3_MaterialResponse_System.h"
#include "ChunkSystem/Asura_Chunk_ResourceFile_PS3.h"
#include "Rendering/ShadersDefinition/FP/Water_FP.h"
#if defined ASURA_USE_NEW_VISIBILITY_SYSTEM
#include "Visibility/Asura_Visibility_System.h"
#endif	//defined ASURA_USE_NEW_VISIBILITY_SYSTEM

// C L A S S   I M P L E M E N T A T I O N S /////////////////////////////////

// Modified		: Catalin Arsenescu (23-April-2007) -> Copied from xBox360
void Asura_Chunk_ResourceFile_PS3_Environment::Process( const char* szFilename, Asura_Chunk_Stream& xStream )
{
	if( Version != ASURA_PS3_ENVIRONMENT_CHUNK_VERSION )
	{
		Asura_Assertf( false, ("Invalid environment chunk version (%d) encountered. Should be %d. You may need new code, or to re-export the level.", Version, ASURA_PS3_ENVIRONMENT_CHUNK_VERSION) );
		return;
	}
	u_int	uNumberOfStrips;

	// Read the data...
	xStream >> uNumberOfStrips;

	Asura_PS3_EnvironmentRenderer::s_uNumberOfStrips = uNumberOfStrips;

	// allocate storage space 
	Asura_PS3_EnvironmentRenderer::s_pxStrips	= new Asura_PS3_EnvironmentRenderer_Strip[ uNumberOfStrips ];
	Asura_PS3_EnvironmentRenderer::s_pxBuffers	= new Asura_PS3_EnvironmentRenderer_Buffer[ uNumberOfStrips ];

	// load in strip descriptions, all in one go
	xStream.Read( sizeof( Asura_PS3_EnvironmentRenderer_Strip ) * uNumberOfStrips, Asura_PS3_EnvironmentRenderer::s_pxStrips );


#if 0 //We can no longer use this code to find out the maximum number of strips for every type of rendering
	//in the moment we load the environment the data we don't have any informations about the textures
	int iTransparentStrip	= 1;	// Last value -1 to know when we need to stop rendering
	int iNonAlphaTest		= 1;	// Last value -1 to know when we need to stop rendering
	int iAlphaTest			= 1;	// Last value -1 to know when we need to stop rendering
	int iWaterStrips		= 1;	// Last value -1 to know when we need to stop rendering

	for( u_int i = 0; i < uNumberOfStrips; ++i )
	{
#if defined ASURA_USE_NEW_VISIBILITY_SYSTEM
		Asura_PS3_EnvironmentRenderer::s_pxStrips[ i ].m_iModuleIndex = 0;
#endif
		const Asura_MaterialResponse* const pxMaterial1 = Asura_MaterialResponse_System::GetMaterialByHashID( Asura_PS3_EnvironmentRenderer::s_pxStrips[ i ].m_auMaterialResponseHashIDs[0] );
		if( pxMaterial1 )
		{
			if( pxMaterial1->GetSpecialFXMode() == Asura_MaterialResponse::SPECIALFX_MODE_WATER )
			{
				++iWaterStrips;
			}
			if( pxMaterial1->IsTransparent() )
			{
				++iTransparentStrip;
			}
			if( pxMaterial1->GetTransparencyMap() != ASURA_TEXTURE_NONE )
			{
				++iAlphaTest;
			}
			++iNonAlphaTest;
		}
		else
		{
			++iNonAlphaTest;
		}
	}

	Asura_PS3_EnvironmentRenderer::s_aiQueuedWaterStrips	= new int[ iWaterStrips ];
	Asura_PS3_EnvironmentRenderer::s_aiSolidAlphaTestStrips	= new int[ iAlphaTest ];
	Asura_PS3_EnvironmentRenderer::s_aiTransparentStrips	= new int[ iTransparentStrip ];
	Asura_PS3_EnvironmentRenderer::s_aiSolidStrips			= new int[ iNonAlphaTest ];
#else
	Asura_PS3_EnvironmentRenderer::s_aiQueuedWaterStrips	= new int[ uNumberOfStrips+1 ];
	Asura_PS3_EnvironmentRenderer::s_aiSolidAlphaTestStrips	= new int[ uNumberOfStrips+1 ];
	Asura_PS3_EnvironmentRenderer::s_aiTransparentStrips	= new int[ uNumberOfStrips+1 ];
	Asura_PS3_EnvironmentRenderer::s_aiSolidStrips			= new int[ uNumberOfStrips+1 ];

	Asura_PS3_EnvironmentRenderer::s_aiQueuedWaterStrips[ 0 ]		= -1;
	Asura_PS3_EnvironmentRenderer::s_aiSolidAlphaTestStrips[ 0 ]	= -1;
	Asura_PS3_EnvironmentRenderer::s_aiTransparentStrips[ 0 ]		= -1;
	Asura_PS3_EnvironmentRenderer::s_aiSolidStrips[ 0 ]				= -1;
#endif
	Asura_PS3_EnvironmentRenderer::s_abStripInRenderList	= new bool[ uNumberOfStrips ];
	Asura_Mem::Set( Asura_PS3_EnvironmentRenderer::s_abStripInRenderList, false, uNumberOfStrips );

	#if !defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM

		for( u_int u = 0; u < uNumberOfStrips; ++u )
		{
			Asura_PS3_EnvironmentRenderer_Strip& xStrip = Asura_PS3_EnvironmentRenderer::s_pxStrips[u];
			xStrip.m_iMaterial = Asura_Material_System::ConvertIndex( xStrip.m_iMaterial );
		}

	#endif // !defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM


	// get number of vertices	
	u_int uNumVertexBuffers;
	xStream >> uNumVertexBuffers;
	Asura_PS3_EnvironmentRenderer::s_uNumVertexBuffers = uNumVertexBuffers;

	u_int* uNumVerticesInBuffer = new u_int[uNumVertexBuffers];

	for ( u_int i=0; i < uNumVertexBuffers; i++ )
	{
		xStream >> uNumVerticesInBuffer[i];
		
		Asura_Assertf( uNumVerticesInBuffer[i] < 65536, ("Too many vertices or garbage 0x%08x", uNumVerticesInBuffer[i]) );
	}


	Asura_PS3_EnvironmentRenderer::s_pxVertexBuffer = new Asura_PS3_GCM_VertexBuffer[uNumVertexBuffers];

	for ( u_int i=0; i < uNumVertexBuffers; i++ )
	{
		// load in vertices
		Asura_PS3_EnvironmentRenderer::s_pxVertexBuffer[i].Initialise( Asura_PS3_EnvironmentRenderer::GetVertexSize(), uNumVerticesInBuffer[i], CELL_GCM_LOCATION_LOCAL );

		// lock the buffer
		void* pBuffer = Asura_PS3_EnvironmentRenderer::s_pxVertexBuffer[i].LockForWriting();

		// read in data
		xStream.Read( uNumVerticesInBuffer[i] * Asura_PS3_EnvironmentRenderer::GetVertexSize(), pBuffer );

		// unlock the buffer
		Asura_PS3_EnvironmentRenderer::s_pxVertexBuffer[i].Unlock();
	}


	// load in indices
	for ( u_int u=0; u<uNumberOfStrips; ++u )
	{
		Asura_PS3_GCM_IndexBuffer& xIndexBuffer	= Asura_PS3_EnvironmentRenderer::s_pxBuffers[u].m_xIndexBuffer;

		// generate the index buffer
		u_int uIndexBufferSize = Asura_PS3_EnvironmentRenderer::s_pxStrips[u].m_uNumberOfIndices * sizeof( short );
		xIndexBuffer.Initialise( Asura_PS3_EnvironmentRenderer::s_pxStrips[u].m_uNumberOfIndices, CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, CELL_GCM_LOCATION_LOCAL );

		// lock the buffer
		void* pBuffer = xIndexBuffer.LockForWriting();

		// read in data
		xStream.Read( uIndexBufferSize, pBuffer );

		// unlock the buffer
		xIndexBuffer.Unlock();
	}

	// read in the Anti-Alias edges.
	u_int uTotalNumEdgeIndices;
	xStream >> uTotalNumEdgeIndices;
	if ( uTotalNumEdgeIndices > 0 )
	{
		Asura_PS3_EnvironmentRenderer::s_xAntiAliasEdges.Initialise( uTotalNumEdgeIndices, CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16, CELL_GCM_LOCATION_LOCAL, true );

		u_short* puIdxOut = static_cast<u_short*>(Asura_PS3_EnvironmentRenderer::s_xAntiAliasEdges.LockForWriting());
		xStream.Read( uTotalNumEdgeIndices*sizeof(u_short), puIdxOut );
	}
}
