//
// Asura_Xbox360_ObjectHierarchyRenderer.h
//
// Created by KJFL - 09 November 2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#if !defined __ASURA_XBOX360_OBJECTHIERARCHYRENDERER_H__
#define __ASURA_XBOX360_OBJECTHIERARCHYRENDERER_H__

/******************************************************************************/
/* Included Files                                                             */
/******************************************************************************/

#include "Core/Asura_HashTree.h"
#include "Rendering/Asura_Xbox360_IndexBuffer.h"
#include "Rendering/Asura_Xbox360_VertexBuffer.h"

/******************************************************************************/
/* Classes                                                                    */
/******************************************************************************/

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

////////////////////////////////////////////////////////////////////////////////
//
// Asura_Xbox360_ObjectHierarchyRenderer
//
// Manages rendering of object hierarchies on Xbox 360
//
////////////////////////////////////////////////////////////////////////////////

class Asura_Xbox360_ObjectHierarchyRenderer
{
	friend class Asura_Chunk_ResourceFile_Xbox360_ObjectHierarchy;

public:

	// Types

	struct Strip
	{
		Asura_Hash_ID	m_auMaterialResponseHashIDs[2];
		u_int			m_uBoneIndex;
		u_int			m_uStartIndex;
		u_int			m_uNumberOfIndices;
		u_int			m_uNumberOfTriangles;
	};

	class Hierarchy
	{
		friend class Asura_Chunk_ResourceFile_Xbox360_ObjectHierarchy;
		friend class Asura_Xbox360_ObjectHierarchyRenderer;

	public:

		// Constructor / destructor
		Hierarchy();
		~Hierarchy();

		// Functions
		u_int GetNumberOfStrips() const { return m_uNumberOfStrips; }
		const Strip& GetStrip( const u_int uStripIndex ) const { return m_pxStrips[ uStripIndex ]; }

	protected:

		Asura_Xbox360_IndexBuffer	m_xIndexBuffer;
		Asura_Xbox360_VertexBuffer	m_xVertexBuffer;

		u_int						m_uNumberOfStrips;
		Strip*						m_pxStrips;
	};

	// Static functions

	static void Initialise();
	static void Reset();
	static void Shutdown();

	static void ResetCount(void)	{ s_uNumRendered = 0; }

	// To draw a hierarchical object
	// 1. Call BeginRender()
	// 2. Call Render() for each visible strip of the hierarchical object
	// 3. Call EndRender()

	static void RenderHierarchy( const Asura_Animation& xAnim, const Asura_Hierarchy_Skin& xSkin );
	static void RenderShadow( const Asura_Animation& xAnim, const Asura_Hierarchy_Skin& xSkin, const Asura_Shadow& xShadow );

	static void BeginRender( const Asura_Animation& xAnim, const Asura_Hierarchy_Skin& xSkin );
	static void RenderStrip( const u_int uSectionIndex, const Asura_Vector_3& xPosition, const Asura_Matrix_3x3& xOrientation, const Asura_Animation& xAnim, bool bZPrePass );
	static void EndRender();

	static void BeginShadowRender( const Asura_Hierarchy_Skin& xSkin, const Asura_Shadow& xShadow );
	static void RenderShadowStrip( const u_int uStripIndex, const Asura_Vector_3& xPosition, const Asura_Matrix_3x3& xOrientation, const Asura_Animation& xAnim, const Asura_Shadow& xShadow );
	static void EndShadowRender();

	static const Asura_TemplateHashTree< Hierarchy >& GetHierarchyTree() { return s_xHierarchyTree; }
	static bool IsHierarchyOpaque( const Asura_Hash_ID uHash );

protected:

	// Static functions
	static Hierarchy* CreateHierarchy( const Asura_Hash_ID uHashID );

	// Static data
	static u_int								s_uNumRendered;
	static Asura_TemplateHashTree< Hierarchy >	s_xHierarchyTree;
	static Hierarchy*							s_pxCurrentHierarchy;
};

#endif // !defined __ASURA_XBOX360_OBJECTHIERARCHYRENDERER_H__
