/****************************************************************************************************

		MeshDataStructure.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Charles
		Date:	2/23/2005

****************************************************************************************************/

#ifndef __MeshDataStructure__
#define __MeshDataStructure__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "Vector2.h"
#include "Vector3.h"

#include "MCArray.h"
#include "MCClassArray.h"
#include "MCPtrArray.h"
#include "MCSmartPtr.h"
#include "MCSMPCountedObject.h"
#include "MCCountedPtrHelper.h"

struct TFaceSet;
struct FacetMesh;
class  TIndex2;

namespace MeshDataStructure
{

class TVertex;
class TTriangle;
class TEdge;
class TPolygon;
class TQuad;
class TMesh;

struct TVertexArray;



class TSmoothingGroup : public TMCObject
{
public:
	inline TSmoothingGroup() : fNormal(TVector3::kZero)
	{
	}

	inline int32 GetPolygonCount(){ return fPolygonsIndexes.GetElemCount(); }
	inline int32 GetPolygonIndex(int32 i)
	{
		MCAssert(i>=0 && i<(int32)fPolygonsIndexes.GetElemCount());
		return fPolygonsIndexes[i];
	}
	inline void	AddPolygonIndex( int32 polygonIndex )
	{
		fPolygonsIndexes.AddElem(polygonIndex);
	}
	inline void SetPolygons( const TMCArray<int32>& polygons)
	{
		fPolygonsIndexes = polygons;
	}
	inline int32 GetPolygonCount() const
	{
		return fPolygonsIndexes.GetElemCount();
	}
	inline int32 GetPolygonIndex(int32 index) const
	{
		return fPolygonsIndexes[index];
	}

	/// Sets the normal of the smoothing group
	inline void SetNormal(const TVector3& normal) const	{ fNormal = normal; }
	
	/// Returns the normal of the smoothing group
	inline const TVector3& GetNormal() const	{ return fNormal; }
	inline		 TVector3& GetNormal()			{ return fNormal; }

	void GenerateNormal(int32 vertexIndex,const TMCClassArray<TPolygon>& polygons,const TMCArray<TVector3>& positions) const;
	void GenerateNormal(int32 vertexIndex,const TMCClassArray<TQuad>& polygons,const TMCArray<TVector3>& positions) const;

	boolean Contains(int32 polygonIndex) const;
protected:
	mutable TVector3	fNormal;
	TMCArray<int32>		fPolygonsIndexes;
};

struct TUVData : public TMCObject
{
	inline TUVData() : fUV(-10000,-10000) {}

	TVector2				fUV;
	TMCArray<TVector2>		fAdditionalUV;
};

struct TCoordData : public TMCObject
{
	inline TCoordData() : fCoord(-1,-1,-1) {}

	TVector3				fCoord;
	TMCArray<TVector3>		fAdditionalCoord;
};

struct TNormalData : public TMCObject
{
	inline int32 GetNormalCount() const
	{
		const int32 normalCount = fNormals.GetElemCount();

		if (normalCount==0) return 1;

		return normalCount;
	}

	inline const TVector3& GetNormal(int32 index) const
	{
		if (fNormals.GetElemCount()>0)
		{
			return fNormals[index].GetNormal();
		}
		else
		{
			return fUniqueNormal;
		}
	}

	TVector3						fUniqueNormal;	// used only when there is only one normal
	TMCClassArray<TSmoothingGroup>	fNormals;
};

struct TVertexArray : public TMCObject
{
	TVertexArray() : fAllocateBarycentricCoordinates(false) {}

	inline uint32 GetElemCount() { return fPositions.GetElemCount(); }

	TMCArray<TVector3>						fPositions; ///< the position of each vertex

	TMCClassArray< TMCArray<int32> >		fEdges;						///< for each vertex the list of edges that point to it
	TMCClassArray< TMCArray<int32> >		fPolygons;					///< for each vertex the list of polygons that point to it
	TMCClassArray< TUVData >				fUVs;						///< the normals of each vertex
	TMCClassArray< TNormalData >			fNormals;					///< the normals of each vertex
	TMCClassArray< TCoordData >				fBarycentricCoordinates;	///< the barycentric coordinates of each vertex
	TMCArray< TMCColorRGBA8 >				fColors;					///< a color for each vertex

	boolean		fAllocateBarycentricCoordinates;
};


class TConstVertex : public TMCObject
{
public:
	TConstVertex(const TVertexArray& vertexArray,const uint32 index) : fVertexArray(vertexArray),fIndex(index)
	{
	}
	inline const TVector3& GetPosition() const
	{
		return fVertexArray.fPositions[fIndex];
	}
	inline const int32 GetUVsCount() const
	{
		return fVertexArray.fUVs[fIndex].fAdditionalUV.GetElemCount()+1;
	}
	inline const TVector2& GetUV( const int32 index ) const
	{
		const TUVData& data = fVertexArray.fUVs[fIndex];

		if (index==0)
		{
			return data.fUV;
		}
		else
		{
			return data.fAdditionalUV[index-1];
		}
	}
	inline const int32 GetBarycentricCoordCount() const
	{
		return fVertexArray.fBarycentricCoordinates[fIndex].fAdditionalCoord.GetElemCount()+1;
	}
	inline const TVector3& GetBarycentricCoordinates( const int32 index ) const
	{
		const TCoordData& data = fVertexArray.fBarycentricCoordinates[fIndex];

		if (index==0)
		{
			return data.fCoord;
		}
		return data.fAdditionalCoord[index-1];
	}
	inline int32 GetEdgeCount() const
	{
		return fVertexArray.fEdges[fIndex].GetElemCount();
	}
	inline int32 GetEdgeIndex(int32 index) const
	{
		return fVertexArray.fEdges[fIndex][index];
	}
	inline const TNormalData& GetNormals() const
	{
		return fVertexArray.fNormals[fIndex];
	}
	inline int32 GetNormalCount() const
	{
		const int32 normalCount = fVertexArray.fNormals[fIndex].fNormals.GetElemCount();

		if (normalCount==0) return 1;

		return normalCount;
	}
	inline const TVector3& GetNormal(const int32 index) const
	{
		TNormalData& normalData = const_cast<TVertexArray&>(fVertexArray).fNormals[fIndex];

		if (normalData.fNormals.GetElemCount() == 0) return normalData.fUniqueNormal;

		return normalData.fNormals[index].GetNormal();
	}

	inline int32 GetPolygonCount() const
	{
		return fVertexArray.fPolygons[fIndex].GetElemCount();
	}
	inline int32 GetPolygonIndex(int32 index) const
	{
		return fVertexArray.fPolygons[fIndex][index];
	}
	inline boolean operator==(const TConstVertex& vertex) const
	{
		return fIndex == vertex.fIndex;
	}
	int32				Edge(const TMCClassArray<TEdge>& edgeList,int32 vertexIndex) const;
	int32				GetNormalIndex(int32 polygonIndex) const;
	const TVector3&		GetPolygonNormal(int32 polygonIndex) const;

	inline const TMCColorRGBA8&	GetColor() const { return fVertexArray.fColors[fIndex]; }

protected:
	const TVertexArray&		fVertexArray;
	const uint32			fIndex;			// index of the vertex in fVertexArray
};

/// light weight data structure that stores a vertex in a connected mesh.
///
class TVertex : public TConstVertex
{
public:
	TVertex(TVertexArray& vertexArray,const uint32 index) : TConstVertex(vertexArray,index)
	{
	}

	// ****************************************************************************
	//								AddPolygon
	// 
	/// Adds a polygon that contains this vertex.
	/// 
	/// \param polygonIndex  The index of the polygon in the mesh
	/// 
	void AddPolygon(int32 polygonIndex);
	void RemovePolygon(int32 polygonIndex);

	void AddEdge(int32 edgeIndex)
	{
		MCAssert( fVertexArray.fEdges.GetElemCount()>fIndex);

		const_cast<TVertexArray&>(fVertexArray).fEdges[fIndex].AddElem(edgeIndex);
	}
	void RemoveEdge(int32 edgeIndex);

	inline void SetPosition(const TVector3& position)
	{
		const_cast<TVertexArray&>(fVertexArray).fPositions[fIndex] = position;
	}
	// Adds uv coordinates and returns the index of uv. (identical uv coordinates are merged)
	int32 AddUVs(const TVector2& newUV);

	inline void SetUVCount(const int32 count)
	{
		MCAssert(count>0);

		if (count>1)
		{
			const_cast<TVertexArray&>(fVertexArray).fUVs[fIndex].fAdditionalUV.SetElemCount(count-1);
		}
	}

	inline void SetUV(const TVector2& uv, const int32 index)
	{
		TUVData& data = const_cast<TVertexArray&>(fVertexArray).fUVs[fIndex];

		if (index==0)
		{
			data.fUV = uv;
		}
		else
		{
			data.fAdditionalUV[index-1] = uv;
		}
	}
	inline void SetUVs(const TUVData& uvs)
	{
		TUVData& data = const_cast<TVertexArray&>(fVertexArray).fUVs[fIndex];

		data.fUV				= uvs.fUV;
		data.fAdditionalUV		= uvs.fAdditionalUV;
	}
	inline TUVData& GetUVs()
	{
		return const_cast<TVertexArray&>(fVertexArray).fUVs[fIndex];
	}
	inline void SetBarycentricCoordinatesCount(const int32 count)
	{
		MCAssert(count>0);

		if (count>1)
		{
			const_cast<TVertexArray&>(fVertexArray).fBarycentricCoordinates[fIndex].fAdditionalCoord.SetElemCount(count-1);
		}
	}
	inline void SetBarycentricCoordinates(const TVector3& coordinates,const int32 index)
	{
		TCoordData& data = const_cast<TVertexArray&>(fVertexArray).fBarycentricCoordinates[fIndex];

		if (index==0)
		{
			data.fCoord = coordinates;
		}
		else
		{
			data.fAdditionalCoord[index-1] = coordinates;
		}
	}

	//inline TNormalData& GetNormals() const
	//{
	//	return fVertexArray.fNormals[fIndex];
	//}
	inline TVector3& GetNormal(const int32 index)
	{
		TNormalData& normalData = const_cast<TVertexArray&>(fVertexArray).fNormals[fIndex];

		if (normalData.fNormals.GetElemCount() == 0) return normalData.fUniqueNormal;

		return normalData.fNormals[index].GetNormal();
	}
	inline TNormalData& GetNormals() const
	{
		return const_cast<TVertexArray&>(fVertexArray).fNormals[fIndex];
	}

	inline void SetEdgeCount(int32 count)
	{
		const_cast<TVertexArray&>(fVertexArray).fEdges[fIndex].SetElemCount(count);
	}
	inline void SetPolygonCount(int32 count)
	{
		const_cast<TVertexArray&>(fVertexArray).fPolygons[fIndex].SetElemCount(count);
	}

	inline void SetColor(const TMCColorRGBA8& color) { const_cast<TVertexArray&>(fVertexArray).fColors[fIndex] = color; }
};


// Structure to describe a vertex in a polygon:
// a vertex and the UV value to be used.
class TVertexUV : public TMCObject
{
public:
	TVertexUV() {fVertexIndex=0; fUVIndex=0;}

	int32 fVertexIndex;	// the index to get the TVertex.
	int32 fUVIndex;		// the index of the UV in the TVertex.
};


class TQuad : public TMCObject
{
public:
	TQuad()
	{
		fIsHidden=false;
		fShadingDomainID=0;
	}
	inline void SetVertex(const int32 index, const int32 vertexIndex, const int32 UVIndex )
	{
		fVerticesUV[index].fVertexIndex	= vertexIndex;
		fVerticesUV[index].fUVIndex		= UVIndex;
	}
	inline int32 GetVertexIndex(const int32 i) const
	{
		return fVerticesUV[i].fVertexIndex;
	}
	inline int32 GetUVIndex(const int32 i) const
	{
		return fVerticesUV[i].fUVIndex;
	}
	inline const TVertexUV&	GetVertexUV(const int32 index) const
	{
		return fVerticesUV[index];
	}
	inline void SetUVIndex(const int32 i,const int32 uvIndex)
	{
		fVerticesUV[i].fUVIndex = uvIndex;
	}
	inline void SetEdge(const int32 index, const int32 edgeIndex)
	{
		fEdges[index] = edgeIndex;
	}
	inline int32 GetEdge(const int32 index) const
	{
		return fEdges[index];
	}
	inline int32 GetVertexCount() const
	{
		return 4;
	}
	int32			GetUVIndexForVertex(const int32 index) const;
	int32			GetOtherEdge(int32 vertexIndex,int32 edgeIndex) const;
	boolean			GetEdgesForVertex(int32 vertexIndex, int32& edge1, int32& edge2)const; 
	inline void		SetShadingDomainID(int32 ID){fShadingDomainID = ID;}
	inline int32	GetShadingDomainID() const {return fShadingDomainID;}
	inline void		SetIsHidden(boolean hidden){fIsHidden = hidden;}
	inline boolean	GetIsHidden() const {return fIsHidden;}

	int32 GetVertexIndexInQuad(const int32 vertexIndex) const;
	TVector3		GetPolygonNormalForVertex(const int32 vertexIndex,const TMCArray<TVector3>& positions) const;
	void			HarmonizeUV(TVertexArray& vertices,TMCArray<boolean>& wrapping);
protected:
	TVertexUV			fVerticesUV[4]; // The vertices and the index of the UV to be used
	int32				fEdges[4];
	int32				fShadingDomainID;
	boolean				fIsHidden;
};

class TPolygon : public TMCObject
{
public:
	TPolygon()
	{ 
		fShadingDomainID=0;
		fVerticesUV.SetElemSpace(4);
		fEdges.SetElemSpace(4);
	}
	
	/// An invalid polygon is a polygon that has been deleted from the mesh
	inline boolean IsValidPolygon() const
	{
		return fVerticesUV.GetElemCount()>0;
	}

	inline void SetVertexCount(int32 verticesCount)
	{
		fVerticesUV.SetElemCount(verticesCount);
		fEdges.SetElemCount(verticesCount);
	}
	inline int32 GetVertexCount() const
	{
		return fVerticesUV.GetElemCount();
	}
	inline int32 GetEdgeCount() const
	{
		return fEdges.GetElemCount();
	}
	inline void SetVertex(const int32 index, const int32 vertexIndex, const int32 UVIndex )
	{
		fVerticesUV[index].fVertexIndex	= vertexIndex;
		fVerticesUV[index].fUVIndex		= UVIndex;
	}
	inline int32 GetVertexIndex(const int32 i) const
	{
		return fVerticesUV[i].fVertexIndex;
	}
	inline int32 GetUVIndex(const int32 i) const
	{
		return fVerticesUV[i].fUVIndex;
	}
	inline void SetUVIndex(const int32 i,const int32 uvIndex)
	{
		fVerticesUV[i].fUVIndex = uvIndex;
	}
	int32 GetUVIndexForVertex(const int32 index) const;
	inline void SetEdge(const int32 index, const int32 edgeIndex)
	{
		fEdges[index] = edgeIndex;
	}
	inline const TVertexUV&	GetVertexUV(const int32 index) const
	{
		return fVerticesUV[index];
	}
	inline int32 GetEdge(const int32 index) const
	{
		return fEdges[index];
	}
	inline const TMCArray<TVertexUV>& GetVertices() const
	{
		return fVerticesUV;
	}

	int32			GetOtherEdge(int32 vertexIndex,int32 edgeIndex) const;
	boolean			GetEdgesForVertex(int32 vertexIndex, int32& edge1, int32& edge2)const; 
	inline void		SetShadingDomainID(int32 ID){fShadingDomainID = ID;}
	inline int32	GetShadingDomainID() const {return fShadingDomainID;}
	inline void		SetIsHidden(boolean hidden){fIsHidden = hidden;}
	inline boolean	GetIsHidden() const {return fIsHidden;}

	int32	GetVertexIndexInPolygon(const int32 vertexIndex) const;
	TVector3		GetPolygonNormalForVertex(const int32 vertexIndex,const TMCArray<TVector3>& positions) const;
	void			HarmonizeUV(TVertexArray& vertices,TMCArray<boolean>& wrapping);

protected:
//	TMCArray<int32>		fVertices;
	TMCArray<TVertexUV>	fVerticesUV; // The vertices and the index of the UV to be used
	TMCArray<int32>		fEdges;
	int32				fShadingDomainID;
	boolean				fIsHidden;
};

class TEdge : public TMCObject
{
public:
	TEdge();

	/// An invalid edge is an edge that has been deleted from the mesh
	inline boolean IsValidEdge() const
	{
		return fVertices[0]>=0;
	}

	inline boolean IsPartOfPolygon(int32 polygonIndex) const
	{
		int32 arraySize = fPolygons.GetElemCount();
		for(int32 index=0; index < arraySize; index++)
		{
			if(fPolygons[index] == polygonIndex)
				return true;
		}
		return false;
	}
	inline boolean ContainsVertex(int32 vertexIndex) const
	{
		return (fVertices[0] == vertexIndex || fVertices[1] == vertexIndex);
	}
	void SetVertices(int32 pt1,int32 pt2)
	{
		fVertices[0] = pt1;
		fVertices[1] = pt2;
	}
	inline int32 GetVertex(int32 vertexIndex) const
	{
		MCAssert(vertexIndex>=0 && vertexIndex<2);

		return fVertices[vertexIndex];
	}
	inline int32 GetOtherPoint(int32 vertexIndex) const
	{
		if (vertexIndex != fVertices[0])
		{
			return fVertices[0];
		}
		return fVertices[1];
	}
	void AddPolygon(int32 index);
	void RemovePolygon(int32 index);

	inline void RemoveAllPolygons()
	{
		int32 arraySize = fPolygons.GetElemCount();
		for(int32 index=0; index < arraySize; index++)
			fPolygons[index] = -1;
	}

	inline int32 GetPolygon(int32 index) const
	{
		int32 arraySize = fPolygons.GetElemCount();
		MCAssert(index >= 0 && index < arraySize);

		return fPolygons[index];
	}
	inline int32 GetPolygonCount() const
	{
		int32 count=0;
		int32 arraySize = fPolygons.GetElemCount();
		for(int32 index=0; index < arraySize; index++)
		{
			if(fPolygons[index] >= 0)
				count++;
		}
		
		return count;
	}
	inline int32 GetOtherPolygon(int32 polygonIndex) const
	{
		int32 polygonCount = GetPolygonCount();

		MCAssert(polygonCount <= 2);
		MCAssert(IsPartOfPolygon(polygonIndex));

		if(polygonCount == 1)
			return -1;

		int32 arraySize = fPolygons.GetElemCount();
		for(int32 index=0; index < arraySize; index++)
		{
			if(fPolygons[index] != polygonIndex)
				return fPolygons[index];
		}
		return -1;
	}
	real GetMagnitudeSquared(TMesh& mesh) const;

	inline boolean	GetCrease() const {return fCrease;}
	inline void		SetCrease(boolean crease) {fCrease = crease;}
protected:
	int32			fVertices[2];
	TMCArray<int32>	fPolygons; // triangles that share that edge (-1 means no triangle)
	boolean			fCrease;
};




class TMesh : public TMCObject
{
public:
	TMesh();
	virtual ~TMesh();

	// ****************************************************************************
	//								BuildMesh
	// 
	/// Create a mesh object from a facet mesh. Note that edges are not built
	/// 
	/// \param facetMesh  The facet mesh
	/// 
	void	BuildMesh(const FacetMesh* facetMesh);

	// ****************************************************************************
	//								BuildMesh
	// 
	/// Create a mesh object from a face set.
	/// 
	/// \param faceSet  The face set
	///
	void	BuildMesh(const TFaceSet* faceSet);

	
	// ****************************************************************************
	//								CreateFacetMesh
	// 
	/// Creates a new facet mesh that corresponds to this mesh
	/// 
	/// \param outMesh           The facet mesh that is created
	/// \param needsUV           true if the UV in the facet mesh need to be filled
	/// \param needsFacetColors  true if the face colors are used
	/// \param needsVertexColors true if the vertex colors are used (only if it is available)
	///
	void CreateFacetMesh(FacetMesh** outMesh,boolean needsUV, boolean needsFacetColors, boolean needsVertexColors);
	//void CreateQuadFacetMesh(FacetMesh** outMesh,boolean needsUV, boolean needsFacetColors);

	// ****************************************************************************
	//								TriangulateMesh
	// 
	/// Triangulates a mesh. Only implemented for quads right now.
	/// 
	/// 
	void TriangulateMesh();

	// ****************************************************************************
	//								GenerateNormals
	// 
	/// Calculates the normal of the mesh
	/// 
	void	GenerateNormals();


	// ****************************************************************************
	//								HarmonizePolygonUVs
	// 
	/// Make sure that the uv are coherent on all the polygons of the mesh
	/// 
	void	HarmonizePolygonsUVs();

	void	HarmonizeQuadsUVs();

	virtual void	AllocateVertices(uint32			vertexCount,
									 boolean		allocateEdges,
									 boolean		allocatePolygons,
									 boolean		allocateUVs,
									 boolean		allocateNormals);

	void		AllocateVertexColors();

	// ****************************************************************************
	//								CopyVertices
	// 
	/// Copy all the vertices of a mesh into the current mesh
	/// 
	/// \param fromMesh  The mesh whose vertices are copied
	/// 
	virtual void   CopyVertices(const TMesh& fromMesh);

	/// Adds barycentric coordinates for each vertex
	void		AllocateBarycentricCoordinates(boolean allocate);
	boolean		HasBarycentricCoordinates() const { return fVertices.fAllocateBarycentricCoordinates; }

	void AllocateEdges(int32 edgeCount);

	// allocates the memory for a given number of polygons
	virtual void AllocatePolygons(int32 polygonCount);

	void AddPolygon(const TMCArray<TVertexUV>& vertices, 
					const TMCArray<boolean>& edgeCrease, 
					const int32 shadingDomainID,
					const boolean hidden);

	// this function assumes that the edges have already been added
	void AddPolygon(const TMCArray<TVertexUV>& vertices, 
					const int32 shadingDomainID,
					const boolean hidden);

	// this function has the list of the edges in the mesh
	void AddPolygon(const TMCArray<TVertexUV>& vertices,
					const TMCArray<int32>&	edges,
					const int32 shadingDomainID,
					const boolean hidden);


	void AddQuad(const TMCArray<TVertexUV>& verticesUV,
				 const TMCArray<boolean>& edgeCrease, 
				 const int32 shadingDomainID,
				 const boolean hidden);

	// add a edge to the mesh (does not check if it already exist)
	int32 AddEdgeLowLevel(TIndex2& vertices,const boolean creased);
	
	// check if the edge exists, if not adds a new edge to the mesh	
	int32 AddEdge(const int32 vertexIndex0,const int32 vertexIndex1,boolean creased);



	void	RemovePolygon(const int32 polygonIndex);
	void	RemoveEdge(const int32 edgeIndex);

	void	CreaseEdges(const real smoothingAngle);

	void InvalidateNormals();

	void SwapPolygonArray();

	void SetEdgeCount(int32 edgeCount)
	{
		fEdges.SetElemCount(edgeCount);
	}

	inline int32 GetPolygonCount() const
	{
		return fPolygons.GetElemCount();
	}
	inline TPolygon& GetPolygon(uint32 polygonIndex)
	{
		return fPolygons[polygonIndex];
	}
	inline TMCClassArray<TPolygon>& GetPolygons()
	{
		return fPolygons;
	}
	inline const TPolygon& GetPolygon(uint32 polygonIndex) const
	{
		return fPolygons[polygonIndex];
	}
	inline int32 GetQuadCount() const
	{
		return fQuads.GetElemCount();
	}
	inline TQuad& GetQuad(uint32 quadIndex)
	{
		return fQuads[quadIndex];
	}
	inline TMCClassArray<TQuad>& GetQuads()
	{
		return fQuads;
	}
	inline const TQuad& GetQuad(uint32 quadIndex) const
	{
		return fQuads[quadIndex];
	}
	inline int32 GetEdgeCount() const
	{
		return fEdges.GetElemCount();
	}
	inline const TEdge& GetEdge(uint32 edgeIndex) const
	{
		return fEdges[edgeIndex];
	}
	inline TEdge& GetEdge(uint32 edgeIndex)
	{
		return fEdges[edgeIndex];
	}
	inline int32 GetVertexCount() const
	{
		return fVertices.fPositions.GetElemCount();
	}
	inline TVertex	GetVertex(uint32 vertexIndex)
	{
		return TVertex(fVertices,vertexIndex);
	}
	inline TConstVertex	GetVertex(uint32 vertexIndex) const
	{
		return TConstVertex(fVertices,vertexIndex);
	}
	inline void SetWrapping(boolean wrapU,boolean wrapV)
	{
		fWrapping[0] = wrapU;
		fWrapping[1] = wrapV;
	}
	void SetVertex(int32 index,const TVector3& position,const TMCClassArray<TVector2>& uv,int32 edgeCount);

	TVertexArray&			GetVertices()			{ return fVertices; }
	const TVertexArray&		GetVertices() const		{ return fVertices; }

	TMCClassArray<TEdge>&	GetEdges()					{ return fEdges; }
	const TMCClassArray<TEdge>&	GetEdges() const		{ return fEdges; }

	TMCArray<boolean>&		GetWrapping()	{ return fWrapping; }

	
protected:
	int32 AddPolygonLowLevel( const TMCArray<TVertexUV>& vertices,const int32 shadingDomainID,const boolean hidden);
	
	// AddOnePolygon: adds one polygon at the end of the polygon array
	virtual void AddOnePolygon();	
protected:
	TVertexArray				fVertices;
	TMCClassArray<TEdge>		fEdges;
	TMCClassArray<TPolygon>		fPolygons;
	TMCClassArray<TQuad>		fQuads;

	TMCArray<int32>				fDeletedEdges;
	TMCArray<int32>				fDeletedPolygons;

	TMCArray<boolean>			fWrapping;

	boolean						fNormalsValid;
};

class TMeshList : public TMCSMPCountedObject
{
public:
	static	void	Create(TMeshList** outMesh)
	{ 
		TMCCountedCreateHelper<TMeshList> result(outMesh);
		result= new TMeshList;
	}
protected:
	TMeshList();
	~TMeshList();
public:	
	int32			GetMeshCount()				{ return fMeshList.GetElemCount(); }
	TMesh*			GetMesh(int32 meshIndex)	{ return fMeshList[meshIndex]; }

	void			SetMeshCount(int32 meshCount)				{ fMeshList.SetElemCount(meshCount); }
	void			SetMesh(int32 meshIndex,TMesh* mesh)		{ fMeshList.SetElem(meshIndex,mesh); }
protected:
	TMCPtrArray<TMesh>		fMeshList;
};

}// end namespace MeshDataStructure








#endif
