Index: /branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h	(revision 8640)
+++ /branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h	(revision 8641)
@@ -56,5 +56,6 @@
 			head = tail = NULL;
 		}
-		
+		inline int getIBSize() { return ibSize; }
+		inline int getVBSize() { return vbSize; }		
 		inline void acquire( GLuint &_vbName, GLuint &_ibName );
 		
@@ -78,5 +79,4 @@
 	pBufferPair bp = head, prev = NULL;
 	bool removed = false;
-	
 	while ( bp ) {
 
@@ -106,5 +106,5 @@
 inline void BufferBroker::acquire( GLuint &_vbName, GLuint &_ibName )
 {
-
+	assert( capacity > lastAcquired );
 	int index = capacity-lastAcquired-1;
 	_vbName = freeVertexBuffers[index]; _ibName = freeIndexBuffers[index];
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8640)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8641)
@@ -34,5 +34,5 @@
 	//tex = (Texture*)MANAGER->load( lightmapSource );
 	//TODO: Determine layer visibility!	
-	for ( int i = 0; i < materials.size(); ++i ) {
+	for ( unsigned int i = 0; i < materials.size(); ++i ) {
 		
 	}
@@ -92,4 +92,46 @@
 	newPage->calculateErrors();
 	return newPage;
+}
+
+void Terrain::addLevelFourPage( int _numVertices, Vertex *_vertices, 
+	int _numIndices, unsigned short *_indices )
+{
+	assert( indices ); assert( vertices );
+	BufferInfo bi = buffers[current];	
+	if ( ( MAX_VERTICES < _numVertices+bi.numVertices ) || 
+		( MAX_INDICES < _numIndices+bi.numIndices+2 ) ) {
+		//So, we need the next vb and ib. Lets put the old into vram...
+		glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier );
+		glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 
+			vertices, GL_DYNAMIC_DRAW_ARB );
+		glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bi.ibIdentifier );
+		glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 
+			indices, GL_DYNAMIC_DRAW_ARB );
+		//printf( "uploaded %d verts and %d indices\n", bi.numIndices, bi.numVertices );
+		BufferInfo newInfo;
+		broker->acquire( newInfo.vbIdentifier, newInfo.ibIdentifier );			
+		current++;	
+		buffers.push_back( newInfo );	
+		bi = newInfo;
+	}
+	//For the vertex data, a simple copy operation is sufficient...
+	memcpy( &vertices[bi.numVertices], _vertices, 
+		_numVertices*sizeof( Vertex ) );
+	bi.numVertices+=_numVertices;
+	//The indices need to be updated with an offset :(
+	unsigned short *end = _indices+_numIndices;
+	unsigned short *dst = indices+bi.numIndices;
+	int offset = bi.numIndices;
+	if ( bi.numIndices > 0 ) {
+		indices[bi.numIndices] = indices[bi.numIndices-1];
+		indices[bi.numIndices+1] = _indices[0]+offset;
+		dst+=2;
+		bi.numIndices+=2;
+	}
+	for ( unsigned short *i = _indices; i < end; ++i ) {
+		*indices = *i+offset;
+	}
+	bi.numIndices+=_numIndices;
+	buffers[current] = bi;
 }
 
@@ -154,4 +196,8 @@
 	page = activePages;
 	bool dirty;
+	current = 0;
+	BufferInfo bi;
+	broker->acquire( bi.vbIdentifier, bi.ibIdentifier );
+	buffers.push_back( bi );
 	do {
 		dirty = false;
@@ -174,5 +220,6 @@
 				wantedBottom = neighbor->getWantedLOD();			
 		
-			minLOD = std::min( std::min( wantedBottom, wantedTop ), std::min( wantedLeft, wantedRight ) );	
+			minLOD = std::min( std::min( wantedBottom, wantedTop ), 
+				std::min( wantedLeft, wantedRight ) );	
 			if ( minLOD < page->getWantedLOD()-1 ) {
 				page->setWantedLOD( minLOD+1 );
@@ -188,7 +235,18 @@
 		page = page->getNext();
 	}
-	
+	//Finish the last buffer
+	if ( buffers[current].numIndices != 0 ) {
+		BufferInfo bi = buffers[current];	
+		glBindBufferARB( GL_ARRAY_BUFFER_ARB, 
+			bi.vbIdentifier );
+		glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 
+			vertices, GL_DYNAMIC_DRAW_ARB );
+		glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
+			bi.ibIdentifier );
+		glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 
+			indices, GL_DYNAMIC_DRAW_ARB );
+	}
 	s = 500.0f;
-	for ( int i = 0; i < materials.size(); ++i ) {
+	for ( unsigned int i = 0; i < materials.size(); ++i ) {
 		page = activePages;	
 		
@@ -202,12 +260,25 @@
 		glLoadIdentity();
 		glScalef( s, s, s );
-		
+
 		glClientActiveTextureARB( GL_TEXTURE0_ARB );
 		glActiveTextureARB( GL_TEXTURE0_ARB );
 		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );				
 		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+		for ( unsigned j = 0; j < buffers.size(); ++j ) {
+			BufferInfo bi = buffers[j];
+			glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier );
+			glClientActiveTextureARB( GL_TEXTURE0_ARB );
+			glInterleavedArrays( GL_T2F_V3F, 0, NULL );
+
+			glClientActiveTextureARB( GL_TEXTURE1_ARB );
+			glInterleavedArrays( GL_T2F_V3F, 0, NULL );
+
+			glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
+				bi.ibIdentifier );	
+
+			glDrawElements( GL_TRIANGLE_STRIP, bi.numIndices, 
+							GL_UNSIGNED_SHORT, NULL );
+		}
 		while ( page ) {
-			//Draw the page. TODO: It would be nice if all the pages with an LOD of 4 could be merged
-			//in one index buffer. This would give us a speed boost for sure...
 			if ( page->hasMaterial( i ) )
 				page->draw();
@@ -219,4 +290,11 @@
 		//printf( "culled %f%% terrain pages away\n",  percentage );
 	}
+	
+	//Get rid of the buffers
+	
+	for ( unsigned int i = 0; i < buffers.size(); ++i )
+		broker->release( buffers[i].vbIdentifier, buffers[i].ibIdentifier );
+	buffers.clear();
+		
 	glClientActiveTextureARB( GL_TEXTURE1_ARB );	
 	glDisableClientState( GL_VERTEX_ARRAY );
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 8640)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 8641)
@@ -33,9 +33,31 @@
 
 typedef struct {
-	int 		width;
-	int 		height;
-	int			pitch;
-	UByte		*data;
+	int 			width;
+	int 			height;
+	int				pitch;
+	UByte			*data;
 } Heightfield, *pHeightfield;
+
+struct BufferInfo {
+	
+	unsigned int	vbIdentifier,
+					ibIdentifier,
+					numIndices,
+					numVertices;
+	
+	BufferInfo( unsigned int _vb, unsigned int _ib, 
+		unsigned int _numV, unsigned int _numI )
+	{
+		vbIdentifier = _vb; ibIdentifier = _ib; 
+		numIndices = _numI; numVertices =_numV;
+		
+	}
+	
+	BufferInfo()
+	{
+		vbIdentifier = ibIdentifier = numIndices = numVertices = 0;
+	}
+};
+
 
 class Terrain;
@@ -47,5 +69,7 @@
 class Terrain {
 	public:
-	
+		const static int PAGE_SIZE 			= 17;
+		const static int MAX_VERTICES 		= PAGE_SIZE*PAGE_SIZE;
+		const static int MAX_INDICES		= 3*MAX_VERTICES/*2*( PAGE_SIZE*PAGE_SIZE - PAGE_SIZE ) - 2*/;
 		/**
 		 * The amount of geometry rendered is largely depending on this constant. So chose a
@@ -75,4 +99,7 @@
 		void getAltitude( Triple& _alt, Triple& _normal );
 		
+		//What a bad name: Need to rename that :(
+		void addLevelFourPage( int _numVertices, Vertex *_vertices, 
+			int _numIndices, unsigned short *_indices );
 		void showPages( int _x0, int _z0, int _width, int _height );
 					
@@ -86,7 +113,9 @@
 			frustum = new Frustum();
 			activatedCount = deactivatedCount = 0;
-#ifdef USE_VBO
-			broker = new BufferBroker( 400, pageSize*pageSize*sizeof( Vertex ), 
-				pageSize*pageSize*sizeof( short )*3 );
+			vertices = new Vertex[MAX_VERTICES];
+			indices = new unsigned short[MAX_INDICES];
+#ifdef USE_VBO
+			broker = new BufferBroker( 200, MAX_VERTICES*sizeof( Vertex ), 
+				MAX_INDICES*sizeof( short ) );
 #endif			
 		}
@@ -181,24 +210,32 @@
 		
 #ifdef USE_VBO
-		pBufferBroker			broker;
+		pBufferBroker				broker;
 #endif
-		pTerrainQuad			root;		// The quad-tree root node.
-		pTerrainPage			*pages;		// the references to all pages
-		std::string				heightmapSource;
-		std::string				lightmapSource;
-		Heightfield				heightfield;
-		Triple					scale;
-		int 					pagesX, 
-								pagesZ;
-		int						pageSize;	
-		int						cullCount;
-		
-		int						activatedCount, 
-								deactivatedCount; // For debugging and statistics
-		Texture					*tex;
-		Triple					cameraPosition;
-		pFrustum				frustum;
-		pTerrainPage			activePages;
-		std::vector<Material*>	materials;
+		pTerrainQuad				root;		// The quad-tree root node.
+		pTerrainPage				*pages;		// the references to all pages
+		std::string					heightmapSource;
+		std::string					lightmapSource;
+		Heightfield					heightfield;
+		Triple						scale;
+		int 						pagesX, 
+									pagesZ;
+		int							pageSize;	
+		int							cullCount;
+		
+		int							activatedCount, 
+									deactivatedCount; // For debugging and statistics
+								
+		//The next five members are for the level 4 pages.						
+		Vertex						*vertices;						
+		unsigned short				*indices;
+		int							current;
+									
+		std::vector<BufferInfo>		buffers;			
+			
+		//Texture					*tex;
+		Triple						cameraPosition;
+		pFrustum					frustum;
+		pTerrainPage				activePages;
+		std::vector<Material*>		materials;
 };
 
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8640)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8641)
@@ -33,5 +33,5 @@
 	numVertices = numIndices = 0;
 	errors = new LODError[TerrainPage::MAX_LODS];
-	vertices = NULL; indices = NULL;
+	vertices = NULL; indices = NULL; 
 	position = Triple( scale.x*_xOffset, 0.0f, scale.z*_zOffset );
 	isVisible = false;
@@ -41,4 +41,5 @@
 	currentLOD = -1;
 	forceTesselation = true;
+	vbIdentifier = 0; ibIdentifier = 0;
 }
 
@@ -259,9 +260,17 @@
 	}	
 	currentLOD = wantedLOD;
+	//Check if the page is a level four page. If yes, copy the vertex and index data into 
+	//
+	if ( currentLOD == TerrainPage::MAX_LODS-1 ) {
+		owner->addLevelFourPage( numVertices, vertices, 
+			numIndices, indices );
+	}
 	forceTesselation = false;
 }
 
-void TerrainPage::tesselateLevelFourPatch( bool _adapt[] )
-{
+void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
+{
+	assert( indices ); assert( vertices );
+	numIndices = numVertices = 0;
 	const int	halfStride = 8, stride = 16;
 	
@@ -434,4 +443,7 @@
 			break;
 	}
+	assert( numVertices > 3 );
+
+	assert( numIndices % 2 == 0 );
 }
 
@@ -440,8 +452,6 @@
 {
 
-	int count = owner->getPageSize()*owner->getPageSize();	
-
 	memset( indexHash, 0xffff, 
-			sizeof(unsigned short)*count );
+			sizeof(unsigned short)*Terrain::MAX_VERTICES );
 	
 	numVertices = 0; numIndices = 0;
@@ -454,32 +464,53 @@
 	assert( isVisible );
 #ifdef USE_VBO
-	
-	glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
-	
-	// The call to glBufferDataARB with a null argument for data is to tell the GPU, that the
-	// old data is invalid. Then calling call glMapBuffer() tells the driver that the previous 
-	// data aren’t valid. As a consequence, if the GPU is still working on them, there won’t 
-	// be a conflict because we invalidated these data. The function glMapBuffer() returns a 
-	// new pointer that we can use while the GPU is working on the previous set of data.. 
-	
-	glBufferDataARB( GL_ARRAY_BUFFER_ARB, count*sizeof( Vertex ), NULL, GL_DYNAMIC_DRAW_ARB );
-	
-	vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB, 
-		GL_WRITE_ONLY_ARB );
-	
-	glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
-	
-	glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
-		count*3*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB );	
-		
-	indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
-		GL_WRITE_ONLY_ARB );
-	
-	assert( indices ); 
-	assert( vertices );
-	
+	if ( _lod == TerrainPage::MAX_LODS-1 ) {
+		if ( vbIdentifier && ibIdentifier ) {
+			owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
+			vbIdentifier = ibIdentifier = 0;
+		}
+		if ( !vertices ) 
+			vertices =  new Vertex[8]; 
+		if ( !indices )
+			indices = new unsigned short[8];
+	}
+	else {
+		if ( !vbIdentifier && !ibIdentifier ) {
+			owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
+			if ( vertices )
+				delete[] vertices;
+			if ( indices )
+				delete[] indices;
+			vertices = NULL; indices = NULL;	
+		}
+		assert( vbIdentifier ); assert( ibIdentifier );
+		glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
+
+		// The call to glBufferDataARB with a null argument for data is to make things faster.
+		// Then calling call glMapBuffer() tells the driver that the previous 
+		// data aren’t valid. As a consequence, if the GPU is still working on them, there won’t 
+		// be a conflict because we invalidated these data. The function glMapBuffer() returns a 
+		// new pointer that we can use while the GPU is working on the previous set of data.. 
+
+		glBufferDataARB( GL_ARRAY_BUFFER_ARB, Terrain::MAX_VERTICES*sizeof( Vertex ), 
+			NULL, GL_DYNAMIC_DRAW_ARB );
+
+		vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB, 
+			GL_WRITE_ONLY_ARB );
+
+		glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
+
+		glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
+			Terrain::MAX_INDICES*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB );	
+
+		indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
+			GL_WRITE_ONLY_ARB );
+
+	}	
+
 #endif	
+
+	assert( indices ); 	assert( vertices );
 	if ( _lod == TerrainPage::MAX_LODS-1 ) {
-		tesselateLevelFourPatch( adapt );
+		tesselateLevelFourPage( adapt );
 		return;
 	}
@@ -508,6 +539,10 @@
 	
 #ifdef USE_VBO
-	glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
-	glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB );
+	if ( vbIdentifier && ibIdentifier ) {
+		glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
+		indices = NULL;
+		glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB );
+		vertices = NULL;
+	}	
 #endif
 
@@ -517,21 +552,19 @@
 void TerrainPage::show( )
 {
-	int count = owner->getPageSize()*owner->getPageSize();
 	
 #ifdef USE_VBO	
-	owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
+	//This is done later on...
+	//owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
 	vertices = NULL;
 	indices = NULL;
 #else
-	vertices = new Vertex[count];
-	// Not the economical way, but we just want to have space for all indices.
-	indices = new unsigned short[count*3];
+	vertices = new Vertex[Terrain::MAX_VERTICES];
+	indices = new unsigned short[Terrain::MAX_INDICES];
 #endif	
-
-	indexHash = new unsigned short[count];	
+	vbIdentifier = 0; ibIdentifier = 0;
+	indexHash = new unsigned short[Terrain::MAX_VERTICES];	
 	forceTesselation = true;
 	activate();
 	active = true;
-	
 }
 
@@ -539,6 +572,6 @@
 {
 #ifdef USE_VBO
-	owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
-#else	
+	owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );	
+#endif
 	if ( vertices ) {
 		delete[] vertices;
@@ -550,5 +583,4 @@
 		numIndices = 0;
 	}
-#endif
 	deactivate();
 }
@@ -582,5 +614,6 @@
 	glPopMatrix();
 }
-
+//TODO: put all the pages that have a coarses tesselation level than 4 into a
+//		separate list!
 void TerrainPage::draw( )
 {
@@ -588,4 +621,7 @@
 	assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
 	
+	if ( currentLOD == TerrainPage::MAX_LODS-1 )
+		return;
+		
 	assert( isVisible ); assert( numIndices > 0 );
 	assert( active );
@@ -625,5 +661,5 @@
 }
 
-short TerrainPage::getIndex( int _x, int _z )
+unsigned short TerrainPage::getIndex( int _x, int _z )
 {
 	unsigned short index = _z*owner->getPageSize()+_x;
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8640)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8641)
@@ -43,5 +43,5 @@
 	public:
 		enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 };
-		const static int MAX_LODS = 5;
+		const static int MAX_LODS 			= 5;
 		/**
 		 * Creates a new terrain page with its lower left corner set
@@ -263,6 +263,6 @@
 		 * created before, this method does that for you. 
 		 */			
-		short getIndex( int _x, int _z );
-		void tesselateLevelFourPatch( bool _adapt[] );
+		unsigned short getIndex( int _x, int _z );
+		void tesselateLevelFourPage( bool _adapt[] );
 	   /**
 		* Generates the tesselation for the given level of detail.
