//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS3_CharacterRenderer.h
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_PS3_CHARACTERRENDERER_H___
#define ___ASURA_PS3_CHARACTERRENDERER_H___ 1

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

// Asura independent
#include "Core/Asura_HeapArray.h"

// Engine platform-specific.
#include "Rendering/Asura_PS3_GCM_IndexBuffer.h"
#include "Rendering/Asura_PS3_GCM_VertexBuffer.h"
#include "Rendering/Asura_PS3_SPU_SkinningTypes.h"

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_Animation;
class Asura_Hierarchy_Skin;
class Asura_Matrix_3x3;
class Asura_Shadow;
class Asura_Vector_3;

class Asura_PS3_CharacterRenderer_Skin;
class Asura_PS3_SPU_Skinning;
class Asura_Platform_Animation_RenderCache;

#ifndef ASURA_HIERARCHY_QUAD
#error ASURA_HIERARCHY_QUAD must be defined
#endif

// C L A S S E S /////////////////////////////////////////////////////////////
// DaveR 06/12/06 - This is called a 'strip' now, not a material, to match the
// PC version, and because we'll soon support multiple skin elements
struct Asura_PS3_CharacterRenderer_Strip
{
	Asura_Hash_ID	m_uFPHashID;
	Asura_Hash_ID	m_auMaterialResponseHashIDs[2];
	u_int			m_uNumIndices;
	u_int			m_uStartIndex;
	int				m_iElementID;
};

class Asura_PS3_CharacterRenderer_Skin
{
	friend class Asura_Chunk_ResourceFile_PS3_Character;
	friend class Asura_PS3_CharacterRenderer;
	friend class Asura_PS3_SPU_Skinning;

public:

	// Constructor / destructor
	Asura_PS3_CharacterRenderer_Skin();
	~Asura_PS3_CharacterRenderer_Skin();

	// Functions
	u_int GetNumMaterials() const { return m_uNumStrips; }
	const Asura_PS3_CharacterRenderer_Strip& GetStrip( const u_int uStripIndex ) const { return m_pxStrips[ uStripIndex ]; }

	u_int GetNumStrips( void ) const { return m_uNumStrips; }
	Asura_PS3_GCM_VertexBuffer*	GetVertexBuffer( void ) { return &m_xVertexBuffer; }
	Asura_PS3_GCM_IndexBuffer*	GetIndexBuffer( void ) { return &m_xIndexBuffer; }
	const Asura_PS3_GCM_IndexBuffer* GetIndexBuffer( void ) const { return &m_xIndexBuffer; }

protected:

	// Data

    Asura_PS3_GCM_VertexBuffer			m_xVertexBuffer;
    Asura_PS3_GCM_IndexBuffer			m_xIndexBuffer;
	Asura_PS3_CharacterRenderer_Strip*	m_pxStrips;
	u_int								m_uNumStrips;
	u_int								m_uNumTriangles;
};

class Asura_PS3_CharacterRenderer
{

public:
	//Static functions
	static void Initialise(void);
	static void Reset();
	static void Shutdown(void);

	static Asura_PS3_CharacterRenderer_Skin* CreateCharacter( const Asura_Hash_ID uHash, const u_int uNumStrips );
	static Asura_PS3_CharacterRenderer_Skin* GetCharacter( const Asura_Hash_ID uHash );
	static bool IsCharacterOpaque( const Asura_Hash_ID uHash );

	static void RenderCharacter(const Asura_Animation& xAnimation,
		const Asura_Hierarchy_Skin& xSkin,
		Asura_AMatrix4x4_InParam xTransform,
		Asura_AMatrix4x4_InParam xInverseTransform,
		const Asura_AMatrix4x4* const pxBones,
		u_int uSkinIdx);

	static void RenderShadow(const Asura_Animation& xAnimation,
		const Asura_Hierarchy_Skin& xSkin,
		const Asura_Shadow& xShadow,
		Asura_AMatrix4x4_InParam xTransform,
		const Asura_AMatrix4x4* const pxBones,
		u_int uSkinIdx);

	static int GetVertexSize( void );

	static const Asura_AMatrix4x4* GetBonesForRender( const Asura_AMatrix4x4* pxBones, int iNumberOfBones, const Asura_Animation& xAnimation, bool bUseDamageMaps, bool bSpuVs );
	
	static void UseSpuSkinning( Asura_PS3_CharacterRenderer_Skin* pxCharacterStrips,
								const Asura_Animation& xAnimation,
								SPU_SKINNING_MODE eMode,
								Asura_AMatrix4x4_InParam xTransform,
								const Asura_AMatrix4x4* const pxBoneTransforms,
								u_int uNumBones,
								u_int uSkinIdx );

protected:

	static void RenderCharacterZPassOnly(const Asura_Animation& xAnimation,
		const Asura_Hierarchy_Skin& xSkin,
		Asura_AMatrix4x4_InParam xTransform,
		Asura_AMatrix4x4_InParam xInverseTransform,
		const Asura_AMatrix4x4* const pxBones, const u_int uSkinIdx,
		bool bUseDamageMaps );

	static void RenderCharacterUsingZPrepass(const Asura_Animation& xAnimation,
		const Asura_Hierarchy_Skin& xSkin,
		Asura_AMatrix4x4_InParam xTransform,
		Asura_AMatrix4x4_InParam xInverseTransform,
		const Asura_AMatrix4x4* const pxBones);

	static void SetVPData( Asura_PS3_CharacterRenderer_Skin* pxCharacterStrips,
		const Asura_Animation& xAnimation,
		const Asura_Hierarchy_Skin& xSkin,
		u_int uSkinIdx,
		Asura_AMatrix4x4_InParam xTransform,
		Asura_AMatrix4x4_InParam xInverseTransform,
		const Asura_AMatrix4x4* const pxBones,
		bool bUseDamageMaps, bool bTransparentPass, bool bSpuVS );
};

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef ___ASURA_PS3_CHARACTERRENDERER_H___
