//
// Tools_HierarchyProcessor_MultiMaterial.h
//
// Cloned by RJF from Tools_HierarchyProcessor.h 12-4-05
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#ifndef __TOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_H__
#define __TOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_H__

#include "Core/Asura_Maths.h"
#include "Misc/list_tem.hpp"
class Asura_Mesh;
class Asura_Hierarchy_Skin;

const float fTOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_VERTEX_EPSILON = 0.005f;
const float fTOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_VERTEX_EPSILON_SQD = 0.005f * 0.005f;

class Tools_HierarchyProcessor_MultiMaterial_Vertex
{
	public:
		Asura_Vector_3	m_xPosition;
		Asura_Vector_3	m_xNormal;
		float			m_fU0;
		float			m_fV0;
		float			m_fAlpha;
		unsigned short	m_usBoneIndex;
		u_int			m_uARGBColour;

		inline bool operator == ( const Tools_HierarchyProcessor_MultiMaterial_Vertex& v ) const
		{
			Asura_Vector_2 xUVDelta( m_fU0, m_fV0 );
			xUVDelta.x -= v.m_fU0;
			xUVDelta.y -= v.m_fV0;

			return m_usBoneIndex == v.m_usBoneIndex
				&& Asura_Maths::Abs( m_fAlpha - v.m_fAlpha ) < fTOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_VERTEX_EPSILON
				&& xUVDelta.MagnitudeSquared() < fTOOLS_HIERARCHYPROCESSOR_MULTIMATERIAL_VERTEX_EPSILON_SQD
				&& m_xPosition.ApproximatelyEquals( v.m_xPosition )
				&& m_xNormal.ApproximatelyEquals( v.m_xNormal );
		}
};

class Tools_HierarchyProcessor_MultiMaterial_Strip
{
	public:
		
		Tools_HierarchyProcessor_MultiMaterial_Strip()
		{
			m_pxVertices = 0;
			m_pusIndices = 0;
		}
		
		~Tools_HierarchyProcessor_MultiMaterial_Strip()
		{
			delete [] m_pxVertices;
			delete [] m_pusIndices;
		}

		u_int								m_uNumberOfIndices;
		u_int								m_uNumberOfTriangles;
		u_int								m_uNumberOfVertices;

		int									m_iMaterialID;
		unsigned short						m_usBoneIndex;

		Tools_HierarchyProcessor_MultiMaterial_Vertex*	m_pxVertices;
		u_short*							m_pusIndices;
};



class Tools_HierarchyProcessor_MultiMaterial
{
	public:
		typedef u_int (ColourGenerationHook)(const Asura_Mesh& xMesh, const int iPoly, const int iVertex);
		typedef void (VertexModificationHook)(Tools_HierarchyProcessor_MultiMaterial_Vertex& xVertex);

		static bool Initialise(const Asura_Hierarchy_Skin* pxSkin, bool bStripify = true);
		static void Shutdown(void);

		static const Tools_HierarchyProcessor_MultiMaterial_Strip* GetProcessedStrip(u_int uIndex);
		static u_int GetTotalNumberOfVertices(void);
		static u_int GetTotalNumberOfIndices(void);
		static u_int GetTotalNumberOfStrips(void);
		static void ConvertMaterialsForExport(void);
		inline static bool DoesRequireVertexAlpha(void) { return s_bRequiresVertexAlpha; }
		
		static bool ConcatenateStrips(void);
		static const Tools_HierarchyProcessor_MultiMaterial_Strip* GetCattedStrip();

		static void SetColourGenerationCallback(ColourGenerationHook* const pfnColourGenerationFunction = NULL) { s_pfnColourGenerationFunction = pfnColourGenerationFunction; }
		static void SetVertexModificationCallback(VertexModificationHook* const pfnVertexModificationFunction = NULL) { s_pfnVertexModificationFunction = pfnVertexModificationFunction; }

		static u_int							s_uTotalNumberOfVertices;
		static u_int							s_uTotalNumberOfIndices;
		static u_int							s_uTotalNumberOfTriangles;
		static u_int							s_uTotalNumberOfStrips;
		static bool								s_bBeenInitialised;
		static bool								s_bRequiresVertexAlpha;
	
	private:

		static const Asura_Hierarchy_Skin* s_pxCurrentSkin;
		static bool MeshProcess(Asura_Mesh* pxMesh, unsigned short usBoneIndex, bool bStripify);
		static List<Tools_HierarchyProcessor_MultiMaterial_Strip*> s_xProcessedStrips;
		static Tools_HierarchyProcessor_MultiMaterial_Strip* s_pxCattedStrip;
		
		static int s_iCurrentMaterial;
		static bool MaterialSelectorFunction(Asura_Mesh* pxMesh, int iPolyIndex);

		static ColourGenerationHook* s_pfnColourGenerationFunction;
		static VertexModificationHook* s_pfnVertexModificationFunction;
};


#endif//__TOOLS_HIERARCHYPROCESSOR_H__
