//*********************************
//Halsafar's 3D City - LandScape Class
//
//Function: Allows manual creation of vertices and index's along with textures for
//			textures for a specific map segment.  65535 max segments, that high will
//			prolly cause an error
//
//Date: September 2004
//
//Author: Steve Damm
//*********************************



#ifndef __LANDSCAPEGUARD__
#define __LANDSCAPEGUARD__



class LandScape
{
private:
	//Segment structure -- each segment represents a basic land mass scheme
	struct SEGMENT
	{
		string				m_Name;			//Name of the segment
		D3DMATRIX			matTemp;		//Temp basic Matrix
		vector<D3DVERTEX>	m_Vertices;		//Vertices
		D3DVERTEX*			m_VerticesArray;//Vertices array -- used for render
		D3DVECTOR			m_Pos;			//Position
		LPDIRECTDRAWSURFACE7 m_Texture;		//The actual texture for this segment
		//UINT				m_TextureID;	//Texture Idea
		vector<WORD>		m_Index;		//The Index
		WORD*			    m_IndexArray;	//The Index as an array -- always set on update
	};

	UINT	m_MaxSegments;			//Numbers of Segments

	vector<SEGMENT> Segments;		//Segments

	LPDIRECT3DDEVICE7 m_Device3D;	//Device 3D
public:
	//Constructor
	LandScape()
	{
		m_MaxSegments = 0;
	}

	//Constructor
	LandScape(LPDIRECT3DDEVICE7 &lpDevice)
	{
		m_MaxSegments = 0;
		m_Device3D = lpDevice;
	}
	
	
	//Destructor
	~LandScape()
	{

	}
	
	void SetPoint_Device3D(LPDIRECT3DDEVICE7 &lpDevice3D);	//Allows setting the device pointer at some time

	//-----------------
	//Identify Matrix
	//-----------------
	inline VOID SetIdentityMatrix(D3DMATRIX& m)
	{
		m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
		m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
		m._11 = m._22 = m._33 = m._44 = 1.0f;
	}


	//------------------
	//Add a segment to the list, with a unique ID to allow editing
	//------------------
	inline void CreateSegment(string SegmentID)
	{
		//temp a segment, set some basics and push it into the vector
		SEGMENT temp;

		temp.m_Name = SegmentID;
		SetIdentityMatrix(temp.matTemp);

		Segments.push_back(temp);

		//incrememnt max segments
		m_MaxSegments++;
	}
	
	//------------------
	//Adds a vertice to a segments vertice vector
	//------------------
	inline void AddVertice(string SegmentID,int x,int y,int z, float tileU, float tileV)
	{
		//Loop through each segment
		for (int i = 0; i < m_MaxSegments; i++)
		{
			//Id match
			if (Segments[i].m_Name == SegmentID)
			{
				//temp a vertex, fill it, push it into the vertices vector of this segment
				D3DVERTEX temp;
				temp = D3DVERTEX( D3DVECTOR(x, y, z), D3DVECTOR(0, 1, 0), tileU, tileV);
				Segments[i].m_Vertices.push_back(temp);
			}
		}

	}
	
	//---------------
	//Adds an Index to the vector -- obviously must be set in order
	//---------------
	inline void AddIndex(string SegmentID, WORD Index)
	{
		for (int i = 0; i < m_MaxSegments; i++)
		{
			if (Segments[i].m_Name == SegmentID)	Segments[i].m_Index.push_back(Index);
		}
	}
	

	//-----------------
	//Adds a Texture pointer to a Segment
	//-----------------
	inline void AddTexture(string SegmentID, LPDIRECTDRAWSURFACE7 &lpTexture)
	{
		for (int i = 0; i < m_MaxSegments; i++)
		{
			if (Segments[i].m_Name == SegmentID)	Segments[i].m_Texture = lpTexture;
		}
	}

	//You must update before a render -- may not error, but will not work
	void Update(string SegmentID);			//Updates a segment to a useable form
	
	//-----------------------
	//This will Render all the segments
	//-----------------------
	inline void Render()
	{
		for (int i = 0; i < m_MaxSegments; i++)
		{
			m_Device3D->SetTransform( D3DTRANSFORMSTATE_WORLD, &Segments[i].matTemp );
			
			m_Device3D->SetTexture(0, Segments[i].m_Texture);
			m_Device3D->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, Segments[i].m_VerticesArray+0, 4, Segments[i].m_IndexArray, 4, NULL );
		}
	}


};


//---------------
//Sets the m_Index vector into the m_IndexArray array.  Must be done before render
//---------------
__forceinline void LandScape::Update(string SegmentID)
{	
	//loop through each segment till you find an ID
	for (int i = 0; i < m_MaxSegments; i++)
	{
		//ID FOUND
		if (Segments[i].m_Name == SegmentID)
		{
			//Thanks to sunburnt:
			//Copy the m_Index vector into m_IndexArray
			Segments[i].m_IndexArray = new WORD[Segments[i].m_Index.size()];
			memcpy(Segments[i].m_IndexArray, &Segments[i].m_Index[0], sizeof(WORD) * Segments[i].m_Index.size());

			//Copy the m_Vertices Vertex into m_VerticesArray
			Segments[i].m_VerticesArray = new D3DVERTEX[Segments[i].m_Vertices.size()];
			memcpy(Segments[i].m_VerticesArray, &Segments[i].m_Vertices[0], sizeof(D3DVERTEX) * Segments[i].m_Vertices.size());
		}
	}
}


//--------------------
//Sets the device 3d pointer -- use if you did not construct with a pointer param
//--------------------
__forceinline void LandScape::SetPoint_Device3D(LPDIRECT3DDEVICE7 &lpDevice3D)
{
	m_Device3D = lpDevice3D;
}
#endif