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

	File: HeightmapLoader
	Desc: Simple patch loader that loads data from a heightmap
	Date: 2003/03/02

	Author: Martin Persson
	Modified by Mike Prosser

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

#include <OgreConfigFile.h>
#include <OgreMaterialManager.h>
#include <OgreStringConverter.h>
#include <OgreImage.h>
#include <OgreSceneNode.h>
#include <OgreTechnique.h>
#include <OgrePass.h>
#include <OgreTextureUnitState.h>
#include <OgreSceneManager.h>

#include "HeightmapLoader.h"

namespace Ogre
{

//----------------------------------------------------------------------------

HeightmapLoader::HeightmapLoader(SceneNode *sceneRoot)
//    : BDAMPatchLoader(sceneRoot)
{
    mInited = false;

    mMapSizeX  = mMapSizeY = 0;
    mHeightMap = 0;

    // get default material
    mMaterial = reinterpret_cast<Material *>
	(MaterialManager::getSingleton().getByName("BaseWhite"));
}

//----------------------------------------------------------------------------

HeightmapLoader::~HeightmapLoader()
{
    if (mHeightMap != 0) delete mHeightMap;
	fclose(savefile);
}

//----------------------------------------------------------------------------

unsigned char* HeightmapLoader::loadRAWHeightmap(const char *filename,
			   			 unsigned int realSize,
						 unsigned int requestSize,
						 unsigned int xoff,
						 unsigned int yoff)
{
    unsigned char *heightMap;
    unsigned int readBytes = 0;
    unsigned int off = 0;

    FILE *fp;

    // allocate memory for the heightmap 
    if ((heightMap = new unsigned char[requestSize*requestSize]) == 0)
	return 0;

    // open the mapfile in read-only mode
    if ((fp = fopen(filename, "rb")) == 0)
	return 0;

    // seek to start offset
    fseek(fp, (yoff*realSize) + xoff, SEEK_SET);

    while (readBytes < (requestSize * requestSize))
    {
		// read 1 row of data
		fread(&heightMap[off], requestSize, 1, fp);
		off += requestSize;
		readBytes += requestSize;

		// seek to the next row
		fseek(fp, (realSize - requestSize), SEEK_CUR);
    }

    fclose(fp);
    return heightMap;
}

//----------------------------------------------------------------------------

bool HeightmapLoader::initialise(const String& filename)
{
    ConfigFile config;
    config.load(filename);


// NO GOOD, would choke computer with big maps!!!
//    mHeightMap = new Image();
//    mHeightMap->load(heightmap);

    std::cout << "Setting some variables" << std::endl;

    mScale.x = atof(config.getSetting("Scale.x").c_str());
    mScale.y = atof(config.getSetting("Scale.y").c_str());
    mScale.z = atof(config.getSetting("Scale.z").c_str());
    mScaleHeight = atof(config.getSetting("Scale.height").c_str());
    if (mScale.x == 0) mScale.x = 1.0;
    if (mScale.y == 0) mScale.y = 0.25;
    if (mScale.z == 0) mScale.z = 1.0;
    if (mScaleHeight == 0) mScaleHeight = 1.0;
    std::cout << "Scale : " << mScale.x << "," << mScale.y << "," << mScale.z << "," << mScaleHeight << std::endl;
    
    
	// TODO One of these has to be removed
	// It is either we use a fixed distance per patch
	// or we use a fixed number of quads per patch (prob 2e is best)
    clipRegion = atof(config.getSetting("ClipRegion").c_str());
    if (clipRegion == 0) clipRegion = 10;

//    clipSize = atoi(config.getSetting("ClipSize").c_str());
//    if (clipSize == 0) clipSize = 100;


    mWorld.x = atof(config.getSetting("World.x").c_str());
    mWorld.y = atof(config.getSetting("World.y").c_str());
    mWorld.z = atof(config.getSetting("World.z").c_str());
    mOffset = atof(config.getSetting("World.height").c_str());

    std::cout << "Clipmap map present? : ";
    String clipmap = config.getSetting("ClipmapMap");
    String savemap = config.getSetting("SaveClipmapMap");
    if ((savemap == "YES")||(savemap == "TRUE")||(savemap == "yes")||(savemap == "true")) {
    	saveClipmap = true;
    } else {
    	saveClipmap = false;
    }
    if (clipmap!=""){
	    swapmap = true;
	    if (saveClipmap){	    	
		    std::cout << "GENERATING" << std::endl;
		    //TODO maybe first write it, and then read it?
			savefile = fopen(clipmap.c_str(),"w+b");
		    String heightmap = config.getSetting("HeightMap");
			generateClipmapTree(heightmap);			
		} else {
		    std::cout << "YES" << std::endl;
			savefile = fopen(clipmap.c_str(),"rb");
	    	loadClipmapTree();
	    }
    } else {
	    swapmap = false;
	    std::cout << "NO" << std::endl;
	    String heightmap = config.getSetting("HeightMap");
	    generateClipmapTree(heightmap);
    }

#if USE_TEXTURES
	material = config.getSetting("WorldTexture").c_str();
#endif
	#if USE_NORMALS
		mMaterial->setLightingEnabled(true);
	#endif

//    std::cout << "blip" << std::endl;
    std::cout << "Patch is loaded" << std::endl;
    mInited = true;
    return true;
}
//
bool HeightmapLoader::checkValidMap(){
	//TODO make this sane
	int bdamPatchSize = 64;
    int sx = mHeightMap->getWidth() / bdamPatchSize;
    int sy = mHeightMap->getHeight() / bdamPatchSize;
    
    // check that heightmap is of correct size
    if ((sx * bdamPatchSize) + 1 != mHeightMap->getWidth() || 
		(sy * bdamPatchSize) + 1 != mHeightMap->getHeight())
    {
		mMapSizeX = mMapSizeY = 0;

			String err = "Error: Invalid heightmap size : "
			+ StringConverter::toString(mHeightMap->getWidth())
			+ "," + StringConverter::toString(mHeightMap->getHeight()) 
			+ ". Should be bdamPatchSize *n+1, bdamPatchSize *n+1";
		
		std::cout << err << std::endl;
		return false;
    }

    if (mHeightMap->getFormat() != PF_L8)
    {
		std::cout << "Error: Heightmap is not a grayscale image." << std::endl;
		return false;
    }
    mMapSizeX = sx;
    mMapSizeY = sy;
}
//----------------------------------------------------------------------------
bool HeightmapLoader::generateClipmapTree(const String& filename, bool rawdata){
	int i, j;
	if (rawdata){
	    std::cout << "This is raawwww data!" << std::endl;
	} else {
	    std::cout << "Loading heightmap-image" << std::endl;
// TODO : NO GOOD, would choke computer with big maps!!!
    	mHeightMap = new Image();
    	mHeightMap->load(filename);
	    std::cout << "is it OK? : ";
		bool ok = checkValidMap();
		if (ok) {
		    std::cout << "YES" << std::endl;
		} else {
		    std::cout << "NO" << std::endl;
		}
#if USE_NORMALS
		    std::cout << "Using normals" << std::endl;
#else
		    std::cout << "Not using normals" << std::endl;
#endif
		heightMap = mHeightMap->getData();
		int size = mHeightMap->getWidth()-1;
		mMapSizeX = mHeightMap->getWidth();
		mMapSizeY = mHeightMap->getHeight();

		// Open the file to write the clipmap to
		
	    std::cout << "Creating quadindex" << std::endl;
	    quadIndex = new QuadIndex(size);
	    
	    std::cout << "Setting fileformat" << std::endl;
	    // calculate the size of the quads to save
	    setVertexSaveSize(quadIndex);
	    setLevelHeaderSize(quadIndex);
	    quadIndex->setClipmapFile(savefile);
		

	    std::cout << "World " << mWorld.x << "," << mWorld.y << "," << mWorld.z << std::endl;
	    std::cout << "Scale " << mScale.x << "," << mScale.y << "," << mScale.z << std::endl;
	    std::cout << "Loading map" << std::endl;
	    std::cout << "Tree depth = " << quadIndex->getDepth() << std::endl;
		int width = mHeightMap->getWidth()-1;
		int height = mHeightMap->getHeight()-1;
//		Quad *patch = new Quad(quadIndex->getDepth()-1);
		if (saveClipmap){
			writeLevelHeader(quadIndex->getDepth()-1,width,height,savefile);
			for (j=0;j<size+1;j++){
				for (i=0;i<size+1;i++){
					Real height = heightMap[(j)*(size+1)+(i)]*mScale.y;
					Real* vertex = new Real[VERTEXSIZE];
					short ind=0;
					Vector3 vertexPos = getVertex(i,j,0,quadIndex->getDepth()-1,quadIndex);
					vertex[ind++]=vertexPos.x*mScale.x+mWorld.x;
					vertex[ind++]=vertexPos.y*mScale.y+mWorld.y;
					vertex[ind++]=vertexPos.z*mScale.z+mWorld.z;
#if USE_NORMALS
					Vector3* normal = new Vector3();
					getNormal(i,j,normal,heightMap);
					vertex[ind++]=normal->x;
					vertex[ind++]=normal->y;
					vertex[ind++]=normal->z;
#endif
#if USE_TEXTURES
					Real tx,ty;
					getTextureCoordinates(i,j,tx,ty);
					vertex[ind++]=tx;					
					vertex[ind++]=ty;
//					std::cout << "Texture coordinate " << tx << "," << ty << std::endl;
#endif

					writeVertex(vertex, height, savefile);
					
					delete normal;
					delete [] vertex;
				}
			}
		} else {
			for (j=0;j<size;j++){
				for (i=0;i<size;i++){
					Quad *patch = new Quad(quadIndex->getDepth()-1);
					Real* vertices = patch->vertices;
	#if USE_NORMALS
					Real* normals = patch->normals;
	#endif
	#if USE_16BIT_INDICES
					unsigned short* indices = patch->indices;
	#else
					unsigned int* indices = patch->indices;
	#endif
					// Init the vertices
					Real hoogte = 0;
					for (int l=0;l<2;l++){
						for (int k=0;k<2;k++){
							Real height = heightMap[(j+l)*(size+1)+(i+k)]*mScale.y;
							hoogte += height;
							*(vertices++)=(i+k)*mScale.x+mWorld.x;
							*(vertices++)=height*mScale.y+mWorld.y;
							*(vertices++)=(j+l)*mScale.z+mWorld.z;
	#if USE_NORMALS
							Vector3* normal = new Vector3();
							getNormal(i+k,j+l,normal,heightMap);
	//						std::cout << "normal " << i+k << "," << j+l << " : " << normal->x << "," << normal->y << "," << normal->z << std::endl;
							*(normals++)=normal->x;
							*(normals++)=normal->y;
							*(normals++)=normal->z;
	#endif
						}
					}
					patch->height = hoogte / 4.0;
					if ((i+j) % 2 == 0){
						indices[0]=0;
						indices[1]=2;
						indices[2]=1;
						indices[3]=2;
						indices[4]=3;
						indices[5]=1;
					} else {
						indices[0]=0;
						indices[1]=3;
						indices[2]=1;
						indices[3]=3;
						indices[4]=0;
						indices[5]=2;
					}
					if (!swapmap){
						quadIndex->setQuad(i,j,quadIndex->getDepth()-1,patch);
					} else {
	//					writeQuad(patch,savefile);
						delete patch;
					}
	//				std::cout << "added patch " << patch << " " << i << "," << j << " levelsize " << quadIndex->getLevelSize(quadIndex->getDepth()-1) << " level " << quadIndex->getDepth()-1 << std::endl;
				}
			}
		}
//				quadIndex->setQuad(0,0,quadIndex->getDepth()-1,patch);

		if (!swapmap){
			for (j=0;j<height;j++){
				for (i=0;i<width;i++){			
					Quad *patch=quadIndex->getQuad(i,j,quadIndex->getDepth()-1);
					if (i>0){
						patch->setLeft(quadIndex->getQuad(i-1,j,quadIndex->getDepth()-1));
					}
					if (i<width-2){
						patch->setRight(quadIndex->getQuad(i+1,j,quadIndex->getDepth()-1));
					}
					if (j>0){
						patch->setTop(quadIndex->getQuad(i,j-1,quadIndex->getDepth()-1));
					}
					if (j<height-2){
						patch->setBottom(quadIndex->getQuad(i,j+1,quadIndex->getDepth()-1));
					}
				}
			}
		}
		collapseLevels(quadIndex);
		return true;
	}
}

bool HeightmapLoader::loadClipmapTree(){
	int i, j;
#if USE_NORMALS
		    std::cout << "Using normals" << std::endl;
#else
		    std::cout << "Not using normals" << std::endl;
#endif
		
		int size = readMapsize(savefile);
		mMapSizeX = size+1;
		mMapSizeY = size+1;

	    quadIndex = new QuadIndex(size);
	    
	    // calculate the size of the quads to save
	    setVertexSaveSize(quadIndex);
	    setLevelHeaderSize(quadIndex);
	    quadIndex->setClipmapFile(savefile);
		

	    std::cout << "World " << mWorld.x << "," << mWorld.y << "," << mWorld.z << std::endl;
	    std::cout << "Scale " << mScale.x << "," << mScale.y << "," << mScale.z << std::endl;
	    std::cout << "Tree depth = " << quadIndex->getDepth() << std::endl;
		return true;
		
}

void HeightmapLoader::collapseLevels(QuadIndex* quadIndex){
    std::cout << "Collapsing levels" << std::endl;
	for (int i=quadIndex->getDepth()-1;i>0;i--){
		collapseLevel(quadIndex,i);
	}
}

void HeightmapLoader::collapseLevel(QuadIndex* quadIndex,int level){
    std::cout << "Collapsing level " << level << std::endl;
    int i, j;
    int depth = quadIndex->getDepth();
	int size = quadIndex->getLevelSize(level-1);
	int mapsize = quadIndex->getLevelSize(depth-1);
	if (saveClipmap){
		writeLevelHeader(level-1,quadIndex->getLevelSize(level-1),quadIndex->getLevelSize(level-1),savefile);
		
			for (j=0;j<size+1;j++){
				for (i=0;i<size+1;i++){
					Real height = getHeight((i)<<(depth-level),(j)<<(depth-level),level-1)*mScale.y;
					Real* vertex = new Real[VERTEXSIZE];
					short ind=0;
					Vector3 vertexPos = getVertex(i<<(depth-level),j<<(depth-level),0,level-1,quadIndex);
					vertex[ind++]=vertexPos.x*mScale.x+mWorld.x;
					vertex[ind++]=vertexPos.y*mScale.y+mWorld.y;
					vertex[ind++]=vertexPos.z*mScale.z+mWorld.z;
#if USE_NORMALS
					Vector3* normal = new Vector3();
					getNormal(((i)<<(depth-level)),((j)<<(depth-level)),level-1,normal,heightMap);
					vertex[ind++]=normal->x;
					vertex[ind++]=normal->y;
					vertex[ind++]=normal->z;
#endif
#if USE_TEXTURES
					Real tx,ty;
					getTextureCoordinates(i<<(depth-level),j<<(depth-level),tx,ty);
					vertex[ind++]=tx;
					vertex[ind++]=ty;
#endif
					int pos = getVertexPosition(i,j,level-1, quadIndex);
					fseek(savefile, pos, SEEK_SET);
					
					writeVertex(vertex, height, savefile);
					delete normal;
					delete [] vertex;
				}
			}
	} else {
//	std::cout << "size " << size << std::endl;
	for (j=0;j<quadIndex->getLevelSize(level-1);j++){
		for (i=0;i<quadIndex->getLevelSize(level-1);i++){
//		    std::cout << "Collapsing  " << i << "," << j << std::endl;
			Quad* quad = new Quad(level-1);
//		    std::cout << "Get vertices of new quad" << std::endl;
			Real* vertices = quad->vertices;
#if USE_NORMALS
			Real* normals = quad->normals;
#endif
#if USE_16BIT_INDICES
			unsigned short* indices = quad->indices;
#else
			unsigned int* indices = quad->indices;
#endif
			// Init the vertices
			int index=0;
//		    std::cout << "Get quad and vertices" << std::endl;
			Real hoogte = 0;
			for (int l=0;l<2;l++){
				for (int k=0;k<2;k++){
					if (!swapmap){
						Quad* tempQuad = quadIndex->getQuad(2*i+k,2*j+l,level);
						hoogte += tempQuad->height;
	//				    std::cout << "TempQuad " << tempQuad->vertices[index] << "," << tempQuad->vertices[index+1] << "," << tempQuad->vertices[index+2] << " " << tempQuad << " level " << level << std::endl;
#if USE_NORMALS
						*(normals++)=tempQuad->normals[index];
						*(normals++)=tempQuad->normals[index+1];
						*(normals++)=tempQuad->normals[index+2];
#endif
						*(vertices++)=tempQuad->vertices[index++];
						*(vertices++)=tempQuad->vertices[index++];
						*(vertices++)=tempQuad->vertices[index++];
					}
//					std::cout << "getDepth " << quadIndex->getDepth() << std::endl;
				}
			}
			quad->height = hoogte/4.0;
			// Just to make it easier to debug 2 level drawn together
/*			if ((quadIndex->getDepth()+level) % 2 == 1){
				indices[0]=0;
				indices[1]=1;
				indices[2]=2;
				indices[3]=2;
				indices[4]=1;
				indices[5]=3;
			} else {
				indices[0]=0;
				indices[1]=1;
				indices[2]=3;
				indices[3]=3;
				indices[4]=2;
				indices[5]=0;
			}
*/
				if ((i+j) % 2 == 1){
					indices[0]=0;
					indices[1]=2;
					indices[2]=1;
					indices[3]=2;
					indices[4]=3;
					indices[5]=1;
				} else {
					indices[0]=0;
					indices[1]=3;
					indices[2]=1;
					indices[3]=3;
					indices[4]=0;
					indices[5]=2;
				}
//		    std::cout << "Set new quad " << quad << std::endl;
			if (!swapmap){
			    quadIndex->setQuad(i,j,level-1,quad);
			}
		}
	}
	if (!swapmap){
		for (j=0;j<quadIndex->getLevelSize(level);j++){
			for (i=0;i<quadIndex->getLevelSize(level);i++){
				Quad *patch=quadIndex->getQuad(i,j,level);
				if (i>0){
					patch->setLeft(quadIndex->getQuad(i-1,j,level));
				}
				if (i<quadIndex->getLevelSize(level)-1){
					patch->setRight(quadIndex->getQuad(i+1,j,level));
				}
				if (j>0){
					patch->setTop(quadIndex->getQuad(i,j-1,level));
				}
				if (j<quadIndex->getLevelSize(level)-1){
					patch->setBottom(quadIndex->getQuad(i,j+1,level));
				}
//				std::cout << "getDepth " << quadIndex->getDepth() << std::endl;
			}
		}
	}
	}
	
}

Real HeightmapLoader::getHeight(int x, int y, int level){
	int dist;
	if (level<quadIndex->getDepth()-1){
		dist = (1<<(quadIndex->getDepth()-level-2));
	} else {
		dist = 0;
	}
	int i,j;
	int num=0;
	Real result=0;
	for (i=x-dist;i<=x+dist;i++){
		for (j=y-dist;j<=y+dist;j++){
			if ((i>=0)&&(i<mMapSizeX)&&(j>=0)&&(j<mMapSizeY)){
				num++;
				result+=heightMap[j*mMapSizeX+i];
			}
		}
	}
	result /= (Real)num;
	return result;
}

void HeightmapLoader::getNormal(int x, int y, int level, Vector3 *normal, unsigned char* heightMap){
	int dist;
	if (level<quadIndex->getDepth()-1){
		dist = (1<<(quadIndex->getDepth()-level-2));
	} else {
		dist = 0;
	}
	int i,j;
	int num=0;
	Vector3* tnormal = new Vector3();
	for (i=x-dist;i<=x+dist;i++){
		for (j=y-dist;j<=y+dist;j++){
			if ((i>=0)&&(i<mMapSizeX)&&(j>=0)&&(j<mMapSizeY)){
				num++;
				getNormal(i,j, tnormal,heightMap);
				(*normal) += (*tnormal);
			}
		}
	}
	delete tnormal;
	if (num!=0){
		normal->normalise();
	}
}

void HeightmapLoader::getTextureCoordinates(int x, int y, Real &tx, Real &ty)
{   
	tx = x/(Real)mHeightMap->getWidth();
	ty = y/(Real)mHeightMap->getHeight();
}

void HeightmapLoader::getNormal(int x, int z, Vector3 *normal, unsigned char* heightMap)
{   
    Vector3 here, left, down;
                
    int heightMapWidth = mHeightMap->getWidth();
    here.x = x;
    here.y = heightMap[z * heightMapWidth + x]
        * mScale.y + mWorld.y;
    here.z = z;
    
    left.x = x - 1;
    if (x > 0)
        left.y = heightMap[z * heightMapWidth + (x - 1)]
            * mScale.y + mWorld.y;
    else
        left.y = here.y;

    left.z = z;

    down.x = x;
    if (z < heightMapWidth)
        down.y = heightMap[(z + 1) * heightMapWidth + x]
            * mScale.y + mWorld.y;
    else
        down.y = here.y;

    down.z = z + 1;

    left = left - here;
    down = down - here;

    left.normalise();
    down.normalise();

    *normal = left.crossProduct(down);
    normal->normalise();
}

int HeightmapLoader::getMapSize(){
	return mMapSizeX;
}

bool HeightmapLoader::writeVertex(Real* vertex, Real height, FILE *file){
	int sizewritten;
	sizewritten = fwrite(&height, sizeof(Real), 1, file);
	if (sizewritten < 1) {
		std::cout << "Coult not write to file!" << std::endl;
		return false;
	}
	//write vertex and if used normal
	sizewritten = fwrite(vertex, sizeof(Real), SIMPLESIZE, file);
	if (sizewritten < SIMPLESIZE) {
		std::cout << "Coult not write to file!" << std::endl;
		return false;
	}
	std::cout << "saving vertex ";
	for (int i=0;i<SIMPLESIZE;i++){
		std::cout << vertex[i];
		if (i<SIMPLESIZE-1) std::cout << ",";
	}
	std::cout << " with height " << height << std::endl;
	
	//WARNING: you can only load clipmaps saved with the same configuration as
	//where they are written in
	
	return true;
}


bool HeightmapLoader::writeLevelHeader(int level, int width, int height, FILE *file){
//	std::cout << "Writing level-header " << level << " " << width << "," << height << " to " << file << std::endl;
	int sizewritten;
	
	sizewritten = fwrite(&level, sizeof(int), 1, file);
	if (sizewritten < 1) {
		std::cout << "Coult not write to file!" << std::endl;
		return false;
	}
	sizewritten = fwrite(&width, sizeof(int), 1, file);
	if (sizewritten < 1) {
		std::cout << "Coult not write to file!" << std::endl;
		return false;
	}
	sizewritten = fwrite(&height, sizeof(int), 1, file);
	if (sizewritten < 1) {
		std::cout << "Coult not write to file!" << std::endl;
		return false;
	}
//	std::cout << "New Writing to pos " << ftell(file) << std::endl;

	return true;
}

void HeightmapLoader::setVertexSaveSize(QuadIndex* quadIndex){
	    saveSize = sizeof(Real);
	    saveSize += sizeof(Real)*SIMPLESIZE;

	    quadIndex->setVertexSize(saveSize);
}

void HeightmapLoader::setLevelHeaderSize(QuadIndex* quadIndex){
	    levelHeaderSize = sizeof(int)*3;
	    quadIndex->setLevelHeaderSize(levelHeaderSize);
}

/*
void HeightmapLoader::setQuadSize(QuadIndex* quadIndex){
	    quadSize = sizeof(Real);
	    quadSize += sizeof(Real)*3*4;
#if USE_NORMALS
	    quadSize += sizeof(Real)*12;
#endif
#if USE_16BIT_INDICES
		quadSize +=  sizeof(short) * 6;
#else
		quadSize +=  sizeof(int) * 6;
#endif

	    quadIndex->setQuadSize(quadSize);
}
*/

int HeightmapLoader::readMapsize(FILE* file){
	fseek(file, 0, SEEK_SET);
	int level;
	int width;
	int height;
	int rlength = fread(&level, sizeof(int), 1, file);
	rlength = fread(&width, sizeof(int), 1, file);
	rlength = fread(&height, sizeof(int), 1, file);
	return width;
}

int HeightmapLoader::getVertexPosition(int x, int y, int level, QuadIndex* quadIndex){
	if ((level < quadIndex->getDepth())&&(level>=0)&&(x <= quadIndex->getLevelWidth(level))&&(y <= quadIndex->getLevelHeight(level))&&(x >= 0)&&(y >= 0)) {
		int pos = (quadIndex->getDepth()-level)*levelHeaderSize;
		int i;
		for (i=quadIndex->getDepth()-1;i>level;i--){
			pos+=(quadIndex->getLevelHeight(i)+1)*(quadIndex->getLevelWidth(i)+1)*saveSize;
		}
		pos += saveSize*(x+y*(quadIndex->getLevelWidth(level)+1));
//		std::cout << "Going to write " << x << "," << y << " level " << level << " to " << pos << std::endl;
		return pos;
	} else {
		std::cout << "WARNING : Not in boundaries!" << std::endl;	
		return -1;
	}
}

Vector3 HeightmapLoader::getVertex(int x, int y, int direction, int level, QuadIndex* quadIndex){
	std::cout << "Getting vertex... " << x << "," << y << std::endl;
	int size = quadIndex->getLevelWidth(level);
/*	Real posx = (2/(Real)size)*x-1;
	Real posy = (2/(Real)size)*y-1;
	Vector3 vertex = Vector3(posx,1,posy);
	std::cout << "v : " << vertex.x << "," << vertex.y << "," << vertex.z << std::endl;
	vertex.normalise();
	std::cout << "v : " << vertex.x << "," << vertex.y << "," << vertex.z << std::endl;
	vertex *= (1+getHeight(x,y,level))*mScaleHeight;
	std::cout << "v : " << vertex.x << "," << vertex.y << "," << vertex.z << std::endl;
	Vector3 normal = vertex;
	normal.normalise();
	vertex += normal * mOffset;
*/	Vector3 vertex = Vector3((x-size/2.0)<<(quadIndex->getDepth()-level-1),getHeight(x,y,level),(y-size/2.0)<<(quadIndex->getDepth()-level-1));
	std::cout << "vertex : " << vertex.x << "," << vertex.y << "," << vertex.z << std::endl;

	return vertex;
	
}

} // namespace Ogre

