#include "heightmap.h"
#include "main.h"
#include "skybox.h"

extern rMath *m;

inline int Offset(int x, int y, int sizeRow)
{
	return (x + y*sizeRow);
}

rHeightMap::~rHeightMap()
{
	glDeleteLists(listIndex, 1);
	if(heights)
	{
		delete [] heights;
		heights = 0;
	}
	if(normals)
	{
		delete [] normals;
		normals = 0;
	}
}

void rHeightMap::Load(vector3* normalArray, float* heightArray,
		int xb,
		int zb,
		int patchSize,
		int mapSize,
		float &highestY,
		float &lowestY)
{
	if(heightArray == 0)
		return;

	normals = 0;
	sideX = sideZ = patchSize;

	// Corner patches are smaller
	if(xb + sideX >= mapSize)
		sideX--;

	if(zb + sideZ >= mapSize)
		sideZ--;

	int allocSize = (sideX + 1)*(sideZ + 1);

	heights = new float [allocSize];

	int rowElems = sideX + 1;

	for(int i=0; i<=sideZ; i++)
	{
		m->MemCopy(
			heights + i*rowElems,
			heightArray + Offset(xb, zb+i, mapSize),
			sizeof(float) * rowElems);
	}

	if(normalArray)
	{
		normals = new vector3 [allocSize];
		for(int i=0; i<=sideZ; i++)
		{
			memcpy(
				normals + i*rowElems,
				normalArray + Offset(xb, zb+i, mapSize),
				sizeof(vector3) * rowElems);
		}
	}

	listIndex = glGenLists(1);
	glNewList(listIndex, GL_COMPILE);

		float u, v;
		float y;
		int offsetX = xb - mapSize/2;
		int offsetZ = zb - mapSize/2;

		highestY = *heights;
		lowestY = highestY;

		for(int z = 0; z < sideZ; z++)
		{
			glBegin(GL_TRIANGLE_STRIP);
			for(int x = 0; x <= sideX; x++)
			{
				y = *(heights + x + z * rowElems);

				if(y > highestY)
					highestY = y;
				else if(y < lowestY)
					lowestY = y;

				u = (float)(x+xb)/(float)mapSize;
				v = 1.0f - (float)(z+zb)/(float)mapSize;

				glMultiTexCoord2f(GL_TEXTURE0, u, v);
				glMultiTexCoord2f(GL_TEXTURE1, u, v);
				glVertex3f((float)(x + offsetX), y, (float)(z + offsetZ));

				z++;
				y = *(heights + x + z * rowElems);

				if(y > highestY)
					highestY = y;
				else if(y < lowestY)
					lowestY = y;

				v = 1.0f - (float)(z+zb)/(float)mapSize;

				glMultiTexCoord2f(GL_TEXTURE0, u, v);
				glMultiTexCoord2f(GL_TEXTURE1, u, v);
				glVertex3f((float)(x + offsetX), y, (float)(z + offsetZ));
				z--;
			}
			glEnd();
		}

	glEndList();
}

void rHeightMap::Render()
{
	glCallList(listIndex);
}