Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8348)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8349)
@@ -35,5 +35,5 @@
 	
 	//TODO: Determine layer visibility!
-	printf( "creating terrain pages ( %d, %d )...", pagesX, pagesZ );
+	printf( " * creating terrain pages ( %d, %d )...", pagesX, pagesZ );
 	pages = new pTerrainPage[pagesX*pagesZ];	
 	for ( int x = 0; x < pagesX; ++x )
@@ -41,5 +41,16 @@
 			pages[z*pagesX+x] = createPage( x, z );
 	printf( "looks good\n" );
-	printf( "creating quad_tree data structure..." );
+	printf( " * inform pages about the adjacent pages..." );			
+	//Inform each page about its neighbors.
+	for ( int x = 0; x < pagesX; ++x )
+		for ( int z = 0; z < pagesZ; ++z )
+			pages[z*pagesX+x]->setNeighbors(
+				x > 0 			? getPage( x-1, z+0 ) : NULL,
+				x < pagesX-1	? getPage( x+1, z+0 ) : NULL, 
+				z > 0 			? getPage( x+0, z-1 ) : NULL,
+				z < pagesZ-1	? getPage( x+0, z+1 ) : NULL );
+	
+	printf( "looks good\n" );
+	printf( " * creating quad_tree data structure..." );
 	root = createQuadTree( 0, 0, pagesX, pagesZ );
 	activePages = NULL;
@@ -132,5 +143,4 @@
 	determineVisiblePages( root );
 		
-	int count = 0;
 	page = activePages;	
 	while ( page ) {
@@ -139,9 +149,6 @@
 			page = tmp->getNext();
 			tmp->setVisibility( false );
-			tmp->deactivate();
-			deactivatedCount++;
 			continue;
 		}	
-		count++;
 		page->updateTesselation();
 		//Draw the page. TODO: It would be nice if all the pages with an LOD of 4 could be merged
@@ -150,7 +157,6 @@
 		page = page->getNext();
 	}
-	//printf( "%d pages activated, %d pages deactivated\n", activatedCount, deactivatedCount );
 	activatedCount = 0; deactivatedCount = 0;
-	float percentage = (float)cullCount/(float)(pagesX*pagesZ)*100.0f;
+	//float percentage = (float)cullCount/(float)(pagesX*pagesZ)*100.0f;
 	//printf( "culled %f%% terrain pages away\n",  percentage );
 }
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8348)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8349)
@@ -42,4 +42,67 @@
 }
 
+void TerrainPage::tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight )
+{
+	int xStart = 0, xEnd = owner->getPageSize();
+	
+	int halfStride = _zStride >> 1;
+
+
+	if ( _z ) {
+		addAgain( );
+		addIndex( getIndex( 0, _z ) );
+	}
+	if ( _adaptLeft ) {
+		assert( halfStride > 0 ); 		
+		addIndex( getIndex( 0, _z ) );
+		addIndex( getIndex( 0, _z+halfStride ) );
+		addIndex( getIndex( _xStride, _z ) );
+		addIndex( getIndex( 0, _z+_zStride ) );
+		addIndex( getIndex( _xStride, _z+_zStride ) );
+		addAgain();
+		xStart = _xStride;
+	}
+	
+	if ( _adaptRight )
+		xEnd-=_xStride;
+		
+	for ( int x = xStart; x < xEnd; x+=_xStride ) {
+		addIndex( getIndex( x, _z) );
+		addIndex( getIndex( x, _z+_zStride ) );
+	}
+	
+	int w = owner->getPageSize()-1;
+	
+	if ( _adaptRight ) {
+		assert( halfStride > 0 ); 		
+		addIndex( getIndex( w-_xStride, _z ) );
+		addAgain();
+		addIndex( getIndex( w, _z ) );
+		addIndex( getIndex( w-_xStride, _z+_zStride ) );
+		addIndex( getIndex( w, _z+halfStride ) );
+		addIndex( getIndex( w, _z+_zStride ) );
+	}
+}
+
+//TODO: Perform benchmark to measure if the isVisible test should be included
+//in this method.
+
+void TerrainPage::determineBorderAdaption( bool _adapt[] )
+{
+	_adapt[0] = _adapt[1] = _adapt[2] = _adapt[3] = false;
+	
+	if ( left  && left->isVisible ) 
+		_adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0;
+		
+	if ( right && right->isVisible ) 
+		_adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0;
+		
+	if ( top && top->isVisible) 
+		_adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0;				
+		
+	if ( bottom && bottom->isVisible ) 
+		_adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0;		
+}
+
 int TerrainPage::chooseLOD()
 {
@@ -65,5 +128,6 @@
 		wantedLOD = TerrainPage::MAX_LODS-1;
 	}	
-	// Calculate the tween factor. This is differently if the LOD is 0.
+	// Calculate the tween factor. The calculation is different if LOD is 0
+	// 
 	if ( wantedLOD > 0 ) {
 		
@@ -82,5 +146,4 @@
 	if ( list )
 		list->previous = this;
-	owner->incActivated();
 	owner->setActiveList( this );
 }
@@ -99,5 +162,4 @@
 		owner->setActiveList( next );
 	next = NULL;
-	owner->incDeactivated();
 	previous = NULL;
 	
@@ -111,21 +173,21 @@
 	if( _lod!=0 )
 	{
-		int pow = 1 << _lod, x0, y0, xi, yi;
+		int stride = 1 << _lod, x0, y0, xi, yi;
 		// Altough these four nested loops look very scary, they're not 
-		// that bad. 
-		for( y0 = 0 ; y0 < size-pow; y0 += pow ) {
-			for( x0 = 0; x0 < size-pow; x0 += pow ) {
-				for( yi = 1; yi < pow; yi++ ) {
-					for( xi = 1; xi < pow; xi++ )
+		// that bad and require only about O(n^2). 
+		for( y0 = 0 ; y0 < size-stride; y0 += stride ) {
+			for( x0 = 0; x0 < size-stride; x0 += stride ) {
+				for( yi = 1; yi < stride; yi++ ) {
+					for( xi = 1; xi < stride; xi++ )
 					{
 						int	x = x0+xi,
 						y = y0+yi;
-						float	fx0 = ( float )xi/( float )pow, fx1 = 1.0f-fx0,
-								fy0 = ( float )yi/( float )pow, fy1 = 1.0f-fy0;
+						float	fx0 = ( float )xi/( float )stride, fx1 = 1.0f-fx0,
+								fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0;
 						
 						float	height00 = getAltitude( x0, y0 ),
-								height10 = getAltitude( x0+pow,y0 ),
-								height01 = getAltitude( x0,y0+pow ),
-								height11 = getAltitude( x0+pow, y0+pow );
+								height10 = getAltitude( x0+stride,y0 ),
+								height01 = getAltitude( x0,y0+stride ),
+								height11 = getAltitude( x0+stride, y0+stride );
 						
 						float	paintHeight =	fx1*fy1 * height00 +
@@ -179,40 +241,244 @@
 }
 
+bool TerrainPage::needsRetesselation()
+{
+	
+	bool 	leftChanged 	= ( left && left->isVisible ) && ( left->wantedLOD != left->currentLOD ),
+			rightChanged	= ( right && right->isVisible ) && ( right->wantedLOD != right->currentLOD ),
+			topChanged		= ( top && top->isVisible ) && ( top->wantedLOD != currentLOD ),
+			bottomChanged	= ( bottom && bottom->isVisible ) && ( bottom->wantedLOD != bottom->currentLOD ),
+			iChanged		=  wantedLOD != currentLOD;
+				
+	return ( leftChanged || rightChanged || topChanged || bottomChanged || forceTesselation || iChanged );
+}
+
 void TerrainPage::updateTesselation( )
 {
+
+	if ( needsRetesselation() ) {
+		tesselate( wantedLOD );
+	}	
 	currentLOD = wantedLOD;
-	if ( forceTesselation || currentLOD != currentLOD ) {
-		tesselate( currentLOD );
-	}	
-
 	forceTesselation = false;
 }
 
-/**
- * Genererates a tesselation for the given _lod. 
- */
+void TerrainPage::tesselateLevelFourPatch( bool _adapt[] )
+{
+	const int	halfStride = 8, stride = 16;
+	
+	enum { ADAPT_L = 1, ADAPT_R = 2, ADAPT_B = 4, ADAPT_T = 8,
+		ADAPT_LR = 3, ADAPT_LB = 5, ADAPT_LT = 9, ADAPT_RB = 6, 
+		ADAPT_RT = 10, ADAPT_BT = 12, ADAPT_LRB = 7, ADAPT_LBT = 13, ADAPT_LRT = 11, 
+		ADAPT_RBT = 14, ADAPT_LRBT = 15, ADAPT_NONE = 0 };
+		
+	int			code =  ( _adapt[TP_LEFT] 	? ADAPT_L : 0 ) | 
+						( _adapt[TP_RIGHT] 	? ADAPT_R : 0 ) | 
+						( _adapt[TP_BOTTOM] ? ADAPT_B : 0 ) | 
+						( _adapt[TP_TOP]	? ADAPT_T : 0 );
+	switch( code ) {
+		case ADAPT_NONE:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+			
+	 	case ADAPT_L:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, stride ) );
+			addAgain(  );
+		 	break;
+		
+		case ADAPT_R:
+			addIndex( getIndex( stride, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, 0 ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_LR:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+
+		case ADAPT_B:
+			addIndex( getIndex( 0, 0 ) );
+			addAgain(  );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+
+		case ADAPT_LB:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+
+		case ADAPT_RB:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( stride, 0 ) );
+			addAgain(  );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+
+		case ADAPT_LRB:
+			addIndex( getIndex( stride, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, 0 ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_T:
+			addIndex( getIndex( stride, stride ) );
+			addAgain(  );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( 0, 0 ) );
+			break;
+
+		case ADAPT_LT:
+			addIndex( getIndex( stride, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( 0, stride ) );
+			addAgain(  );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( 0, 0 ) );
+			break;
+
+		case ADAPT_RT:
+			addIndex( getIndex( stride, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( 0, 0 ) );
+			break;
+
+		case ADAPT_LRT:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, stride ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_BT:
+			addIndex( getIndex( 0, 0 ) );
+			addAgain(  );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, stride ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_LBT:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, stride ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_RBT:
+			addIndex( getIndex( stride, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, 0 ) );
+			addAgain(  );
+			break;
+
+		case ADAPT_LRBT:
+			addIndex( getIndex( 0, 0 ) );
+			addIndex( getIndex( 0, halfStride ) );
+			addIndex( getIndex( halfStride, 0 ) );
+			addIndex( getIndex( 0, stride ) );
+			addIndex( getIndex( stride, 0 ) );
+			addIndex( getIndex( halfStride, stride ) );
+			addIndex( getIndex( stride, halfStride ) );
+			addIndex( getIndex( stride, stride ) );
+			break;
+	}
+}
+
+
 void TerrainPage::tesselate( int _lod )
 {
+
 	int count = owner->getPageSize()*owner->getPageSize();	
+
 	memset( indexHash, 0xffff, 
 			sizeof(unsigned short)*count );
+	
 	numVertices = 0; numIndices = 0;
 	
-	assert( isVisible );
 	//Calculate the pace, based on the lod.
 	int stride = 1 << _lod;
-	for ( int z = 0; z < owner->getPageSize()-stride; z+=stride ) {
-		if ( z > 0 ) {			
-			//Connect the two rows together by inserting the last index of last row
-			//and the first index of the next row two times. This will produce two
-			//degenerate triangles.
-			addAgain( );
-			addIndex( getIndex( 0, z ) );
-		}
-		for ( int x = 0; x < owner->getPageSize(); x+=stride ) {
-			addIndex( getIndex( x, z ) );
-			addIndex( getIndex( x, z+stride ) );
-		}
-	}
+		
+	bool adapt[4];
+	determineBorderAdaption( adapt );
+	assert( isVisible );
+	if ( _lod == TerrainPage::MAX_LODS-1 ) {
+		tesselateLevelFourPatch( adapt );
+		return;
+	}
+	
+	int zStart = 0, zEnd = owner->getPageSize()-stride;
+	
+	if ( adapt[TP_TOP] ) {
+		tesselateRow( 0, stride / 2, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+		zStart+= stride;
+	}
+	
+	if ( adapt[TP_BOTTOM] )
+		zEnd-= stride;
+		
+	for ( int z = zStart; z < zEnd; z+=stride )
+		tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+	
+
+	if ( !adapt[TP_BOTTOM] )
+		return;
+		
+	addAgain( );
+	addIndex( getIndex( 0, owner->getPageSize()-1-stride ) );
+	
+	tesselateRow( owner->getPageSize()-1-stride, stride / 2, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+
 }
 
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8348)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8349)
@@ -35,4 +35,5 @@
 class TerrainPage : public TerrainQuad {
 	public:
+		enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 };
 		const static int MAX_LODS = 5;
 		/**
@@ -112,5 +113,6 @@
 		 * No geometry is updated in this method. You need to call 
 		 * updateTesselation() in order to see a change in geometry. This method is
-		 * just a recommandation.
+		 * just a recommondation for the LOD. It might be invalid due to outer 
+		 * constraints.
 		 */
 		int chooseLOD();
@@ -140,5 +142,6 @@
 		 */
 		bool cull( );
-		
+
+		bool needsRetesselation();
 		/**
 		 * Sets the neighbors of this terrain page. pass null if a neighbor if this
@@ -160,4 +163,9 @@
 			position.z = _pos.z;
 		}
+
+		pTerrainPage getLeft() { return left; }
+		pTerrainPage getRight() { return right; }
+		pTerrainPage getBottom() { return bottom; }
+		pTerrainPage getTop() { return top; }						
 		
 		/**
@@ -175,5 +183,5 @@
 		 */
 		inline pTerrainPage getPrevious() { return previous; }			
-		
+		inline int getCurrentLOD() { return currentLOD; }
 		/**
 		 * @return Returns the wanted LOD. Make sure you call this method after a call to
@@ -194,10 +202,35 @@
 		protected:
 			
-			
+			/**
+			 * @brief Tesselates one row of the terrain page.
+			 * @param _z 			The z-offset of the row
+			 * @param _xStride 		Determines the step-size horizontally
+			 * @param _zStride		Determines the step-size vertically.
+			 * @param _adaptRight	True if the right neighbor has a coarser
+			 *						tesselation level.
+			 * @param _adaptLeft	True if the left neighbor has a coarser
+			 *						tesselation level.			
+			 */
+			void tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight );
+
+			/** 
+			 * @brief Returns four boolean values in the oder
+			 */
+			void determineBorderAdaption( bool _adapt[] );
+			
+			/**
+			 * @brief Adds the given index to the index-array
+			 */
 			inline void addIndex( unsigned short _index );
-	
+			
+			/**
+			 * @brief We programmers are very lazy :) This method just adds the last added index
+			 * again.
+			 */
 			inline void addAgain();
 			
+			
 			void getCoord( int _x, int _z, TexCoord& _coord) const;
+			
 			/** 
 			 * Fills _vertex with the vertex information at index.
@@ -205,10 +238,10 @@
 			void getVertex( int _x, int _z, Triple& _vertex ) const;
 			
-			/**
-			* Use this method to safely get a vertex at location ( _x, _z ). If it wasn't
-			* created before, this method does that for you. 
-			*/			
+		 	/**
+			 * Use this method to safely get a vertex at location ( _x, _z ). If it wasn't
+			 * created before, this method does that for you. 
+			 */			
 			short getIndex( int _x, int _z );
-			
+			void tesselateLevelFourPatch( bool _adapt[] );
 		   /**
 			* Generates the tesselation for the given level of detail.
Index: /branches/terrain/src/world_entities/camera.cc
===================================================================
--- /branches/terrain/src/world_entities/camera.cc	(revision 8348)
+++ /branches/terrain/src/world_entities/camera.cc	(revision 8349)
@@ -36,5 +36,5 @@
   this->setFovy(90);
   this->setAspectRatio(1.2f);
-  this->setClipRegion(.1, 2000);
+  this->setClipRegion( .1, 100.0f );
 
   this->setViewMode(Camera::ViewNormal);
