#include "ClipmapRegion.h"

namespace Ogre {

ClipmapRegion::ClipmapRegion(Vector3ix upperLeftQuad,Vector3ix lowerRightQuad, 
					Vector3ix innerUpperLeftQuad, Vector3ix innerLowerRightQuad,
					QuadIndex* quadIndex,
					HardwareVertexBufferSharedPtr &vertexBuffer,
					HardwareIndexBufferSharedPtr &indexBuffer,
					ClipmapRegion* previousRegion,
					int vertexOffset)
{
	std::cout << "Creating new region... level " << upperLeftQuad.z << std::endl;
	this->upperLeftQuad = upperLeftQuad;
	this->lowerRightQuad = lowerRightQuad;
	this->innerUpperLeftQuad = innerUpperLeftQuad;
	this->innerLowerRightQuad = innerLowerRightQuad;
	this->vertexBuffer = vertexBuffer;
	this->indexBuffer = indexBuffer;
	changed = true;
	setQuadIndex(quadIndex);
	initializeVertices();
	this->vertexOffset=vertexOffset;
	this->previousRegion = previousRegion;
	xmove=0;
	ymove=0;
}

ClipmapRegion::ClipmapRegion(Vector3ix upperLeftQuad,Vector3ix lowerRightQuad, 
					Vector3ix innerUpperLeftQuad, Vector3ix innerLowerRightQuad)
{
	this->upperLeftQuad = upperLeftQuad;
	this->lowerRightQuad = lowerRightQuad;
	this->innerUpperLeftQuad = innerUpperLeftQuad;
	this->innerLowerRightQuad = innerLowerRightQuad;
//	initializeVertices();
	xmove=0;
	ymove=0;
	changed = true;
}

ClipmapRegion::~ClipmapRegion()
{}

/**
 * Adds a collumn or row to the region. May overwrite a previous written one
 * on the other side of the region
 */
void ClipmapRegion::addExteriorRows(int amount, int direction){
//	std::cout << "Adding " << amount << " exterior rows in direction " << direction << std::endl;
//	std::cout << "startOffset was " << startOffset << " endOffset was " << endOffset << std::endl;
//	std::cout << "outerWidth was " << outerWidth << std::endl;
	int i;
	if (amount > 0){
		switch (direction) {
			case LEFT : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(upperLeftQuad.getLeft())==NULL) {
						if (isTooBigOnRight()) {
							lowerRightQuad = lowerRightQuad.getLeft();
							endOffset=(endOffset+REGIONSURF-(REGIONSIZE+1))%REGIONSURF;
						}
					} else {
						if (isTooSmallOnLeft()){
							//+REGIONSURF is just to be shure it takes the positive modulo
							startOffset=(startOffset-(REGIONSIZE+1)+REGIONSURF)%REGIONSURF;
							addCollumn(startOffset,upperLeftQuad.x-1,upperLeftQuad.y);
							upperLeftQuad = upperLeftQuad.getLeft();
							if (isTooBigOnRight()) {
								lowerRightQuad = lowerRightQuad.getLeft();
								endOffset=(endOffset+REGIONSURF-(REGIONSIZE+1))%REGIONSURF;
							}
						} else {
							std::cout << "WARNING : trying to move out of center ulx " << upperLeftQuad.x << " centerx " << centerx << std::endl;
						}
					}
				}
				break;
			case RIGHT : 
				for (i=0;i<amount;i++){
//					std::cout << "Adding to right" << std::endl;
					if (quadIndex->getQuad(lowerRightQuad.getRight())==NULL) {
						if (isTooBigOnLeft()) {
							upperLeftQuad = upperLeftQuad.getRight();
							startOffset=(startOffset+(REGIONSIZE+1))%REGIONSURF;
						}
					} else {					
						if (isTooSmallOnRight()){
							endOffset=(endOffset+(REGIONSIZE+1))%REGIONSURF;
							addCollumn((endOffset-(lowerRightQuad.y-upperLeftQuad.y+1)+REGIONSURF)%REGIONSURF,lowerRightQuad.x+2,upperLeftQuad.y);
							lowerRightQuad = lowerRightQuad.getRight();
		//					std::cout << "Checking new size" << std::endl;
							if (isTooBigOnLeft()) {
								upperLeftQuad = upperLeftQuad.getRight();
								startOffset=(startOffset+(REGIONSIZE+1))%REGIONSURF;
							}
						} else {
							std::cout << "WARNING : trying to move out of center lrx " << lowerRightQuad.x << " centerx " << centerx << std::endl;
						}
					}
				}
				break;
			case UP : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(upperLeftQuad.getTop())==NULL) {
						if (isTooBigOnDown()) {
							lowerRightQuad = lowerRightQuad.getTop();
							endOffset=(endOffset+REGIONSURF-1)%REGIONSURF;
						}
					} else {					
						if (isTooSmallOnUp()){
							startOffset=(startOffset+REGIONSURF-1)%REGIONSURF;
							addRow(startOffset,upperLeftQuad.x,upperLeftQuad.y-1);
							upperLeftQuad = upperLeftQuad.getTop();
							if (isTooBigOnDown()) {
								lowerRightQuad = lowerRightQuad.getTop();
								endOffset=(endOffset+REGIONSURF-1)%REGIONSURF;
							}
						} else {
							std::cout << "WARNING : trying to move out of center uly " << upperLeftQuad.y << " centerz " << centerz << std::endl;
						}
					}
				}
				break;
			case DOWN : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(lowerRightQuad.getBottom())==NULL) {
						if (isTooBigOnUp()) {
							upperLeftQuad = upperLeftQuad.getBottom();
							startOffset=(startOffset+1)%REGIONSURF;
						}
					} else {					
						if (isTooSmallOnDown()){
							endOffset=(endOffset+1)%REGIONSURF;
							addRow((endOffset-(REGIONSIZE+1)*(lowerRightQuad.x-upperLeftQuad.x+1)+REGIONSURF)%REGIONSURF,upperLeftQuad.x,lowerRightQuad.y+2);
							lowerRightQuad = lowerRightQuad.getBottom();
							if (isTooBigOnUp()) {
								upperLeftQuad = upperLeftQuad.getBottom();
								startOffset=(startOffset+1)%REGIONSURF;
							}
						} else {
							std::cout << "WARNING : trying to move out of center lry " << lowerRightQuad.y << " centerz " << centerz << std::endl;
						}
					}
				}
				break;
		}
		changed = true;
	} else if (amount < 0) {
		removeExteriorRows(-amount,direction);
	} 
//	std::cout << "Done adding" << std::endl;
}

/**
 * Adds a collumn of vertices to the vertexBuffer
 */
void ClipmapRegion::addCollumn(int offset,int startx,int starty){	
//	std::cout << "Adding collumn... at offset " << offset << std::endl;
	int vertexSize=3;
#if USE_NORMALS
	vertexSize+=3;
#endif
	// The number of of quads to be added
	int number = lowerRightQuad.y - upperLeftQuad.y+2;
	int i, pos;
	for (i=0; i<number;i++){
//		std::cout << "Adding vertex " << i << " " << startx << "," << starty+i;
		Vector3 vertex = quadIndex->getVertex(startx,starty+i,upperLeftQuad.z);
#if USE_NORMALS
		Vector3 normal = quadIndex->getNormal(startx,starty+i,upperLeftQuad.z);
#endif
		pos = ((i+offset)%REGIONSURF)*vertexSize;
//		std::cout << " pos " << pos << std::endl;
		vertices[pos] = vertex.x;
		vertices[pos+1] = vertex.y;
		vertices[pos+2] = vertex.z;
#if USE_NORMALS
		vertices[pos+3] = normal.x;
		vertices[pos+4] = normal.y;
		vertices[pos+5] = normal.z;
#endif
//		std::cout << "Adding vertex " << vertex.x << ", "<< vertex.y << ", "<< vertex.z << " at " << pos << std::endl;
	}
	changed = true;
}
/*
void ClipmapRegion::updateTransition(int amount, int direction){
	int i,j;
	Real* vertices = (Real*)vertexBuffer->lock(vertexOffset*VERTEXSIZE*sizeof(Real),REGIONSURF*VERTEXSIZE*sizeof(Real),HardwareBuffer::HBL_NO_OVERWRITE);
	for (i=0;i<=getWidth();i++){
		for (j=0;j<=getHeight();j++){
			Real alphax = calculateAlphaX(i);
			Real alphay = calculateAlphaY(j);
			Real alpha = max(alphax,alphay);
			int pos = getVertexPosition(i,j)-vertexOffset;
			setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
		}
	}
	vertexBuffer->unlock();
}
*/
/**
 * Updates the vertices in the transition zone.
 */
void ClipmapRegion::updateTransition(int amount, int direction){
//	std::cout << "Updating transition of level " << upperLeftQuad.z << ", amount " << amount << " direction " << direction << std::endl;
//	std::cout << "getHeight() " << getHeight() << " getWidth() " << getWidth() << std::endl;
	if (amount>0){
	int i,j;
	Real* vertices = (Real*)vertexBuffer->lock(vertexOffset*VERTEXSIZE*sizeof(Real),REGIONSURF*VERTEXSIZE*sizeof(Real),HardwareBuffer::HBL_NO_OVERWRITE);
	int pos;
	switch (direction) {
		case LEFT : 
		case RIGHT : 
			// Commit the unblended vertices			
			if (isCompleteInLeft()){
//				std::cout << "Committing left" << std::endl;
				for (i=TRANSITIONSIZE(getWidth());i<TRANSITIONSIZE(getWidth())+amount;i++){
					Real alphax = calculateAlphaX(i);
					for (j=0;j<TRANSITIONSIZE(getHeight());j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						Real alpha = max(alphax, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=TRANSITIONSIZE(getHeight());j<getHeight()-TRANSITIONSIZE(getHeight())+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
/*	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
*/					}				
					for (j=getHeight()-TRANSITIONSIZE(getHeight())+1;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						Real alpha = max(alphax, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
//				std::cout << "Updating left" << std::endl;
				// Update the blended vertices
				for (i=0;i<TRANSITIONSIZE(getWidth());i++){
					Real alpha = calculateAlphaX(i);
					for (j=0;j<TRANSITIONSIZE(getHeight());j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						alpha = max(alpha, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=TRANSITIONSIZE(getHeight());j<getHeight()-TRANSITIONSIZE(getHeight())+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaY(j);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=getHeight()-TRANSITIONSIZE(getHeight())+1;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						alpha = max(alpha, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
			} else {
//				std::cout << "Not complete in left " << upperLeftQuad.z << std::endl;
				for (i=0;i<min(amount,getWidth()+1);i++){
					for (j=0;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}
				}
			}
			if (isCompleteInRight()){
				// Commit the unblended vertices
//				std::cout << "Committing right" << std::endl;
				for (i=max(getWidth()-amount-TRANSITIONSIZE(getWidth()),0);i<getWidth()-TRANSITIONSIZE(getWidth())+1;i++){
//						commitVertex(pos, vertices);
					Real alphax = calculateAlphaX(i);
					for (j=0;j<TRANSITIONSIZE(getHeight());j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						Real alpha = max(alphax, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=TRANSITIONSIZE(getHeight());j<getHeight()-TRANSITIONSIZE(getHeight())+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
//						Real alpha = calculateAlphaY(j);
						commitVertex(pos, vertices);
//	#if USE_NORMALS					
//						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
//	#else
//						setVertex(pos,blendVertex(i,j, alpha), vertices);
//	#endif
					}				
					for (j=getHeight()-TRANSITIONSIZE(getHeight())+1;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						Real alpha = max(alphax, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
				// Update the blended vertices
//				std::cout << "Updating right" << std::endl;
				for (i=getWidth()-TRANSITIONSIZE(getWidth())+1;i<getWidth()+1;i++){
					Real alpha = calculateAlphaX(i);
					for (j=0;j<TRANSITIONSIZE(getHeight());j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						alpha = max(alpha, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=TRANSITIONSIZE(getHeight());j<getHeight()-TRANSITIONSIZE(getHeight())+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaY(j);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (j=getHeight()-TRANSITIONSIZE(getHeight())+1;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphay = calculateAlphaY(j);
						alpha = max(alpha, alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
			} else {
//				std::cout << "Not complete in right " << upperLeftQuad.z << std::endl;
				for (i=getWidth()-min(amount,getWidth()+1);i<getWidth()+1;i++){
					for (j=0;j<getHeight()+1;j++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}
				}
			}
			break;
		case DOWN : 
		case UP : 
			if (isCompleteInDown()){
				// Commit the unblended vertices
//				std::cout << "Committing down" << std::endl;
				for (j=max(getHeight()-amount-TRANSITIONSIZE(getHeight()),0);j<getHeight()-TRANSITIONSIZE(getHeight())+1;j++){
					Real alphay = calculateAlphaY(j);
					for (i=0;i<TRANSITIONSIZE(getWidth());i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphax = calculateAlphaX(i);
						Real alpha = max(alphax,alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=TRANSITIONSIZE(getWidth());i<getWidth()-TRANSITIONSIZE(getWidth())+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}				
					for (i=getWidth()-TRANSITIONSIZE(getWidth())+1;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphax = calculateAlphaX(i);
						Real alpha = max(alphax,alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
				// Update the blended vertices
//				std::cout << "Updating down" << std::endl;
				for (j=getHeight()-TRANSITIONSIZE(getHeight())+1;j<getHeight()+1;j++){
					Real alpha = calculateAlphaY(j);
					for (i=0;i<TRANSITIONSIZE(getWidth());i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=TRANSITIONSIZE(getWidth());i<getWidth()-TRANSITIONSIZE(getWidth())+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=getWidth()-TRANSITIONSIZE(getWidth())+1;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
			} else {
//				std::cout << "Not complete in down " << upperLeftQuad.z << std::endl;
				for (j=getHeight()-amount;j<getHeight()+1;j++){
					for (i=0;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}
				}
			}
			if (isCompleteInUp()){
				// Commit the unblended vertices
//				std::cout << "Committing up" << std::endl;
				for (j=TRANSITIONSIZE(getHeight());j<min(TRANSITIONSIZE(getHeight())+amount,getHeight());j++){
					Real alphay = calculateAlphaY(j);
					for (i=0;i<TRANSITIONSIZE(getWidth());i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphax = calculateAlphaX(i);
						Real alpha = max(alphax,alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=TRANSITIONSIZE(getWidth());i<getWidth()-TRANSITIONSIZE(getWidth())+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}				
					for (i=getWidth()-TRANSITIONSIZE(getWidth())+1;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphax = calculateAlphaX(i);
						Real alpha = max(alphax,alphay);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
				// Update the blended vertices
//				std::cout << "Updating up" << std::endl;
				for (j=0;j<TRANSITIONSIZE(getHeight());j++){
					Real alpha = calculateAlphaY(j);
					for (i=0;i<TRANSITIONSIZE(getWidth());i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=TRANSITIONSIZE(getWidth());i<getWidth()-TRANSITIONSIZE(getWidth())+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
					for (i=getWidth()-TRANSITIONSIZE(getWidth())+1;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						Real alphab = calculateAlphaX(i);
						alpha = max(alpha, alphab);
	#if USE_NORMALS					
						setVertex(pos,blendVertex(i,j, alpha), blendNormal(i,j, alpha), vertices);
	#else
						setVertex(pos,blendVertex(i,j, alpha), vertices);
	#endif
					}				
				}
			} else {
//				std::cout << "Not complete in up " << upperLeftQuad.z << std::endl;
				for (j=0;j<min(amount,getHeight()+1);j++){
					for (i=0;i<getWidth()+1;i++){
						pos = getVertexPosition(i,j)-vertexOffset;
						commitVertex(pos, vertices);
					}
				}
			}
			break;
	}
	vertexBuffer->unlock();
	}
}

/**
 * Updates the vertices in the transition zone without blending.
 */
void ClipmapRegion::updatePlain(int amount, int direction){
	int i,j;
	Real* vertices = (Real*)vertexBuffer->lock(vertexOffset*VERTEXSIZE*sizeof(Real),REGIONSURF*VERTEXSIZE*sizeof(Real),HardwareBuffer::HBL_NO_OVERWRITE);
	int pos;
	switch (direction) {
		case LEFT : 
		case RIGHT : 
			// Commit the unblended vertices
			for (i=0;i<amount;i++){
				for (j=0;j<getHeight();j++){
					pos = getVertexPosition(i,j)-vertexOffset;
					commitVertex(pos, vertices);
				}
			}
			// Commit the unblended vertices
			for (i=getWidth()-amount;i<getWidth();i++){
				for (j=0;j<getHeight();j++){
					pos = getVertexPosition(i,j)-vertexOffset;
					commitVertex(pos, vertices);
				}
			}
		case UP : 
		case DOWN : 
			// Commit the unblended vertices
			for (j=getHeight()-amount;j<getHeight();j++){
				for (i=0;i<getWidth();i++){
					pos = getVertexPosition(i,j)-vertexOffset;
					commitVertex(pos, vertices);
				}
			}
			// Commit the unblended vertices
			for (j=0;j<amount;j++){
				for (i=0;i<getWidth();i++){
					pos = getVertexPosition(i,j)-vertexOffset;
					commitVertex(pos, vertices);
				}
			}
	}
	vertexBuffer->unlock();
}


inline Real ClipmapRegion::calculateAlphaX(int pos){
//	std::cout << "Calculatign alpha " << pos << " centerx " << centerx << std::endl;
#if TRANSITION
	if (centerx<pos) pos+=1;
	Real res = min(max((abs(pos-centerx)-(REGIONSIZE/2-TRANSITION-1))/(double)TRANSITION,(double)0),(double)1);
#else
	Real res = 0;
#endif
//	std::cout << "alphax = " << res << std::endl;
	return res;
}
inline Real ClipmapRegion::calculateAlphaY(int pos){
//	std::cout << "Calculatign alpha " << pos << " centerz " << centerz << std::endl;
#if TRANSITION
	if (centerz<pos) pos+=1;
	Real res = min(max((abs(pos-centerz)-(REGIONSIZE/2-TRANSITION-1))/(double)TRANSITION,(double)0),(double)1);
#else
	Real res = 0;
#endif
//	std::cout << "alphay = " << res << std::endl;
	return res;
}

/**
 * Sets the 
 */
inline void ClipmapRegion::setVertex(int pos, Vector3 vertex, Real* vertices){
	int i;
	pos*=VERTEXSIZE;
	for (i=0;i<3;i++){
		vertices[pos+i]=vertex[i];
	}
#if USE_NORMALS
	for (i=0;i<3;i++){		 
		vertices[pos+3+i]=this->vertices[pos+3+i];
	}
#endif	
}

inline void ClipmapRegion::setVertex(int pos, Vector3 vertex, Vector3 normal, Real* vertices){
	int i;
	pos*=VERTEXSIZE;
	for (i=0;i<3;i++){
		vertices[pos+i]=vertex[i];
	}
#if USE_NORMALS
	for (i=0;i<3;i++){		 
		vertices[pos+3+i]=normal[i];
	}
#endif	
}

/**
 * Uses the coordinates in the Local vertexBuffer for the value in the 
 * HW-vertexBuffer
 */
inline void ClipmapRegion::commitVertex(int pos, Real* vertices){
//	std::cout << "Committing vertex at " << pos << std::endl;
	int i;
	pos*=VERTEXSIZE;
	for (i=0;i<VERTEXSIZE;i++){
		vertices[pos+i]=this->vertices[pos+i];
	}
}

/**
 * Blends a vertex with a given amount into the next level
 */
Vector3 ClipmapRegion::blendVertex(int x, int y, Real alpha){
//	std::cout << "Blending vertex " << x << "," << y << " with alpha " << alpha << std::endl;
//		std::cout << "upperLeftQuad.x " << upperLeftQuad.x << " upperLeftQuad.y " << upperLeftQuad.y << std::endl;
//		std::cout << "lowerRightQuad.x " << lowerRightQuad.x << " lowerRightQuad.y " << lowerRightQuad.y << std::endl;
//		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
//	std::cout << "upperLeftQuad.x " << upperLeftQuad.x << " upperLeftQuad.y " << upperLeftQuad.y  << "upperLeftQuad.z " << upperLeftQuad.z << std::endl;
	Vector3i rcoords = getVertexCoordinates(x,y);	
//	std::cout << "Got coordinates " << rcoords.x << "," << rcoords.y << std::endl;
	Vector3 coordinates = previousRegion->getRelativeCoordinates(rcoords.x>>1,rcoords.y>>1);	
//	std::cout << "Got previous coordinates " << coordinates.x << "," << coordinates.y << std::endl;
	int pos0 = getVertexPosition(x,y)-vertexOffset;
//	std::cout << "Got vertexPosition0 " << pos0 << std::endl;
	Vector3 val1 = Vector3(vertices[pos0*VERTEXSIZE],
				vertices[pos0*VERTEXSIZE+1],
				vertices[pos0*VERTEXSIZE+2]);
//	Vector3i coordinates = previousRegion->getVertexCoordinates(x,y);
	if ((x%2==0)&&(y%2==0)){
		int pos = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos*=VERTEXSIZE;
//		std::cout << "Got vertexPosition1 " << pos << std::endl;
		Vector3 val2 = Vector3(previousRegion->vertices[pos],
			previousRegion->vertices[pos+1],
			previousRegion->vertices[pos+2]);
		return (1-alpha)*val1+alpha*val2;
	} else if ((x%2==1)&&(y%2==0)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1*=VERTEXSIZE;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y)-previousRegion->vertexOffset;
		pos2*=VERTEXSIZE;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		return (1-alpha)*val1+alpha*(val21+val22)/2.0;
	} else if ((x%2==0)&&(y%2==1)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1*=VERTEXSIZE;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos2*=VERTEXSIZE;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		return (1-alpha)*val1+alpha*(val21+val22)/2.0;
	} else if ((x%2==1)&&(y%2==1)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1*=VERTEXSIZE;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos2*=VERTEXSIZE;
		int pos3 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y)-previousRegion->vertexOffset;
		pos3*=VERTEXSIZE;
		int pos4 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos4*=VERTEXSIZE;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
//		std::cout << "Got vertexPosition3 " << pos3 << std::endl;
//		std::cout << "Got vertexPosition4 " << pos4 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		Vector3 val23 = Vector3(previousRegion->vertices[pos3],
			previousRegion->vertices[pos3+1],
			previousRegion->vertices[pos3+2]);
		Vector3 val24 = Vector3(previousRegion->vertices[pos4],
			previousRegion->vertices[pos4+1],
			previousRegion->vertices[pos4+2]);
		return (1-alpha)*val1+alpha*(val21+val22+val23+val24)/4.0;
	}
}

/**
 * Blends a vertex with a given amount into the next level
 */
Vector3 ClipmapRegion::blendNormal(int x, int y, Real alpha){
	return Vector3(0,1,0);
//	std::cout << "Blending normal " << x << "," << y << " with alpha " << alpha << std::endl;
	Vector3i rcoords = getVertexCoordinates(x,y);	
//	std::cout << "Got coordinates " << rcoords.x << "," << rcoords.y << std::endl;
	Vector3 coordinates = previousRegion->getRelativeCoordinates(rcoords.x>>1,rcoords.y>>1);	
//	std::cout << "Got previous coordinates " << coordinates.x << "," << coordinates.y << std::endl;
	int pos0 = (getVertexPosition(x,y)-vertexOffset)*VERTEXSIZE+3;
//	std::cout << "Got vertexPosition0 " << pos0 << std::endl;
	Vector3 val1 = Vector3(vertices[pos0],
				vertices[pos0+1],
				vertices[pos0+2]);
//	std::cout << "Got val1" << std::endl;
	if ((x%2==0)&&(y%2==0)){
//		std::cout << "previousRegion " << previousRegion << std::endl;
		int pos = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos=pos*VERTEXSIZE+3;
//		std::cout << "Got vertexPosition1 " << pos << std::endl;
		Vector3 val2 = Vector3(previousRegion->vertices[pos],
			previousRegion->vertices[pos+1],
			previousRegion->vertices[pos+2]);
//		std::cout << "Got val2" << std::endl;
		Vector3 res = ((1-alpha)*val1+alpha*val2);
		res.normalise();
		return res;
	} else if ((x%2==1)&&(y%2==0)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1=pos1*VERTEXSIZE+3;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y)-previousRegion->vertexOffset;
		pos2=pos2*VERTEXSIZE+3;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		Vector3 val2 = (val21+val22)/2.0;
//		val2.normalise();
		Vector3 res = ((1-alpha)*val1+alpha*val2);
//		res.normalise();
		return res;
	} else if ((x%2==0)&&(y%2==1)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1=pos1*VERTEXSIZE+3;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos2=pos2*VERTEXSIZE+3;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		Vector3 val2 = (val21+val22)/2.0;
//		val2.normalise();
		Vector3 res = ((1-alpha)*val1+alpha*val2);
//		res.normalise();
		return res;
	} else if ((x%2==1)&&(y%2==1)){
		int pos1 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y)-previousRegion->vertexOffset;
		pos1=pos1*VERTEXSIZE+3;
		int pos2 = previousRegion->getVertexPosition((int)coordinates.x, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos2=pos2*VERTEXSIZE+3;
		int pos3 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y)-previousRegion->vertexOffset;
		pos3=pos3*VERTEXSIZE+3;
		int pos4 = previousRegion->getVertexPosition((int)coordinates.x+1, (int)coordinates.y+1)-previousRegion->vertexOffset;
		pos4=pos4*VERTEXSIZE+3;
//		std::cout << "Got vertexPosition1 " << pos1 << std::endl;
//		std::cout << "Got vertexPosition2 " << pos2 << std::endl;
//		std::cout << "Got vertexPosition3 " << pos3 << std::endl;
//		std::cout << "Got vertexPosition4 " << pos4 << std::endl;
		Vector3 val21 = Vector3(previousRegion->vertices[pos1],
			previousRegion->vertices[pos1+1],
			previousRegion->vertices[pos1+2]);
		Vector3 val22 = Vector3(previousRegion->vertices[pos2],
			previousRegion->vertices[pos2+1],
			previousRegion->vertices[pos2+2]);
		Vector3 val23 = Vector3(previousRegion->vertices[pos3],
			previousRegion->vertices[pos3+1],
			previousRegion->vertices[pos3+2]);
		Vector3 val24 = Vector3(previousRegion->vertices[pos4],
			previousRegion->vertices[pos4+1],
			previousRegion->vertices[pos4+2]);
		Vector3 val2 = (val21+val22+val23+val24)/4.0;
//		val2.normalise();
		Vector3 res = ((1-alpha)*val1+alpha*val2);
//		res.normalise();
		return res;
	}
}


/**
 * Adds a row of vertices to the vertexBuffer
 */
void ClipmapRegion::addRow(int offset,int startx,int starty){	
	int vertexSize=3;
#if USE_NORMALS
	vertexSize+=3;
#endif
	// The number of of quads to be added
	int number = lowerRightQuad.x - upperLeftQuad.x+2;
	int i, pos;
	for (i=0; i<number;i++){
//		std::cout << "Adding vertex " << i << " " << startx << "," << starty+i;
		Vector3 vertex = quadIndex->getVertex(startx+i,starty,upperLeftQuad.z);
#if USE_NORMALS
		Vector3 normal = quadIndex->getNormal(startx+i,starty,upperLeftQuad.z);
#endif
		pos = ((i*(REGIONSIZE+1)+offset)%REGIONSURF)*vertexSize;
//		std::cout << " pos " << pos << std::endl;
		vertices[pos] = vertex.x;
		vertices[pos+1] = vertex.y;
		vertices[pos+2] = vertex.z;
#if USE_NORMALS
		vertices[pos+3] = normal.x;
		vertices[pos+4] = normal.y;
		vertices[pos+5] = normal.z;
#endif
//		std::cout << "Adding vertex " << vertex.x << ", "<< vertex.y << ", "<< vertex.z << " at " << pos << std::endl;
	}
	changed = true;
}
/**
 * adds a row to the inner side of the region. (shrinks the hole)
 */
void ClipmapRegion::addInteriorRows(int amount, int direction){
	int i;
	if (amount > 0){
		switch (direction) {
			case LEFT : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(innerUpperLeftQuad.getRight())==NULL) {
						ulex=-1;
						break;
					}
					innerUpperLeftQuad = innerUpperLeftQuad.getRight();
				}
				break;
			case RIGHT : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(innerLowerRightQuad.getLeft())==NULL) {
						lrex=-1;
						break;
					}
					innerLowerRightQuad = innerLowerRightQuad.getLeft();
				}
				break;
			case UP : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(innerUpperLeftQuad.getBottom())==NULL) {
						ulez=-1;
						break;
					}
					innerUpperLeftQuad = innerUpperLeftQuad.getBottom();
				}
				break;
			case DOWN : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(innerLowerRightQuad.getTop())==NULL) {
						lrez=-1;
						break;
					}
					innerLowerRightQuad = innerLowerRightQuad.getTop();
				}
				break;
		}
		changed = true;
	} else if (amount < 0) {
		removeInteriorRows(-amount,direction);
	} 
//	std::cout << "innerHeight changed to " << innerHeight << std::endl;
//	std::cout << "innerWidth changed to " << innerWidth << std::endl;
}

/**
 * Removes a row/collumn from the region
 */
void ClipmapRegion::removeExteriorRows(int amount, int direction){
//	std::cout << "Removing " << amount << " rows in direction " << direction << std::endl;
	int i;
	if (amount > 0){
		switch (direction) {
			case LEFT : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(upperLeftQuad.getRight())==NULL) {
						break;
					}
					upperLeftQuad = upperLeftQuad.getRight();
					startOffset=(startOffset+(REGIONSIZE+1))%REGIONSURF;
					if (lowerRightQuad.x-upperLeftQuad.x < 0) {
						lowerRightQuad = lowerRightQuad.getRight();
						endOffset=(endOffset-(REGIONSIZE+1))%REGIONSURF;
					}
				}
				break;
			case RIGHT : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(lowerRightQuad.getLeft())==NULL) {
						break;
					}
					lowerRightQuad = lowerRightQuad.getLeft();
					endOffset=(endOffset-(REGIONSIZE+1)+REGIONSURF)%REGIONSURF;
					if (lowerRightQuad.x-upperLeftQuad.x < 0) {
						upperLeftQuad = upperLeftQuad.getLeft();
						startOffset=(startOffset-(REGIONSIZE+1)+REGIONSURF)%REGIONSURF;
					}
				}
				break;
			case UP : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(upperLeftQuad.getBottom())==NULL) {
						break;
					}
					upperLeftQuad = upperLeftQuad.getBottom();
					startOffset=(startOffset+1)%REGIONSURF;
					if (lowerRightQuad.x-upperLeftQuad.x < 0) {
						lowerRightQuad = lowerRightQuad.getBottom();
						endOffset=(endOffset+1)%REGIONSURF;
					}
				}
				break;
			case DOWN : 
				for (i=0;i<amount;i++){
					if (quadIndex->getQuad(lowerRightQuad.getTop())==NULL) {
						break;
					}
					lowerRightQuad = lowerRightQuad.getTop();
					endOffset=(endOffset-1+REGIONSURF)%REGIONSURF;
					if (lowerRightQuad.x-upperLeftQuad.x < 0) {
						upperLeftQuad = upperLeftQuad.getTop();
						startOffset=(startOffset-1+REGIONSURF)%REGIONSURF;
					}
				}
				break;
		}
		changed = true;
	} else if (amount < 0) {
		addExteriorRows(-amount,direction);
	} 
}
void ClipmapRegion::removeInteriorRows(int amount, int direction){
	int i;
	if (amount > 0){
		switch (direction) {
			case LEFT : 
				for (i=0;i<amount;i++){
//					std::cout << "Adding " << i+1 << " of " << amount << " to left" << std::endl;
					if (quadIndex->getQuad(innerUpperLeftQuad.getLeft())==NULL) {
						ulex=1;
						break;
					}
					innerUpperLeftQuad = innerUpperLeftQuad.getLeft();					
				}
				break;
			case RIGHT : 
				for (i=0;i<amount;i++){
//					std::cout << "Adding " << i+1 << " of " << amount << " to right" << std::endl;
					if (quadIndex->getQuad(innerLowerRightQuad.getRight())==NULL) {
						lrex=1;
						break;
					}
					innerLowerRightQuad = innerLowerRightQuad.getRight();
				}
				break;
			case UP : 
				for (i=0;i<amount;i++){
//					std::cout << "Adding " << i+1 << " of " << amount << " to up" << std::endl;
					if (quadIndex->getQuad(innerUpperLeftQuad.getTop())==NULL) {
						ulez=1;
						break;
					}
					innerUpperLeftQuad = innerUpperLeftQuad.getTop();
				}
				break;
			case DOWN : 
				for (i=0;i<amount;i++){
//					std::cout << "Adding " << i+1 << " of " << amount << " to down" << std::endl;
					if (quadIndex->getQuad(innerLowerRightQuad.getBottom())==NULL) {
						lrez=1;
						break;
					}
					innerLowerRightQuad = innerLowerRightQuad.getBottom();
				}
				break;
		}
		changed = true;
	} else if (amount < 0) {
		addInteriorRows(-amount,direction);
	} 
}

/**
 * Moves the region an amount of quads to the given direction
 * @param	amount
 * 			| The amount of quads to be moved
 * @param	direction
 * 			| The direction to move to (N,E,S,W)
 * @post	The <amount> rows will be added in the given direction
 * 				the rows that are too much will be overwritten on the other side
 * 			If <amount> is negative, the rows will be added to the opposide side
 * 				of <direction>
 * 			this->centerx and this->centerz will be moved with the given amount
 * 				and direction
 */
void ClipmapRegion::move(int amount, int direction){
	if (amount!=0){
//	std::cout << "Moving " << amount << " in direction " << direction << std::endl;
		if (amount<0) {				
			move(-amount, (direction+2)%4);
		} else {
			int temp1x = upperLeftQuad.x;
			int temp2x = lowerRightQuad.x;
			int temp1y = upperLeftQuad.y;
			int temp2y = lowerRightQuad.y;
	//		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
			switch (direction) {
				case N:
					centerz-=amount;
					ymove=-amount;
					break;
				case E:
					centerx+=amount;
					xmove=amount;
					break;
				case S:
					centerz+=amount;
					ymove=amount;
					break;
				case W:
					centerx-=amount;
					xmove=-amount;
					break;
			}
	//		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
			//TODO Als <amount> groter is als REGIONSIZE wordt de patch beter opnieuw ge?nitialiseerd
			addExteriorRows(amount, direction);
			int amountleft, moveleft;
/*			switch (direction) {
				case N:
					moveleft = amount - (temp1y - upperLeftQuad.y);
					amountleft = (lowerRightQuad.y-centerz)-getPreferredHeight()/2-1;
					if (amountleft > moveleft) amountleft = moveleft;
					
					if (amountleft > 0){
						removeExteriorRows(amountleft,(direction+2)%4);
					}
					break;
				case E:
					moveleft = amount - (lowerRightQuad.x - temp2x);
					amountleft = (centerx-upperLeftQuad.x)-getPreferredWidth()/2;
					if (amountleft > moveleft) amountleft = moveleft;
					if (amountleft > 0){
						removeExteriorRows(amountleft,(direction+2)%4);
					}
					break;
				case S:
					moveleft = amount - (lowerRightQuad.y - temp2y);
					amountleft = (centerz-upperLeftQuad.y)-getPreferredHeight()/2;
					if (amountleft > moveleft) amountleft = moveleft;
					if (amountleft > 0){
						removeExteriorRows(amountleft,(direction+2)%4);
					}
					break;
				case W:
					moveleft = amount - (temp1x - upperLeftQuad.x);
					amountleft = (lowerRightQuad.x-centerx)-getPreferredWidth()/2-1;
					if (amountleft > moveleft) amountleft = moveleft;
					if (amountleft > 0){
						removeExteriorRows(amountleft,(direction+2)%4);
					}
					break;
			}
*/		}
/*		if (previousRegion!=0){
			updateTransition(amount, direction);
		} else {
			updatePlain(amount,direction);
		}
*/		
	} else {
		switch (direction) {
			case N:
				ymove=-amount;
				break;
			case E:
				xmove=amount;
				break;
			case S:
				ymove=amount;
				break;
			case W:
				xmove=-amount;
				break;
		}
	}
//	std::cout << "Moving done" << std::endl;
}

void ClipmapRegion::updateVertices(){
	if (previousRegion!=0){
		updateTransition(xmove, E);
		updateTransition(ymove, S);
	} else {
		updatePlain(xmove,E);
		updatePlain(ymove,S);
	}
}

void ClipmapRegion::updateVertices(int amount, int direction){
	if (amount < 0){
		updateVertices(-amount, (direction+2)%4);
	} else {
		if (previousRegion!=0){
			updateTransition(amount, direction);
		} else {
			updatePlain(amount, direction);
		}
	}
}
/**
 * Returns the level of the region
 */
int ClipmapRegion::getLevel() const {
	return upperLeftQuad.z;
}

/**
 * Returns the preferred width
 */
int ClipmapRegion::getPreferredWidth() const {
	if (quadIndex->getLevelSize(getLevel()) >= REGIONSIZE) {
		return REGIONSIZE;
	} else {
		return quadIndex->getLevelSize(getLevel());
	}
}

/**
 * Returns the preferred height
 */
int ClipmapRegion::getPreferredHeight() const {
	if (quadIndex->getLevelSize(getLevel()) >= REGIONSIZE) {
		return REGIONSIZE;
	} else {
		return quadIndex->getLevelSize(getLevel());
	}
}

/**
 * Returns the current width
 */
int ClipmapRegion::getWidth() const {
	return lowerRightQuad.x-upperLeftQuad.x+1;
}

/**
 * Returns the current height
 */
int ClipmapRegion::getHeight() const {
	return lowerRightQuad.y-upperLeftQuad.y+1;
}


/**
 * Moves the hole of the region
 */
void ClipmapRegion::moveHole(int amount, int direction){
//	std::cout << "Moving hole " << amount << " in direction " << direction << std::endl;
	if (amount<0) {				
		moveHole(-amount, (direction+2)%4);
	} else {
		if (hasHole()){
			switch (direction) {
				case N:
					if (holeIsCompleteInY()){
						addInteriorRows(amount,(direction+2)%4);				
					}
					break;
				case E:
					if (holeIsCompleteInX()){
						addInteriorRows(amount,(direction+2)%4);				
					}
					break;
				case S:
					if (holeIsCompleteInY()){
						addInteriorRows(amount,(direction+2)%4);				
					}
					break;
				case W:
					if (holeIsCompleteInX()){
						addInteriorRows(amount,(direction+2)%4);				
					}
					break;
			}
			removeInteriorRows(amount,direction);
		}
	}
}

/**
 * Returns if this region has a hole for the next level of detail
 */
bool ClipmapRegion::hasHole() const {
	return ((innerUpperLeftQuad.x <= innerLowerRightQuad.x) &&
			(innerUpperLeftQuad.y <= innerLowerRightQuad.y));
}

/**
 * Returns if the hole of this region is REGIONSIZE/2 on REGIONSIZE/2 big
 */
bool ClipmapRegion::holeIsComplete(){
	return (holeIsCompleteInX() &&
			holeIsCompleteInY());
}

bool ClipmapRegion::isCompleteInLeft(){
//	std::cout << "centerx " << centerx << " upperLeftQuad.x " << upperLeftQuad.x << " -> " << (centerx - upperLeftQuad.x == REGIONSIZE>>1) << std::endl;
	return (centerx - upperLeftQuad.x == REGIONSIZE>>1);
}
bool ClipmapRegion::isCompleteInRight(){
//	std::cout << "centerx " << centerx << " lowerRightQuad.x " << lowerRightQuad.x << " -> " << (lowerRightQuad.x - centerx + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.x - centerx + 1 == REGIONSIZE>>1);
}
bool ClipmapRegion::isCompleteInUp(){
//	std::cout << "centerz " << centerz << " upperLeftQuad.y " << upperLeftQuad.y << " -> " << (centerz - upperLeftQuad.y == REGIONSIZE>>1) << std::endl;
	return (centerz - upperLeftQuad.y == REGIONSIZE>>1);
}
bool ClipmapRegion::isCompleteInDown(){
//	std::cout << "centerz " << centerz << " lowerRightQuad.y " << lowerRightQuad.y << " -> " << (lowerRightQuad.y - centerz + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.y - centerz + 1 == REGIONSIZE>>1);
}

bool ClipmapRegion::isTooBigOnLeft(){
//	std::cout << "centerx " << centerx << " upperLeftQuad.x " << upperLeftQuad.x << " -> " << (centerx - upperLeftQuad.x == REGIONSIZE>>1) << std::endl;
	return (centerx - upperLeftQuad.x > REGIONSIZE>>1);
}
bool ClipmapRegion::isTooBigOnRight(){
//	std::cout << "centerx " << centerx << " lowerRightQuad.x " << lowerRightQuad.x << " -> " << (lowerRightQuad.x - centerx + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.x - centerx + 1 > REGIONSIZE>>1);
}
bool ClipmapRegion::isTooBigOnUp(){
//	std::cout << "centerz " << centerz << " upperLeftQuad.y " << upperLeftQuad.y << " -> " << (centerz - upperLeftQuad.y == REGIONSIZE>>1) << std::endl;
	return (centerz - upperLeftQuad.y > REGIONSIZE>>1);
}
bool ClipmapRegion::isTooBigOnDown(){
//	std::cout << "centerz " << centerz << " lowerRightQuad.y " << lowerRightQuad.y << " -> " << (lowerRightQuad.y - centerz + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.y - centerz + 1 > REGIONSIZE>>1);
}

bool ClipmapRegion::isTooSmallOnLeft(){
//	std::cout << "centerx " << centerx << " upperLeftQuad.x " << upperLeftQuad.x << " -> " << (centerx - upperLeftQuad.x == REGIONSIZE>>1) << std::endl;
	return (centerx - upperLeftQuad.x < REGIONSIZE>>1);
}
bool ClipmapRegion::isTooSmallOnRight(){
//	std::cout << "centerx " << centerx << " lowerRightQuad.x " << lowerRightQuad.x << " -> " << (lowerRightQuad.x - centerx + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.x - centerx + 1 < REGIONSIZE>>1);
}
bool ClipmapRegion::isTooSmallOnUp(){
//	std::cout << "centerz " << centerz << " upperLeftQuad.y " << upperLeftQuad.y << " -> " << (centerz - upperLeftQuad.y == REGIONSIZE>>1) << std::endl;
	return (centerz - upperLeftQuad.y < REGIONSIZE>>1);
}
bool ClipmapRegion::isTooSmallOnDown(){
//	std::cout << "centerz " << centerz << " lowerRightQuad.y " << lowerRightQuad.y << " -> " << (lowerRightQuad.y - centerz + 1 == REGIONSIZE>>1) << std::endl;
	return (lowerRightQuad.y - centerz + 1 < REGIONSIZE>>1);
}

/**
 * Returns if the hole of this region is REGIONSIZE/2 big in the x-direction
 */
bool ClipmapRegion::holeIsCompleteInX(){
	std::cout << (innerLowerRightQuad.x - innerUpperLeftQuad.x + 1 == REGIONSIZE>>1) << std::endl;
	return (innerLowerRightQuad.x - innerUpperLeftQuad.x + 1 == REGIONSIZE>>1);
}

/**
 * Returns if the hole of this region is REGIONSIZE/2 big in the y-direction
 */
bool ClipmapRegion::holeIsCompleteInY(){
	std::cout << (innerLowerRightQuad.y - innerUpperLeftQuad.y + 1 == REGIONSIZE>>1) << std::endl;
	return (innerLowerRightQuad.y - innerUpperLeftQuad.y + 1 == REGIONSIZE>>1);
}

void ClipmapRegion::makeZero(){
	vertexCount = 0;
	indexCount = 0;
	changed = false;
	//Obsolete
}

void ClipmapRegion::setQuadIndex(QuadIndex* quadIndex){
	this->quadIndex = quadIndex;
}


void ClipmapRegion::clearBuffers(){
	if (vertices!=NULL){		
		delete [] vertices;
	}
	if (indices!=NULL){
		delete [] indices;
	}
}



void ClipmapRegion::triangulate(){
	changed = false;
}

/**
 * Calculate the vertices
 * @pre	The space between the lowerRightQuad and the upperRightQuad must be
 * 		smaller then REGIONSIZE
 * 		else it will be truncated
 * 		(lowerRightQuad-upperLeftQuad).x <= REGIONSIZE
 * 		(lowerRightQuad-upperLeftQuad).y <= REGIONSIZE
 */
void ClipmapRegion::initializeVertices(){
//	std::cout << "Initializing vertices..." << std::endl;
	Vector3ix size = lowerRightQuad-upperLeftQuad;
	size.x+=1;
	size.y+=1;
	if (size.x > REGIONSIZE) {
		lowerRightQuad.x = upperLeftQuad.x + REGIONSIZE;
		size.x = REGIONSIZE;
	}
	if (size.y > REGIONSIZE) {
		lowerRightQuad.y = upperLeftQuad.y + REGIONSIZE;
		size.y = REGIONSIZE;
	}
	int i,j;
//	std::cout << "getting vertices, upperLeft is " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
//	Real* vertices = (Real*)vertexBuffer->lock(vertexOffset,REGIONSURF,HardwareBuffer::HBL_NO_OVERWRITE);
//	std::cout << "quadIndex " << quadIndex << std::endl;
	for (i=0;i<=size.x;i++){
		for (j=0;j<=size.y;j++){
			int vertexNb = i*(REGIONSIZE+1)+j;
//			std::cout << "i " << i << ", j " << j << ", z " << upperLeftQuad.z << std::endl;
			Vector3 vertex = quadIndex->getVertex(upperLeftQuad.x+i,upperLeftQuad.y+j,upperLeftQuad.z);
			Vector3 normal = quadIndex->getNormal(upperLeftQuad.x+i,upperLeftQuad.y+j,upperLeftQuad.z);
//			std::cout << vertex.x << "," << vertex.y << "," << vertex.z << std::endl;
//			std::cout << "got it!" << std::endl;			
//			vertices[vertexNb*3] = vertex.x;
//			vertices[vertexNb*3+1] = vertex.y;
//			vertices[vertexNb*3+2] = vertex.z;
			this->vertices[vertexNb*VERTEXSIZE] = vertex.x;
			this->vertices[vertexNb*VERTEXSIZE+1] = vertex.y;
			this->vertices[vertexNb*VERTEXSIZE+2] = vertex.z;
			this->vertices[vertexNb*VERTEXSIZE+3] = normal.x;
			this->vertices[vertexNb*VERTEXSIZE+4] = normal.y;
			this->vertices[vertexNb*VERTEXSIZE+5] = normal.z;
//			std::cout << "set it!" << std::endl;			
		}
	}
//	vertexBuffer->unlock();
	startOffset=0;
	int pos = (size.x*(REGIONSIZE+1)+size.y) % ((REGIONSIZE+1)*(REGIONSIZE+1));	
	endOffset=pos;
//	std::cout << "Initialized vertices" << std::endl;
}



void ClipmapRegion::calculateIndices(){
//	std::cout << "Calculating indices" << std::endl;
	//AAABBDD
	//AAABBDD
	//AAA  DD
	//AAACCDD
	//AAACCDD
#if USE_16BIT_INDICES
	unsigned short* index = indices;
#else
	unsigned int* index = indices;
#endif
//	std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
//	std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
//	std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
//	std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
	if ((innerUpperLeftQuad.x > innerLowerRightQuad.x)||(innerUpperLeftQuad.y > innerLowerRightQuad.y)) {
//		std::cout << "No hole" << std::endl;
		
		calculateAll(index);
	} else {
//		std::cout << "A hole" << std::endl;
		calculateA(index);
		calculateB(index);
		calculateC(index);
		calculateD(index);
		if (isCompleteInUp())	calculateN(index);
		if (isCompleteInRight())	calculateE(index);
		if (isCompleteInDown())	calculateS(index);
		if (isCompleteInLeft())	calculateW(index);
	}
	indexCount = index-indices;
	
	changed = false;
//	std::cout << "Calculating done" << std::endl;
}

	//		.---.
	//		|\ /|	<-this line should theoreticly be 0
	//		._._.
#if USE_16BIT_INDICES
void ClipmapRegion::calculateN(unsigned short* &index){
#else
void ClipmapRegion::calculateN(unsigned int* &index){
#endif
	int i;
	for (i=0;i<getWidth();i+=2){
		Vector3i coor = getVertexCoordinates(i,0);
		Vector3 prev = previousRegion->getRelativeCoordinates(coor.x>>1,coor.y>>1);
		*(index++) = getVertexPosition(i,0);
		*(index++) = getVertexPosition(i+1,0);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);

		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);
		*(index++) = getVertexPosition(i+1,0);
		*(index++) = previousRegion->getVertexPosition((int)prev.x+1,(int)prev.y);

		*(index++) = getVertexPosition(i+1,0);
		*(index++) = getVertexPosition(i+2,0);
		*(index++) = previousRegion->getVertexPosition((int)prev.x+1,(int)prev.y);
	}
}
#if USE_16BIT_INDICES
void ClipmapRegion::calculateE(unsigned short* &index){
#else
void ClipmapRegion::calculateE(unsigned int* &index){
#endif
	int i;
	for (i=0;i<getHeight();i+=2){
		Vector3i coor = getVertexCoordinates(getWidth(),i);
		Vector3 prev = previousRegion->getRelativeCoordinates(coor.x>>1,coor.y>>1);
		*(index++) = getVertexPosition(getWidth(),i);
		*(index++) = getVertexPosition(getWidth(),i+1);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);

		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);
		*(index++) = getVertexPosition(getWidth(),i+1);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y+1);

		*(index++) = getVertexPosition(getWidth(),i+1);
		*(index++) = getVertexPosition(getWidth(),i+2);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y+1);
	}
}
#if USE_16BIT_INDICES
void ClipmapRegion::calculateS(unsigned short* &index){
#else
void ClipmapRegion::calculateS(unsigned int* &index){
#endif
	int i;
	for (i=0;i<getWidth();i+=2){
		Vector3i coor = getVertexCoordinates(i,getHeight());
//		std::cout << "Coor = " << coor.x << "," << coor.y << std::endl;
		Vector3 prev = previousRegion->getRelativeCoordinates(coor.x>>1,coor.y>>1);
//		std::cout << "Prev = " << prev.x << "," << prev.y << std::endl;
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);
		*(index++) = getVertexPosition(i+1,getHeight());
		*(index++) = getVertexPosition(i,getHeight());

		*(index++) = previousRegion->getVertexPosition((int)prev.x+1,(int)prev.y);
		*(index++) = getVertexPosition(i+1,getHeight());
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);

		*(index++) = previousRegion->getVertexPosition((int)prev.x+1,(int)prev.y);
		*(index++) = getVertexPosition(i+2,getHeight());
		*(index++) = getVertexPosition(i+1,getHeight());
	}
}
#if USE_16BIT_INDICES
void ClipmapRegion::calculateW(unsigned short* &index){
#else
void ClipmapRegion::calculateW(unsigned int* &index){
#endif
	int i;
	for (i=0;i<getHeight();i+=2){
		Vector3i coor = getVertexCoordinates(0,i);
		Vector3 prev = previousRegion->getRelativeCoordinates(coor.x>>1,coor.y>>1);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);
		*(index++) = getVertexPosition(0,i+1);
		*(index++) = getVertexPosition(0,i);

		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y+1);
		*(index++) = getVertexPosition(0,i+1);
		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y);

		*(index++) = previousRegion->getVertexPosition((int)prev.x,(int)prev.y+1);
		*(index++) = getVertexPosition(0,i+2);
		*(index++) = getVertexPosition(0,i+1);
	}
}
/**
 * Returns the offset of the given vertex in the vertexBuffer.
 * @param	x and y are the coordinates relative to the bufer (0,0 is the 
 * 			upperleftmost vertex in the buffer
 * @pre	the x and y coordinates should be available
 * @post	returns the vertex position, or 0 if not existing
 */
int ClipmapRegion::getVertexPosition(int x, int y) const {
	if ((x > getWidth())||(y > getHeight())||(x < 0)||(y < 0)){
		std::cout << "WARNING : VertexPosition out of bounds! " << x << "," << y << " in level " << upperLeftQuad.z << std::endl;		
		std::cout << "upperLeftQuad.x " << upperLeftQuad.x << " upperLeftQuad.y " << upperLeftQuad.y << std::endl;
		std::cout << "lowerRightQuad.x " << lowerRightQuad.x << " lowerRightQuad.y " << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
	int pos = ((startOffset+x*(REGIONSIZE+1)+y) % (REGIONSURF));
//	std::cout << "x " << x << " y " << y  << " startOffset " << startOffset << " endOffset " << endOffset << " vertexOffset " << vertexOffset << " pos " << pos << std::endl;
	if ((pos > endOffset) && (pos < startOffset)) {
		std::cout << "ERROR : VertexPosition out of bounds! " << x << "," << y << " gives " << pos << ">" << endOffset << " && < " << startOffset << std::endl;
		return 0;
	}
	if ((pos > endOffset) && (pos > startOffset) && (startOffset < endOffset)) {
		std::cout << "ERROR : VertexPosition out of bounds! " << x << "," << y << " gives " << pos << ">" << endOffset << " && > " << startOffset << std::endl;
		return 0;
	}
	if ((pos < endOffset) && (pos < startOffset) && (startOffset < endOffset)) {
		std::cout << "ERROR : VertexPosition out of bounds! " << x << "," << y << " gives " << pos << "<" << endOffset << " && < " << startOffset << std::endl;
		return 0;
	}
	return pos+vertexOffset;
}

/**
 * Returns the "absolute" coordinates of the vertex in relative coordinates in
 * the region
 */
Vector3i ClipmapRegion::getVertexCoordinates(int x, int y) const {
	return Vector3i(upperLeftQuad.x+x,upperLeftQuad.y+y,upperLeftQuad.z);
}
 
/**
 * Returns the "relative" coordinates of the vertex in absolute coordinates in
 * the region
 */
Vector3 ClipmapRegion::getRelativeCoordinates(int x, int y) const {
//	std::cout << "x " << x << " upperLeftQuad.x " << upperLeftQuad.x << " y " << y << " upperLeftQuad.y " << upperLeftQuad.y << std::endl;
	return Vector3((x-upperLeftQuad.x),y-upperLeftQuad.y,0);
}

#define PRINTINDEX //std::cout << "Index : " << i << "," << j << " : " << index[-6]-vertexOffset << "," << index[-5]-vertexOffset << "," << index[-4]-vertexOffset << " " << index[-3]-vertexOffset << "," << index[-2]-vertexOffset << "," << index[-1]-vertexOffset << " startOffset = " << startOffset << std::endl;
#define PRINTVERTEX //std::cout << "Vertex : " << i << "," << j << " : " << vertices[(index[-6]-vertexOffset)*VERTEXSIZE] << "," << vertices[(index[-6]-vertexOffset)*VERTEXSIZE+1] << "," << vertices[(index[-6]-vertexOffset)*VERTEXSIZE+2] << " " << vertices[(index[-6]-vertexOffset)*VERTEXSIZE+3] << "," << vertices[(index[-6]-vertexOffset)*VERTEXSIZE+4] << "," << vertices[(index[-6]-vertexOffset)*VERTEXSIZE+5] << std::endl;

#if USE_16BIT_INDICES
void ClipmapRegion::calculateAll(unsigned short* &index){
#else
void ClipmapRegion::calculateAll(unsigned int* &index){
#endif
	int width = lowerRightQuad.x-upperLeftQuad.x+1;
	int height = lowerRightQuad.y-upperLeftQuad.y+1;
	int i,j;
	if ((width>=0)&&(height>=0)&&(width<=REGIONSIZE)&&(height<=REGIONSIZE)){
		for (int i=0;i<width;i++){
			for (int j=0;j<height;j++){
				//02
				//13
				if (upperLeftQuad.z % 2 == 0){
					*(index++) = getVertexPosition(i,j);		//0
					*(index++) = getVertexPosition(i,j+1);		//1
					*(index++) = getVertexPosition(i+1,j+1);	//3
		
					*(index++) = getVertexPosition(i+1,j+1);	//3
					*(index++) = getVertexPosition(i+1,j);		//2
					*(index++) = getVertexPosition(i,j);		//0
				} else {
					*(index++) = getVertexPosition(i,j);		//0
					*(index++) = getVertexPosition(i,j+1);		//1
					*(index++) = getVertexPosition(i+1,j);		//2
		
					*(index++) = getVertexPosition(i+1,j+1);	//3
					*(index++) = getVertexPosition(i+1,j);		//2
					*(index++) = getVertexPosition(i,j+1);		//1
				}
				PRINTINDEX
				PRINTVERTEX
			}
		}
	} else {
		std::cout << "ERROR : width = " << width << ", height = " << height << " level " << getLevel() << std::endl;
		std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
		std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
		std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
		std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
}


/**
 * Calculates the left part of the clipmap.
 * @pre	The pointer should point to the position of the first index of this
 * 		part to be written in the indexBuffer
 */
#if USE_16BIT_INDICES
void ClipmapRegion::calculateA(unsigned short* &index){
#else
void ClipmapRegion::calculateA(unsigned int* &index){
#endif
	int width = innerUpperLeftQuad.x-upperLeftQuad.x;
	int height = lowerRightQuad.y-upperLeftQuad.y+1;
	int i,j;
	if ((width>=0)&&(height>=0)&&(width<=REGIONSIZE)&&(height<=REGIONSIZE)){
		for (int i=0;i<width;i++){
			for (int j=0;j<height;j++){
				//02
				//13
				if (upperLeftQuad.z % 2 == 0){
					*(index++) = getVertexPosition(i,j);		//0
					*(index++) = getVertexPosition(i,j+1);		//1
					*(index++) = getVertexPosition(i+1,j+1);	//3
		
					*(index++) = getVertexPosition(i+1,j+1);	//3
					*(index++) = getVertexPosition(i+1,j);		//2
					*(index++) = getVertexPosition(i,j);		//0
				} else {
					*(index++) = getVertexPosition(i,j);		//0
					*(index++) = getVertexPosition(i,j+1);		//1
					*(index++) = getVertexPosition(i+1,j);		//2
		
					*(index++) = getVertexPosition(i+1,j+1);	//3
					*(index++) = getVertexPosition(i+1,j);		//2
					*(index++) = getVertexPosition(i,j+1);		//1
				}
				PRINTINDEX
				PRINTVERTEX
			}
		}
	} else {
		std::cout << "ERROR : width = " << width << ", height = " << height << " level " << getLevel() << std::endl;
		std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
		std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
		std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
		std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
}

/**
 * Calculates the upper middle part of the clipmap.
 * @pre	The pointer should point to the position of the first index of this
 * 		part to be written in the indexBuffer
 */
#if USE_16BIT_INDICES
void ClipmapRegion::calculateB(unsigned short* &index){
#else
void ClipmapRegion::calculateB(unsigned int* &index){
#endif
	int widtha = innerUpperLeftQuad.x-upperLeftQuad.x;
	int totalHeight = lowerRightQuad.y-upperLeftQuad.y+1;
	int offset = (widtha)*(totalHeight+1);

	int width = innerLowerRightQuad.x-innerUpperLeftQuad.x+1;
	int height = innerUpperLeftQuad.y-upperLeftQuad.y;
	int i,j;
	if ((width>=0)&&(height>=0)&&(width<=REGIONSIZE)&&(height<=REGIONSIZE)){
		for (int i=0;i<width;i++){
			for (int j=0;j<height;j++){
				//02
				//13
				if (upperLeftQuad.z % 2 == 0){
					*(index++) = getVertexPosition(widtha+i,j);			//0
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
		
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
					*(index++) = getVertexPosition(widtha+i,j);			//0
				} else {
					*(index++) = getVertexPosition(widtha+i,j);			//0
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
		
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
				}
				PRINTINDEX
				PRINTVERTEX
//				std::cout << "widtha " << widtha << std::endl;
			}
		}
	} else {
		std::cout << "ERROR : width = " << width << ", height = " << height << " level " << getLevel() << std::endl;
		std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
		std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
		std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
		std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
}

/**
 * Calculates the lower middle part of the clipmap.
 * @pre	The pointer should point to the position of the first index of this
 * 		part to be written in the indexBuffer
 */
#if USE_16BIT_INDICES
void ClipmapRegion::calculateC(unsigned short* &index){
#else
void ClipmapRegion::calculateC(unsigned int* &index){
#endif
	int widtha = innerUpperLeftQuad.x-upperLeftQuad.x;
	int heighta = innerLowerRightQuad.y-upperLeftQuad.y+1;
	int totalHeight = lowerRightQuad.y-upperLeftQuad.y+1;
	int offset = (widtha)*(totalHeight+1)+innerLowerRightQuad.y-upperLeftQuad.y+1;

	int width = innerLowerRightQuad.x-innerUpperLeftQuad.x+1;
	int height = lowerRightQuad.y-innerLowerRightQuad.y;
	int i,j;
	if ((width>=0)&&(height>=0)&&(width<=REGIONSIZE)&&(height<=REGIONSIZE)){
		for (int i=0;i<width;i++){
			for (int j=0;j<height;j++){
				//02
				//13
				if (upperLeftQuad.z % 2 == 0){
					*(index++) = getVertexPosition(widtha+i,heighta+j);			//0
					*(index++) = getVertexPosition(widtha+i,heighta+j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,heighta+j+1);		//3
		
					*(index++) = getVertexPosition(widtha+i+1,heighta+j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,heighta+j);		//2
					*(index++) = getVertexPosition(widtha+i,heighta+j);			//0
				} else {
					*(index++) = getVertexPosition(widtha+i,heighta+j);			//0
					*(index++) = getVertexPosition(widtha+i,heighta+j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,heighta+j);		//2
		
					*(index++) = getVertexPosition(widtha+i+1,heighta+j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,heighta+j);		//2
					*(index++) = getVertexPosition(widtha+i,heighta+j+1);		//1
				}
				PRINTINDEX
				PRINTVERTEX
//				std::cout << "widtha " << widtha << " heighta " << heighta << std::endl;
			}
		}
	} else {
		std::cout << "ERROR : width = " << width << ", height = " << height << " level " << getLevel() << std::endl;
		std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
		std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
		std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
		std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
}

/**
 * Calculates the right part of the clipmap.
 * @pre	The pointer should point to the position of the first index of this
 * 		part to be written in the indexBuffer
 */
#if USE_16BIT_INDICES
void ClipmapRegion::calculateD(unsigned short* &index){
#else
void ClipmapRegion::calculateD(unsigned int* &index){
#endif
	int widtha = innerLowerRightQuad.x-upperLeftQuad.x+1;
	int totalHeight = lowerRightQuad.y-upperLeftQuad.y+1;
	int offset = (widtha)*(totalHeight+1);

	int width = lowerRightQuad.x-innerLowerRightQuad.x;
	int height = lowerRightQuad.y-upperLeftQuad.y+1;
	int i,j;
	if ((width>=0)&&(height>=0)&&(width<=REGIONSIZE)&&(height<=REGIONSIZE)){
		for (int i=0;i<width;i++){
			for (int j=0;j<height;j++){
				//02
				//13
				if (upperLeftQuad.z % 2 == 0){
					*(index++) = getVertexPosition(widtha+i,j);			//0
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
		
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
					*(index++) = getVertexPosition(widtha+i,j);			//0
				} else {
					*(index++) = getVertexPosition(widtha+i,j);			//0
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
		
					*(index++) = getVertexPosition(widtha+i+1,j+1);		//3
					*(index++) = getVertexPosition(widtha+i+1,j);		//2
					*(index++) = getVertexPosition(widtha+i,j+1);		//1
				}
				PRINTINDEX
				PRINTVERTEX
			}
		}
	} else {
		std::cout << "ERROR : width = " << width << ", height = " << height << " level " << getLevel() << std::endl;
		std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
		std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
		std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
		std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
		std::cout << "centerx " << centerx << " centerz " << centerz << std::endl;
	}
}

Real* ClipmapRegion::getVertices(){
	return vertices;
}


#if USE_16BIT_INDICES
unsigned short* ClipmapRegion::getIndices(){
#else
unsigned int* ClipmapRegion::getIndices(){
#endif


	if (changed) {
		calculateIndices();
	}
	return indices;
}

int ClipmapRegion::getVertexCount(){
	return vertexCount;
}

int ClipmapRegion::getIndexCount(){
//	std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
//	std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
//	std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
//	std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;

	if (changed) {
		calculateIndices();
	}

//	std::cout << "innerUpperLeft " << innerUpperLeftQuad.x << "," << innerUpperLeftQuad.y << std::endl;
//	std::cout << "innerLowerRight " << innerLowerRightQuad.x << "," << innerLowerRightQuad.y << std::endl;
//	std::cout << "upperLeft " << upperLeftQuad.x << "," << upperLeftQuad.y << std::endl;
//	std::cout << "lowerRight " << lowerRightQuad.x << "," << lowerRightQuad.y << std::endl;
	return indexCount;
}

void ClipmapRegion::setVertexBuffer(HardwareVertexBufferSharedPtr &vertexBuffer){
	this->vertexBuffer = vertexBuffer;
}
void ClipmapRegion::setIndexBuffer(HardwareIndexBufferSharedPtr &indexBuffer){
	this->indexBuffer = indexBuffer;
}
void ClipmapRegion::updateVertexBuffer(){
	int vertexSize=3;
#if USE_NORMALS
	vertexSize+=3;
#endif
	int i,j;
//	std::cout << "Updating vertexBuffer" << std::endl;
//	std::cout << "offset : " << vertexOffset << std::endl;	
	Real* vertices = (Real*)vertexBuffer->lock(vertexOffset*vertexSize*sizeof(Real),REGIONSURF*vertexSize*sizeof(Real),HardwareBuffer::HBL_NO_OVERWRITE);
//	Real* vertices = (Real*)vertexBuffer->lock(HardwareBuffer::HBL_NO_OVERWRITE);
//	std::cout << "quadIndex " << quadIndex << std::endl;
	for (i=0;i<REGIONSURF;i++){
		for (j=0;j<vertexSize;j++){
			vertices[i*vertexSize+j] = this->vertices[i*vertexSize+j];
//			std::cout << this->vertices[i*3+j] << ", ";
		}
//		std::cout << std::endl;
	}
	vertexBuffer->unlock();
//	std::cout << "VertexBuffer updated" << std::endl;
}

int ClipmapRegion::updateIndexBuffer(int offset){
//	std::cout << "Updating indexbuffer..." << std::endl;
//	std::cout << "offset : " << offset << std::endl;	
	int count = getIndexCount();
#if USE_16BIT_INDICES
	unsigned short* indices = (unsigned short*)indexBuffer->lock(offset*sizeof(short),count*sizeof(short),HardwareBuffer::HBL_NO_OVERWRITE);
	unsigned short* index;
#else
	unsigned int* indices = (unsigned int*)indexBuffer->lock(offset*sizeof(int),count*sizeof(int),HardwareBuffer::HBL_NO_OVERWRITE);
	unsigned int* index;
#endif
	index = getIndices();
	int i;
	for (i=0;i<count;i++){
//		std::cout << index[i] << ", ";
		indices[i] = index[i];
	}
//	std::cout << std::endl;
//	std::cout << "buffer updated, unlocking" << std::endl;	
	indexBuffer->unlock();
//	std::cout << "done" << offset << std::endl;		
	return count;
}

void ClipmapRegion::setVertexOffset(int vertexOffset){
	this->vertexOffset = vertexOffset;
}

void ClipmapRegion::closeHole(){
//	std::cout << "centerx " << centerx << ", centerz " << centerz << std::endl;
	innerUpperLeftQuad = Vector3ix(centerx,centerz,innerUpperLeftQuad.z);
	innerLowerRightQuad = Vector3ix(centerx-1,centerz-1,innerUpperLeftQuad.z);
	changed=true;
}

bool ClipmapRegion::isVisible() const {
	return !isTooBig();
}

bool ClipmapRegion::isTooBig() const {
	return (upperLeftQuad.x >= innerUpperLeftQuad.x) 
		&& (upperLeftQuad.y >= innerUpperLeftQuad.y)
		&& (lowerRightQuad.x <= innerLowerRightQuad.x)
		&& (lowerRightQuad.y <= innerLowerRightQuad.y);
}

void ClipmapRegion::setInnerUpperLeftQuad(Vector3ix innerUpperLeftQuad){
	this->innerUpperLeftQuad = innerUpperLeftQuad;
	changed = true;
}

void ClipmapRegion::setInnerLowerRightQuad(Vector3ix innerLowerRightQuad){
	this->innerLowerRightQuad = innerLowerRightQuad;
	changed = true;
}

const Vector3ix ClipmapRegion::getInnerUpperLeftQuad() const{
	return innerUpperLeftQuad;
}

const Vector3ix ClipmapRegion::getInnerLowerRightQuad() const{
	return innerLowerRightQuad;
}

const Vector3ix ClipmapRegion::getUpperLeftQuad() const{
	return upperLeftQuad;
}

const Vector3ix ClipmapRegion::getLowerRightQuad() const{
	return lowerRightQuad;
}

}
