/**
*
* \file Tools_SubdividedMesh.h
*
* Created by Kevin Lea - 27/05/2002 10:14:20
*
* Copyright (C) 2002 Rebellion, All Rights Reserved.
*
* \brief
*
**/
#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#ifndef __TOOLS_SUBDIVIDEDMESH_H__
#define __TOOLS_SUBDIVIDEDMESH_H__

#include "Core/Asura_Hash.h"
#include "Core/Asura_Maths.h"

#include "Mesh/Asura_Mesh.h"

class Tools_SubdividedMesh_Vertex
{
	public:
		// (SB - 26/07/07) Allow projects to alter the parameters used for comparing vertices
		// Currently used in Simpsons to generate better strips
		struct VertexComparisonParameters
		{
			union
			{
				u_int m_uComparisonFlags;
				struct
				{
					u_int m_bTestNormals : 1;			// Count normals towards approximate equality
					u_int m_bTestPrimaryUV : 1;			// Count primary UVs towards approximate equality
					u_int m_bTestSecondaryUV : 1;		// Count secondary UVs towards approximate equality
					u_int m_bTestColour : 1;			// Count colour towards approximate equality
				};
			};
			int m_iFlagTestMask;						// Mask to specify which polygon flags to compare for approximate equality
		};

		Asura_Vector_3	Position;
		Asura_Vector_3	Normal;
		unsigned int	Colour; // floats?
		float			U;
		float			V;
		float			U2;
		float			V2;
		int				m_iPolygonFlags;//contains a subset of the polygon flags from the original polygon
		int	m_iPolygonIndex;//Index of one of the polygons that this vertex belonged to in the original mesh

		#if defined(ASURA_TARGET_SM3)
		Asura_SphericalHarmonics_Order3		m_xLightTransportHarmonic;
		Asura_SphericalHarmonics_Order2_RGB m_xDiffuseSH;

		Asura_Vector_3						m_xBrightestLightVector;	// VGP 13Feb2006

		Asura_Vector_3 m_xTangent;
		Asura_Vector_3 m_xBinormal;
		Asura_Vector_3 m_xTangent2;
		Asura_Vector_3 m_xBinormal2;

		#endif

		int m_iIndexInPacket;//Used to help with hash lookups, only really valid while a given packet is being built. RAR 10/07/2006

	   inline bool operator == (const Tools_SubdividedMesh_Vertex& v) const
	   {
		   if( (Colour!=v.Colour) 
			 ||(U!=v.U)
			 ||(V!=v.V)
			 ||(U2!=v.U2)
			 ||(V2!=v.V2)
			 ||(Position!=v.Position)
			 ||(Normal!=v.Normal) 
			 ||(m_iPolygonFlags!=v.m_iPolygonFlags)
			#if defined(ASURA_TARGET_SM3)
			 ||(m_xLightTransportHarmonic != v.m_xLightTransportHarmonic)
			 ||(m_xBrightestLightVector != v.m_xBrightestLightVector) // VGP 13Feb2006
			 ||(m_xTangent != v.m_xTangent) 
			 ||(m_xBinormal != v.m_xBinormal) 
			 ||(m_xTangent2 != v.m_xTangent2) 
			 ||(m_xBinormal2 != v.m_xBinormal2) 
			#endif
			 )
		   {
			   return false;
		   }
		   else
		   {
			   return true;
		   }
	   }

#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM && !defined ASURA_MATERIAL_RESPONSE_CHARACTERS_ONLY
		static bool ApproximatelyEquals(const Tools_SubdividedMesh_Vertex* pxVert1,const Tools_SubdividedMesh_Vertex* pxVert2,bool bDualTexture,bool bCheckPosition);
#else
		static bool ApproximatelyEquals(const Tools_SubdividedMesh_Vertex* pxVert1,const Tools_SubdividedMesh_Vertex* pxVert2,int iMaterial,bool bCheckPosition);
#endif

		inline Asura_Hash_ID GetHashID( void ) const
		{
			// KOR - 02/10/2006 - Hash into millimetre cubes.
			// This ignores a lot of the data, and will result in some different vertices having the same hash.
			// However, the point of the hash is simply to quickly file data - more in-depth checking is done later.
			// The binary hash that was previously done had unfortunate side effects such as -0.0f and 0.0f being treated as distinct.
			const int iX = Asura_Maths::FloatToInt(Position.x * 1000.f);
			const int iY = Asura_Maths::FloatToInt(Position.y * 1000.f);
			const int iZ = Asura_Maths::FloatToInt(Position.z * 1000.f);
			// Snaffled from Asura_Physics_SpatialHash
			const Asura_Hash_ID uHash = 7* iX + 503 * iY + 24847 * iZ;;
			return uHash;
		}

		// This changes the colour tolerance for ApproximatelyEquals. Default is 2.
		static void SetColourTolerance( u_int uTolerance ) { s_uColourTolerance = uTolerance; }

		// Static data
        static const u_int s_uDefaultColourTolerance;
		static u_int s_uColourTolerance;

		// Comparison parameters
		static void SetDefaultVertexComparisonMode();
		static void SetVertexComparisonMode(VertexComparisonParameters& xParams);

protected:
		static VertexComparisonParameters s_xVertexComparisonParameters;
};


class Tools_SubdividedMesh_Packet
{
	public:
		Tools_SubdividedMesh_Packet()
		{
			TriList = NULL;
			Vertices = NULL;
			NumberOfVertices = 0;
			NumberOfTris = 0;
		}
		~Tools_SubdividedMesh_Packet()
		{
			if (TriList) delete [] TriList;
			if (Vertices) delete [] Vertices;
		}


		int								NumberOfTris;

#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM && !defined ASURA_MATERIAL_RESPONSE_CHARACTERS_ONLY
		Asura_Hash_ID					m_auMaterialResponseHashID[TOOLS_NUM_MATERIALRESPONSE_PER_POLY];
#else
		int								m_iMaterialID;
#endif

		int								NumberOfVertices;
		Tools_SubdividedMesh_Vertex*	Vertices;

		// KJL - 26/05/2002 19:13:44 -  TriList info - list of vertex indices making up tris
		// e.g. (0,1,2),(2,3,4),(1,2,4) etc.
		// NumberOfIndicesInTriList = 3*NumberOfTris;
		int*							TriList;


};

class Tools_SubdividedMesh
{
	public:

		Tools_SubdividedMesh( class Asura_Mesh* mesh, Asura_Vector_3& position, bool subdivide = true, bool bOnlyRenderablePolys = false, bool bMakeDoubleSidedPolys = false );
		Tools_SubdividedMesh( int iModuleIndex, bool bOnlyRenderablePolys = false, bool bMakeDoubleSidedPolys = false, bool bSubdivide = true, const u_int uPolygonFlagsToIgnor = AsuraPolygonFlag_Water|AsuraPolygonFlag_DontExport);
		~Tools_SubdividedMesh()
		{
			if (Packets) delete [] Packets;
		}

		void ConvertToMesh( Asura_Mesh* pxOutputMesh, const bool bExpandVertices = true);

	private :
		bool CreatePackets( class Asura_Mesh* pxMesh, bool bSubdivide, bool bOnlyRenderablePolys, bool bMakeDoubleSidedPolys = false, const u_int uPolygonFlagsToIgnor = AsuraPolygonFlag_Water|AsuraPolygonFlag_DontExport);

	public :

		int								NumberOfPackets;
		Tools_SubdividedMesh_Packet*	Packets;

		int								TotalVertices;
		int								TotalTris;

		class Asura_Mesh*				m_pxMesh;
		Asura_Vector_3					m_xPosition;


		static bool						s_bRecalculatePrelighting;
};

#endif//__TOOLS_SUBDIVIDEDMESH_H__
