#include "quadtree.h"
#include "renderer.h"

extern rRenderer *g_Renderer;

rQuadTree::~rQuadTree()
{
	if(nodes)
	{
		delete [] nodes;
		nodes = 0;
	}
	if(HM)
	{
		delete HM;
		HM = 0;
	}
}

void rQuadTree::Create(rMap *Map, int side_Size, vector3* normalArray, float* heightArray)
{
	CreateRec(Map, 0, 0, side_Size, normalArray, heightArray);
}
void rQuadTree::CreateRec(rMap *Map, int X, int Z, int side_Size, vector3* normalArray, float* heightArray)
{
	if(heightArray == 0)
		return;

	g_Map = Map;
	x = X;
	z = Z;

	sideSize = side_Size;
	
	if(sideSize <= max_size)
	{
		HM = new rHeightMap;
		HM->texture = g_Map->texture;
		HM->detailTexture = g_Map->detailTexture;
		nodes = 0;
		bDivided = false;
		HM->Load(normalArray, heightArray, x, z, sideSize, g_Map->sideSize, highestY, lowestY);
	}else
	{
		HM = 0;
		bDivided = true;

		nodes = new rQuadTree [4];

		int halfSize = sideSize/2;

		nodes[0].CreateRec(g_Map, x, z, halfSize, normalArray, heightArray);
		nodes[1].CreateRec(g_Map, x + halfSize, z, halfSize, normalArray, heightArray);
		nodes[2].CreateRec(g_Map, x, z + halfSize, halfSize, normalArray, heightArray);
		nodes[3].CreateRec(g_Map, x + halfSize, z + halfSize, halfSize, normalArray, heightArray);
	
		highestY = nodes[0].highestY;
		lowestY = nodes[0].lowestY;

		for(int i=1; i<4; i++)
		{
			float h = nodes[i].highestY;
			float g_Logger = nodes[i].lowestY;

			if(highestY < h)
				highestY = h;
			if(lowestY > g_Logger)
				lowestY = g_Logger;
		}
	}
	
	x -= g_Map->sideSize / 2;
	z -= g_Map->sideSize / 2;
}

void rQuadTree::Draw()
{
		glActiveTexture(GL_TEXTURE0);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, g_Map->texture);

		glActiveTexture(GL_TEXTURE1);
		glEnable(GL_TEXTURE_2D);

		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 2);
		glBindTexture(GL_TEXTURE_2D, g_Map->detailTexture);

		glMatrixMode(GL_TEXTURE);	//Scale the details
		glLoadIdentity();
		glScalef(g_Map->detailTextureScale, g_Map->detailTextureScale, 1);
		glMatrixMode(GL_MODELVIEW);

		DrawRec();

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
		glDisable(GL_TEXTURE_2D);

		glActiveTextureARB(GL_TEXTURE0_ARB);
	//	glDisable(GL_TEXTURE_2D);

}

void rQuadTree::DrawRec()
{
	if(g_Renderer->IsBoxInFrustum(
		(float)x, lowestY, (float)z,
		(float)(x+sideSize), highestY, (float)(z+sideSize))) {

		if(bDivided)
		{
			nodes[0].DrawRec();
			nodes[1].DrawRec();
			nodes[2].DrawRec();
			nodes[3].DrawRec();
		} else
			HM->Render();
	}
}
