/*
/ BSTMTERRAIN.H
/ *************
/ The main terrain implementation that supports
/ heightmap loading and random terrain generation.
/ Once created, the heightmap is split into patches
/ and only the visible sections are rendered.
/
/ Will Beddow 2010 - http://343gs.com/brainstem
/
/ This software is currently under development
/ and is subject to change and improvement. Some
/ aspects of the system are incomplete and/or 
/ unstable due to ongoing implementation.
/
*/

#ifndef __BSTMTERRAIN_H__
#define __BSTMTERRAIN_H__

#include "Compile.h"
#include "Types.h"
#include "Terrain.h"
#include "Texture.h"
#include "Mesh.h"
#include "Heightmap.h"

#include "BstmDevice.h"

#include <Windows.h>

namespace Brainstem 
{
	class TerrainPatch
	{
	public:

		TerrainPatch();
		~TerrainPatch();
		void Release();

		HRESULT CreateMesh(LPDIRECT3DDEVICE9 device, Heightmap* Map, RECT source, float scaleFactor);					
		void Render(int texture);	

		LPD3DXMESH Mesh;
		RECT MapRect;
		BoundingVolume Bounds;
	};

	class Terrain : public ITerrain
	{
	public:
		Terrain(IDirect3DDevice9* device, ID3DXEffect* effect);
		~Terrain();

		bool Init();
		void Update();
		void Render(ICamera* camera);
		void Release();

		void ApplyTexture(ITexture* texture);
		ITexture* GetTexture();

		BoundingVolume GetBounds() { return Bounds; }

		Dimension2<int> GetDimensions() 
		{ 
			Dimension2<int> mapSize = Map->GetSize();
			return Dimension2<int>(mapSize.Width * ScaleFactor, mapSize.Height * ScaleFactor);
		}

		void GenerateFromFile(unsigned int patches, const char* filename, float scaleFactor);
		void GenerateRandom(unsigned int patches, int seed, float noiseSize, float persistence, int octaves, float scaleFactor);

		float GetHeight(float x, float z);

		Heightmap* Map;
		IDirect3DDevice9* Device;

		AUTO_OBJECT_SIZE;

		void SetTechnique(const char* technique) { Technique = technique; }
		const char* GetTechnique() { return Technique; };

	private:

		ID3DXEffect* Effect;
		IPtr<ITexture> TerrainTexture;
		const char* Technique;

		void CreatePatches(int numPatches);
		std::vector<TerrainPatch*> Patches;	

		unsigned int TotalPatches;
		float ScaleFactor;

		BoundingVolume Bounds;
	};
}

#endif