Index: branches/terrain/src/lib/graphics/importer/Makefile.am
===================================================================
--- branches/terrain/src/lib/graphics/importer/Makefile.am	(revision 8308)
+++ branches/terrain/src/lib/graphics/importer/Makefile.am	(revision 8319)
@@ -21,7 +21,9 @@
                            bsp_file.cc \
                            bsp_tree_node.cc \
-                           bsp_tree_leaf.cc
-
-
+                           bsp_tree_leaf.cc \
+                           terrain/terrain.cc \
+                           terrain/terrain_quad.cc \
+                           terrain/terrain_page.cc \
+                           terrain/frustum.cc
 
 libtc_a_SOURCES  = tc.cc
@@ -49,3 +51,8 @@
 		bsp_file.h \
 		bsp_tree_node.h \
-		bsp_tree_leaf.h
+		bsp_tree_leaf.h \
+		terrain/terrain.h \
+		terrain/terrain_page.h \
+		terrain/terrain_quad.h \
+		terrain/frustum.h \
+		terrain/types.h
Index: branches/terrain/src/lib/graphics/importer/terrain/frustum.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/frustum.cc	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/frustum.cc	(revision 8319)
@@ -0,0 +1,17 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+
+#include "frustum.h"
+
Index: branches/terrain/src/lib/graphics/importer/terrain/frustum.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/frustum.h	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/frustum.h	(revision 8319)
@@ -0,0 +1,119 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+#ifndef _FRUSTUM_H
+#define _FRUSTUM_H
+#include "types.h"
+#include "glincl.h"
+
+#define m( _row,_col )  _m[_col*4+_row-5]
+
+/** 
+ * Code borrowed from Lighthouse 3D 
+ */
+class Frustum;
+typedef Frustum *pFrustum;
+class Frustum {
+
+	public:
+		
+		enum { NEAR = 0 , FAR = 1, TOP = 2, BOTTOM = 3, LEFT = 4, RIGHT = 5 };
+		enum {OUTSIDE, INTERSECT, INSIDE};		
+		
+		Frustum()
+		{
+			planes = new Plane[6];
+		}
+		~Frustum()
+		{
+			if ( planes )
+				delete[] planes;
+		}
+		/**
+		 * Extracts the frustum planes from the GL_PROJECTION and GL_MODELVIEW
+		 * matrices...
+		 */
+		inline void extractPlanes()
+		{
+			float proj[16], view[16], combined[16];
+			glGetFloatv( GL_MODELVIEW_MATRIX, view );
+			glGetFloatv( GL_PROJECTION_MATRIX, proj );
+			multMat( combined, view, proj );
+			setFrustum( combined );
+		}
+		
+		inline int boxInFrustum( const ABox& _box )
+		{
+			int result = INSIDE;
+			for(int i=0; i < 6; i++) {
+
+				if ( planes[i].distance( _box.vertexP( planes[i].n ) ) < 0 )
+					return OUTSIDE;
+				if ( planes[i].distance( _box.vertexN( planes[i].n) ) < 0 )
+					result =  INTERSECT;
+			}
+			return result;		
+		}
+		
+		inline int pointInFrustum( const Triple& _point)
+		{
+			int result = INSIDE;
+			for(int i=0; i < 6; i++) {
+
+				if (planes[i].distance( _point ) < 0)
+					return OUTSIDE;
+			}
+			return result;		
+		}
+		
+		inline Plane getPlane( int _plane ) { return planes[_plane]; }
+		inline void setFrustum( float *_m )
+		{
+			planes[NEAR].setCoefficients(
+							 m( 3, 1 ) + m( 4, 1 ),
+							 m( 3, 2 ) + m( 4, 2 ),
+							 m( 3, 3 ) + m( 4, 3 ),
+							 m( 3, 4 ) + m( 4, 4 ) );
+			planes[FAR].setCoefficients( 
+							-m( 3, 1 ) + m( 4, 1 ),
+							-m( 3, 2 ) + m( 4, 2 ),
+							-m( 3, 3 ) + m( 4, 3 ),
+							-m( 3, 4 ) + m( 4, 4 ) );
+			planes[BOTTOM].setCoefficients(
+							 m( 2, 1 ) + m( 4, 1 ),
+							 m( 2, 2 ) + m( 4, 2 ),
+							 m( 2, 3 ) + m( 4, 3 ),
+							 m( 2, 4 ) + m( 4, 4 ) );
+			planes[TOP].setCoefficients(  
+							-m( 2, 1 ) + m( 4, 1 ),
+							-m( 2, 2 ) + m( 4, 2 ),
+							-m( 2, 3 ) + m( 4, 3 ),
+							-m( 2, 4 ) + m( 4, 4 ) );
+			planes[LEFT].setCoefficients(  
+							 m( 1, 1 ) + m( 4, 1 ),
+							 m( 1, 2 ) + m( 4, 2 ),
+							 m( 1, 3 ) + m( 4, 3 ),
+							 m( 1, 4 ) + m( 4, 4 ) );
+			planes[RIGHT].setCoefficients(
+							-m( 1, 1 ) + m( 4, 1 ),
+							-m( 1, 2 ) + m( 4, 2 ),
+							-m( 1, 3 ) + m( 4, 3 ),
+							-m( 1, 4 ) + m( 4, 4 ) );
+		}
+		
+	protected:
+		Plane		*planes;
+};
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 8319)
@@ -0,0 +1,172 @@
+
+#include "terrain.h"
+#include "terrain_page.h"
+#include "glincl.h"
+
+#ifdef HAVE_SDL_SDL_IMAGE_H
+#include <SDL/SDL_image.h>
+#else
+#include <SDL_image.h>
+#endif
+
+void Terrain::build()
+{
+	SDL_Surface *tmpData = IMG_Load( heightmapSource.c_str() );
+ 	if ( !tmpData ) {
+		printf( "sorry, can't load!!!\n" );
+		return;
+	}		
+	
+	heightfield.height = tmpData->h;
+	heightfield.width = tmpData->w;
+	heightfield.pitch = tmpData->pitch;
+	int dataSize = heightfield.pitch*heightfield.height;
+	heightfield.data = new UByte[dataSize];
+	memcpy( heightfield.data, tmpData->pixels, sizeof(UByte)*dataSize );
+	SDL_FreeSurface( tmpData );
+	//TODO: Check for modulo!
+	pagesX = (heightfield.width/(pageSize-1) );
+	pagesZ = (heightfield.height/(pageSize-1) );
+	tex = new Texture( lightmapSource );
+	
+	printf( "creating terrain pages ( %d, %d )...", pagesX, pagesZ );
+	pages = new pTerrainPage[pagesX*pagesZ];	
+	for ( int x = 0; x < pagesX; ++x )
+		for ( int z = 0; z < pagesZ; ++z )
+			pages[z*pagesX+x] = createPage( x, z );
+	printf( "looks good\n" );
+	printf( "creating quad_tree data structure..." );
+	root = createQuadTree( 0, 0, pagesX, pagesZ );
+	activePages = NULL;
+	printf( "looks good\n" );
+}
+
+pTerrainQuad Terrain::createQuadTree( int _x0, int _z0, int _x1, int _z1, int _depth )
+{
+	int _x01 = (_x1+_x0)/2; int _z01 = (_z1+_z0)/2;
+	pTerrainQuad node;
+	if ( _x1-_x0 == 1 ) {
+		node = getPage( _x0, _z0 );
+		node->setChildren( NULL, NULL, NULL, NULL );
+	}
+	else {
+		assert( ( _x0 % 2 ) == 0 ); 
+		assert( ( _x1 % 2 ) == 0 ); 
+		assert( ( _z0 % 2 ) == 0 ); 
+		assert( ( _z1 % 2 ) == 0 );		
+		node = new TerrainQuad( this, _x0, _z0, _x1, _z1 );
+		node->setChildren( 
+			createQuadTree( _x0, _z0, _x01, _z01, _depth+1 ),
+			createQuadTree( _x01, _z0, _x1, _z01, _depth+1 ), 
+			createQuadTree( _x0, _z01, _x01, _z1, _depth+1 ), 
+			createQuadTree( _x01, _z01, _x1, _z1, _depth+1 ) );
+	}
+	node->calculateBounds();
+	return node;
+}
+
+pTerrainPage Terrain::createPage( int _xOffset, int _zOffset ) const
+{
+	pTerrainPage newPage = new TerrainPage( const_cast<Terrain*>( this ), _xOffset, _zOffset );
+	newPage->setScale( scale );	
+	newPage->setPosition( Triple( scale.x*_xOffset, 0.0f, scale.z*_zOffset ) );
+	newPage->calculateErrors();
+	
+	//newPage->calculateMinMax();
+	return newPage;
+}
+
+//TODO: The method could be optimized. We could get rid of the hidePages call
+//		by setting a active flag in every pages that is visible. Then a walk
+//		through the activePages list is sufficient to remove all invisible 
+//		pages.
+void Terrain::determineVisiblePages( pTerrainQuad _node )
+{
+	switch( _node->cull() ) {
+		case Frustum::INTERSECT:
+			//printf( "partially inside frustum\n" );
+			if ( !_node->isChildless() ) {
+				pTerrainQuad *children = _node->getChildren();
+				for ( int i = 0; i < 4; ++i, ++children )
+					determineVisiblePages( *children );
+			}
+			else {
+				showPages( _node->getXOffset(), 
+						   _node->getZOffset(), 1, 1 );
+			}
+			break;
+		case Frustum::INSIDE:
+			//printf( "fully inside frustum\n" );			
+			showPages( _node->getXOffset(), 
+					   _node->getZOffset(), 
+					   _node->getWidth() , 
+					   _node->getHeight() );
+			break;
+		case Frustum::OUTSIDE:
+			cullCount+= (_node->getWidth()-1)*(_node->getHeight()-1);
+			break;
+	}
+}
+
+void Terrain::draw( )
+{
+	pTerrainPage page = NULL;
+	
+	frustum->extractPlanes();
+	
+	glEnableClientState( GL_VERTEX_ARRAY );
+	glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 
+	glEnable( GL_TEXTURE_2D );
+	glEnable( GL_DEPTH_TEST );
+	glEnable( GL_CULL_FACE );
+
+	
+	glBindTexture( GL_TEXTURE_2D, tex->getTexture() );
+	glDisable( GL_LIGHTING );
+
+	glEnable( GL_COLOR_MATERIAL );
+	glColor3f( 1.0f, 1.0f, 1.0f );
+	cullCount = 0;
+	
+	// Lets see which pages are visible.
+	determineVisiblePages( root );
+		
+	int count = 0;
+	page = activePages;	
+	
+	while ( page ) {
+		if ( !page->isActive() ) {
+			pTerrainPage tmp = page;
+			page = tmp->getNext();
+			tmp->deactivate();
+			continue;
+		}	
+		count++;
+		page->updateTesselation();
+		//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...
+		page->draw();
+		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;
+	//printf( "culled %f%% terrain pages away\n",  percentage );
+}
+
+void Terrain::getAltitude( Triple& _alt, Triple& _normal )
+{
+	
+}
+
+void Terrain::showPages( int _x0, int _z0, int _width, int _height )
+{
+	for ( int x = 0; x < _width; ++x ) {
+		for ( int z = 0; z < _height; ++z ) {
+			pTerrainPage page = getPage( _x0+x, _z0+z );
+			page->chooseLOD( );
+			page->show( );
+		}
+	}
+}
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 8319)
@@ -0,0 +1,187 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+
+ */
+
+#ifndef _TERRAIN_H
+#define _TERRAIN_H
+
+#include "types.h"
+#include "terrain_page.h"
+#include "terrain_quad.h"
+#include <cstdlib>
+#include <string>
+#include "texture.h"
+#include "frustum.h"
+
+
+typedef struct {
+	int 		width;
+	int 		height;
+	int			pitch;
+	UByte		*data;
+} Heightfield, *pHeightfield;
+
+class Terrain;
+typedef Terrain *pTerrain;
+
+class TerrainPage;
+
+class Terrain {
+	public:
+	
+		/**
+		 * The amount of geometry rendered is largely depending on this constant. So chose a
+		 * reasonable value...
+		 */
+		inline float getDetail() { return 0.05f; }
+
+	
+		inline bool debug()
+		{
+			return false;
+		}
+		
+		inline pTerrainPage getActiveList() { return activePages; }
+
+	
+		inline void setCameraPosition( const Triple& _cameraPosition ) 
+		{ 
+			cameraPosition = _cameraPosition; 
+		}
+		
+		inline const Triple& getCameraPosition() const
+		{
+			return cameraPosition;
+		}
+	
+		void getAltitude( Triple& _alt, Triple& _normal );
+		void showPages( int _x0, int _z0, int _width, int _height );
+					
+		/**
+		 * Create a new terrain.
+		 */
+		Terrain( )
+		{ 
+			pageSize = 17;
+			scale  = Triple( 1.0f, 3.0f, 1.0f );
+			frustum = new Frustum();
+			activatedCount = deactivatedCount = 0;
+		}
+		
+		/**
+		 * Draws the terrain.
+		 */
+		void draw( );
+
+		void setPageSize( const Triple& _page ) { }
+		
+		void build();
+		
+		inline void setActiveList( pTerrainPage _page )
+		{
+			activePages = _page;
+		}
+		inline pFrustum getViewingFrustum()
+		{
+			return frustum;
+		}
+		
+		/**
+		 * Returns the normalized ( range from [0..1] ) altitude from the heightmap for the given 
+		 * coordinates.
+		 */
+		inline void incActivated() { activatedCount++; }
+		inline void incDeactivated() { deactivatedCount++; }
+		inline float getAltitude( int _x, int _z ) const;
+		
+		inline void setLightmap( std::string &_lightmap )
+		{
+			lightmapSource = _lightmap;
+		}
+		inline void setHeightmap( std::string &_heightmap ) 
+		{ 
+			heightmapSource = _heightmap; 
+		}
+		
+		inline void setPageSize( int _pageSize )
+		{
+			pageSize = _pageSize;
+		}
+		
+		inline const Triple getScale() const { return scale; }
+		inline int getPageSize() const 
+		{
+			return pageSize;
+		}
+		inline void getCoord( int _x, int _z, TexCoord& _coord) const
+		{
+			_coord.u = ( ( float )_x )/( heightfield.width-1 );
+			_coord.v = ( ( float )_z )/( heightfield.height-1 );			
+		}
+		
+		inline void setScale( const Triple& _scale )
+		{
+			scale = _scale;
+		}
+		
+		inline TerrainPage *getPage( int _x, int _z )
+		{
+			return pages[pagesX*_z+_x];
+		}
+	protected:
+			
+		/**
+		 * convenience method to create a new terrain page at position offset
+		 * p = ( _xOffset, _zOffset ). 
+		 */
+		pTerrainPage createPage( int _xOffset, int _zOffset ) const;				
+		
+		/**
+		 * Creates the quad tree structure for fast culling of the terrain pages.
+		 */		
+		pTerrainQuad createQuadTree( int _x0, int _z0, int _x1, int _z1, int _depth = 0 );
+		
+		/**
+		 * Walks the quad tree to determine which pages are visible, e.g. are in the viewing
+		 * frustum of the camera.
+		 */
+		void determineVisiblePages( pTerrainQuad _node );						
+		
+		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;
+};
+
+inline float Terrain::getAltitude( int _x, int _z ) const
+{
+	if ( _x > heightfield.width || _z > heightfield.height )
+		return 0.0f;
+	return heightfield.data[heightfield.pitch*_z+_x]/255.0f;	
+}
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 8319)
@@ -0,0 +1,321 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+#include "terrain_page.h"
+#include "terrain.h"
+#include "glincl.h"
+#include <stdio.h>
+#include <math.h>
+
+#define CHECK_GL_ERROR() do { \
+	GLenum __err = glGetError(); \
+	if ( __err != GL_NO_ERROR ) \
+		printf( (char*)gluErrorString( __err ) );\
+	}\
+	while ( 0 )
+
+TerrainPage::TerrainPage( Terrain *_owner, int _xOffset, int _zOffset )
+: TerrainQuad( _owner, _xOffset, _zOffset )
+{
+	scale = owner->getScale();
+	numVertices = numIndices = 0;
+	errors = new LODError[TerrainPage::MAX_LODS];
+	vertices = NULL; indices = NULL; coords = NULL;
+	position = Triple( scale.x*_xOffset, 0.0f, scale.z*_zOffset );
+	isVisible = false;
+	next = NULL;
+	active = false;
+	previous = NULL;
+	currentLOD = -1;
+	forceTesselation = true;
+}
+
+int TerrainPage::chooseLOD()
+{
+	wantedLOD = -1;
+	Triple cam( owner->getCameraPosition() );
+	
+	for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) {
+		Triple distance( cam.x-errors[i].correct.x,
+						 cam.y-errors[i].correct.y,
+						 cam.z-errors[i].correct.z );
+		
+		float d = distance.length();
+		
+		assert( d > 0.000001f );
+		float err =  errors[i].diff / d ;
+		
+		if ( err*scale.y < owner->getDetail() ) {
+			wantedLOD = i;
+			break;
+		}	
+	}
+	if ( wantedLOD < 0 ) {
+		wantedLOD = TerrainPage::MAX_LODS-1;
+	}	
+	
+	return wantedLOD;
+}
+
+void TerrainPage::activate()
+{
+	pTerrainPage list = owner->getActiveList();
+	next = list;
+	if ( list )
+		list->previous = this;
+	owner->incActivated();
+	owner->setActiveList( this );
+}
+
+void TerrainPage::deactivate()
+{
+	pTerrainPage list = owner->getActiveList();
+	
+	if ( previous ) {
+		previous->next = next;
+	}
+	if ( next ) {
+		next->previous = previous;
+	}
+	if ( list == this )
+		owner->setActiveList( next );
+	next = NULL;
+	owner->incDeactivated();
+	previous = NULL;
+	
+}
+
+void TerrainPage::calculateError( int _lod )
+{
+	float	sumError = 0.0f;
+	int		numErrors = 0;
+	int size = owner->getPageSize();
+	if( _lod!=0 )
+	{
+		int pow = 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++ )
+					{
+						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	height00 = getAltitude( x0, y0 ),
+								height10 = getAltitude( x0+pow,y0 ),
+								height01 = getAltitude( x0,y0+pow ),
+								height11 = getAltitude( x0+pow, y0+pow );
+						
+						float	paintHeight =	fx1*fy1 * height00 +
+							fx0*fy1 * height10 +
+							fx1*fy0 * height01 +
+							fx0*fy0 * height11,
+							correctHeight =  getAltitude( x, y );
+						
+						float	er = ( float )fabs( correctHeight - paintHeight );
+						
+						numErrors++;
+						sumError += er;
+					}
+				}
+			}
+		}
+		float error = sumError / numErrors;
+		getVertex(size/2, size/2, errors[_lod].correct);
+		errors[_lod].real = errors[_lod].correct;
+		errors[_lod].real.y += error;
+		errors[_lod].diff = error;
+	}
+}
+
+void TerrainPage::calculateBounds()
+{
+	int size = owner->getPageSize();
+	float alt = 0.0f;
+	
+	Triple	min( xOffset*scale.x ,0.0f, zOffset*scale.z ), 
+			max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z);
+	
+	min.y = max.y = getAltitude( 0, 0 );
+	for ( int x = 0; x < size; ++x ) {
+		for ( int z = 0; z < size; ++z ) {
+			alt = getAltitude( x, z );
+			min.y = fmin( min.y, alt );
+			max.y = fmax( max.y, alt );
+		}
+	}
+	bounds.set( min, max );
+}
+
+float TerrainPage::getAltitude( int _x, int _z ) const
+{
+	assert( _x >= 0 && _x < 17 );
+	assert( _z >= 0 && _z < 17 );
+	return position.y+scale.y*owner->getAltitude( 
+			_x+(owner->getPageSize()-1)*xOffset, 
+			_z+(owner->getPageSize()-1)*zOffset );
+}
+
+void TerrainPage::updateTesselation( )
+{
+	currentLOD = wantedLOD;
+	if ( forceTesselation || currentLOD != currentLOD ) {
+		tesselate( currentLOD );
+	}	
+
+	forceTesselation = false;
+}
+
+/**
+ * Genererates a tesselation for the given _lod. 
+ */
+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 ) );
+		}
+	}
+}
+
+
+void TerrainPage::show( )
+{
+	int count = owner->getPageSize()*owner->getPageSize();
+	
+	vertices = new Triple[count];
+	// Not the economical way, but we just want to have space for all indices.
+	indices = new unsigned short[count*3];
+	indexHash = new unsigned short[count];	
+	coords = new TexCoord[count];
+	forceTesselation = true;
+	activate();
+	active = true;
+}
+
+void TerrainPage::hide( )
+{
+	if ( vertices ) {
+		delete[] vertices;
+		vertices = NULL;
+	}
+	delete[] coords;	
+	if ( indices ) {
+		delete[] indices;
+		indices = NULL;
+		numIndices = 0;
+	}
+	deactivate();
+}
+
+void TerrainPage::drawBox()
+{
+	glMatrixMode( GL_MODELVIEW );
+	glPushMatrix();
+	glTranslatef( bounds.corner.x, bounds.corner.y, bounds.corner.z );
+	glBegin( GL_QUADS );
+		glVertex3f( 0.0f, 0.0f, 0.0f );
+		glVertex3f(  bounds.x, 0.0f, 0.0f );
+		glVertex3f( bounds.x, bounds.y, 0.0f );
+		glVertex3f( 0.0f, bounds.y, 0.0f );
+		
+		glVertex3f( 0.0f, 0.0f, bounds.z );
+		glVertex3f(  bounds.x, 0.0f, bounds.z );
+		glVertex3f( bounds.x, bounds.y, bounds.z );
+		glVertex3f( 0.0f, bounds.y, bounds.z );		
+		
+		glVertex3f( 0.0f, 0.0f, 0.0 );
+		glVertex3f(  0.0, 0.0f, bounds.z );
+		glVertex3f( 0.0f, bounds.y, bounds.z );
+		glVertex3f( 0.0f, bounds.y, 0.0f );				
+		
+		glVertex3f( bounds.x, 0.0f, 0.0 );
+		glVertex3f(  bounds.x, 0.0f, bounds.z );
+		glVertex3f( bounds.x, bounds.y, bounds.z );
+		glVertex3f( bounds.x, bounds.y, 0.0f );						
+	glEnd();
+	glPopMatrix();
+}
+
+void TerrainPage::draw( )
+{
+	
+	assert( glIsEnabled( GL_VERTEX_ARRAY ) );
+	assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
+	assert( isVisible ); assert( numIndices );
+	active = false;
+	glVertexPointer( 3, GL_FLOAT, 0, vertices );
+	glTexCoordPointer( 2, GL_FLOAT, 0, coords );	
+	glDrawElements( GL_TRIANGLE_STRIP, numIndices, 
+					GL_UNSIGNED_SHORT, indices );
+	
+	if ( owner->debug() )
+		drawBox( );
+	
+	CHECK_GL_ERROR();
+}
+
+short TerrainPage::getIndex( int _x, int _z )
+{
+	unsigned short index = _z*owner->getPageSize()+_x;
+	if ( indexHash[index] == 0xffff ) {
+		//The vertex didn't exists before, lets create it.
+		indexHash[index] = numVertices;
+		getVertex( _x, _z, vertices[numVertices] );
+		getCoord( _x, _z, coords[numVertices] );
+		numVertices++;
+	}
+	return indexHash[index];
+}
+
+void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const 
+{
+	owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ), 
+					 _z+zOffset*(owner->getPageSize()-1 ), _coord );
+}
+
+void TerrainPage::getVertex( int _x, int _z, Triple& _vertex ) const
+{
+	_vertex.x = position.x+scale.x*_x/
+		( owner->getPageSize()-1 );
+	_vertex.y = getAltitude( _x, _z );
+	_vertex.z = position.z+scale.z*_z/( owner->getPageSize()-1 );
+}
+
+void TerrainPage::calculateErrors()
+{
+	for ( int i = 0; i < TerrainPage::MAX_LODS; ++i )
+		calculateError( i );
+}
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 8319)
@@ -0,0 +1,218 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+
+
+#ifndef TERRAIN_PAGE_H
+#define TERRAIN_PAGE_H
+
+#include "terrain_quad.h"
+#include <stdio.h>
+
+
+class TerrainPage;
+class Terrain;
+
+typedef TerrainPage *pTerrainPage;
+
+typedef struct {
+	Triple	correct;
+	Triple	real;
+	float	diff;
+} LODError, *pLODError;
+
+class TerrainPage : public TerrainQuad {
+	public:
+		const static int MAX_LODS = 5;
+		/**
+		 * Creates a new terrain page with its lower left corner set
+		 * to C = ( _xOffset, _zOffset ), where the two values specify
+		 * the offset in the height-map.
+		 * The size of the page, as well as the scaling factors are read
+		 * from the _owner terrain page.
+		 */
+		TerrainPage( Terrain *_owner, int _xOffset, int _zOffset );
+		
+		inline bool isActive() { return active; }
+		~TerrainPage( )
+		{ 
+			if ( isVisible )
+				hide(); 
+		}
+		
+		/**
+		 * Makes the terrain look as if it were created with the given level of 
+		 * detail.
+		 */
+		void mimick( int _level ) {}
+		
+		void drawBox();
+		virtual void calculateBounds();		
+		/**
+		 * Sets the visibility to _flag. If the visibility changed, the vertex and index
+		 * arrays are allocated or freed, respectively.
+		 */
+		inline void setVisibility( bool _flag );
+
+		/**
+		 * If
+		 */
+		void show( );
+		void hide( ); 
+		/**
+		 * 
+		 */
+		void updateTesselation( );
+		
+		/**
+		 * Returns the current tesselation level.
+		 */
+		int getLOD() { return currentLOD; }
+		
+		/**
+		 * Returns the curren tween factor. This is a number between 0.0f and 1.0f
+		 */
+		float getTween() { return 0.0f; }
+		
+		/**
+		 * Determines the new LOD which should be used by this terrain page based on
+		 * the distance from the camera. 
+		 * Note: 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.
+		 */
+		int chooseLOD();
+		/**
+		 * If the terrain pages tesselation level changed between the last and the
+		 * current frame, this function returns true, else you'll get false as the
+		 * return value.
+		 */
+		bool isDirty() { return true; }
+		
+		/**
+		 * Calculates the maximal errors for every LOD.
+		 */
+		void calculateErrors();
+		
+		/**
+		 * Calculates the error for the given LOD. We just need to know the "worst"
+		 * vertex for choosing an appropriate LOD.
+		 */
+		void calculateError( int _lod );
+		/**
+		 * Tests if the terrain page would cull against the viewing frustum.
+		 */
+		bool cull( );
+		
+		void calculateMinMax();
+		
+		/**
+		 * Sets the neighbors of this terrain page. pass null if a neighbor if this
+		 * pages is at the border.
+		 */
+		inline void setNeighbors( pTerrainPage _left, pTerrainPage _right, 
+			pTerrainPage _top, pTerrainPage _bottom )
+		{
+			left = _left; right = _right; top = _top; bottom = _bottom;
+		}
+		inline void setPosition( const Triple& _pos )
+		{
+			position.x = _pos.x;
+			position.y = _pos.y;
+			position.z = _pos.z;
+		}
+		
+		/**
+		 *  Does what exactly what the name says and nothing more.
+		 */
+		void draw( );
+		
+		inline pTerrainPage getNext() { return next; }
+		inline pTerrainPage getPrevious() { return previous; }			
+		inline int getWantedLOD() { return wantedLOD; }
+		void deactivate();
+		void activate();		
+		protected:
+			
+			inline void addIndex( unsigned short _index );
+	
+			inline void addAgain();
+			
+			void getCoord( int _x, int _z, TexCoord& _coord) const;
+			/** 
+			 * Fills _vertex with the vertex information at index.
+			 */
+			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. 
+			*/			
+			short getIndex( int _x, int _z );
+			
+		   /**
+			* Generates the tesselation for the given level of detail.
+			*/
+			void tesselate( int _lod );			
+			
+			float getAltitude( int _x, int _z ) const;
+			
+			int							currentLOD,
+										wantedLOD;
+			pTerrainPage 				left, 
+										right,
+										top,
+										bottom;
+			bool						forceTesselation;
+			bool						active;
+			Triple						*vertices;
+			unsigned short				*indices;
+			unsigned short				*indexHash;
+			TexCoord					*coords;
+			int							numIndices;
+			int							numVertices;
+			bool						isVisible;
+			pTerrainPage				next;
+			pTerrainPage				previous;
+			LODError					*errors;
+			Triple						position;
+};
+
+inline void TerrainPage::setVisibility( bool _flag )
+{
+	if ( _flag ) {
+		if ( !isVisible ) {
+			isVisible = true;
+			show( );
+		}
+	}
+	else {
+		if ( isVisible ) {
+			isVisible = false;
+			hide( );
+		}
+	}
+}
+
+inline void TerrainPage::addIndex( unsigned short _index )
+{
+	indices[numIndices] = _index; numIndices++;
+}
+
+inline void TerrainPage::addAgain() 
+{ 
+	indices[numIndices] = indices[numIndices-1]; numIndices++;				
+}
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.cc	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.cc	(revision 8319)
@@ -0,0 +1,56 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+#include "terrain_quad.h"
+#include "terrain.h"
+#include <math.h>
+
+TerrainQuad::TerrainQuad( Terrain *_owner, int _xOffset, int _zOffset )
+: owner( _owner ), xOffset( _xOffset ), zOffset( _zOffset ), width( 1 ), height( 1 )
+{
+	scale = owner->getScale();
+}
+
+TerrainQuad::TerrainQuad( Terrain *_owner, int _x0, int _z0, int _x1, int _z1 )
+:	owner( _owner ), xOffset( _x0 ), zOffset( _z0 ), 
+width( _x1-_x0 ), height( _z1-_z0 )
+{
+	//printf( "%d, %d, %d, %d\n", xOffset, zOffset, width, height );
+	scale = owner->getScale();
+}
+
+int TerrainQuad::cull()
+{
+	return owner->getViewingFrustum()->boxInFrustum( bounds );
+}
+
+/** 
+ * Recalculate the bounds of this TerrainQuad. It could be optimized, but how
+ * often is this method really used?
+ */
+void TerrainQuad::calculateBounds()
+{
+	if ( isChildless() ) {
+		printf( "Cannot calculate bounds for a childless terrain quad.\n" );
+		exit( 0 );
+	}	
+	Triple min = Triple( children[BL_CHILD]->getBounds().min() );
+	Triple max = Triple( children[TR_CHILD]->getBounds().max() );
+	for ( int i = 1; i < 4; ++i ) {
+		pTerrainQuad child = children[i];
+		min.y = fmin( child->bounds.min().y, min.y );
+		max.y = fmax( child->bounds.max().y, max.y );		
+	}
+	bounds.set( min, max );
+}
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h	(revision 8319)
@@ -0,0 +1,100 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+#ifndef _TERRAIN_QUAD_TREE_H
+#define _TERRAIN_QUAD_TREE_H
+
+#include "types.h"
+#include "frustum.h"
+#include <stdio.h>
+class Terrain;
+class TerrainQuad;
+typedef TerrainQuad *pTerrainQuad;
+
+typedef enum { TL_CHILD = 0, TR_CHILD = 1, BL_CHILD = 2, BR_CHILD = 3 } TerrainQuadChild;
+	
+class TerrainQuad {
+	public:
+		TerrainQuad( Terrain *_owner, int _xOffset, int _zOffset );
+		TerrainQuad( Terrain *_owner, int _x0, int _z0, int _x1, int _z1 );
+		
+		virtual ~TerrainQuad( ) 
+		{
+			for ( int i = 0; i < 4; ++i )
+				if ( children[i] != NULL )
+					delete children[i];					
+		}
+		int cull( );
+		
+		/**
+		 * Returns the array containing the children quad-nodes of this node in the following
+		 * order: top-left, top-right, bottom-left, bottom-right
+		 */
+		inline pTerrainQuad* getChildren( ) 
+		{ 
+			return children; 
+		}
+		
+		/**
+		 * Sets the child-nodes to the specified _children elements.
+		 */
+		void setChildren( pTerrainQuad _children[] )
+		{
+			for ( int i = 0; i < 4; ++i )
+				children[i] = _children[i];
+		}
+		
+		inline bool isChildless() { return ( children[0] == NULL ); }
+		
+		/**
+		 * Returns the child node given by _child. The returned node may be null.
+		 */
+		inline pTerrainQuad getChild( TerrainQuadChild _child ) 
+		{ 
+			return children[_child]; 
+		}
+		inline void setScale( Triple _scale )
+		{
+			scale = _scale;
+		}
+		inline const ABox getBounds() { return bounds; }
+		inline void setChildren( pTerrainQuad _bl, pTerrainQuad _br, pTerrainQuad _tl,
+			pTerrainQuad _tr )
+		{
+			children[TL_CHILD] = _tl;
+			children[TR_CHILD] = _tr;
+			children[BR_CHILD] = _br;
+			children[BL_CHILD] = _bl;
+		}
+		/**
+		 * Calculates the mininum and maximum value of this box based on the size
+		 * and position of its children.
+		 */
+		virtual void calculateBounds( );
+		inline int getXOffset() { return xOffset; }
+		inline int getZOffset() { return zOffset; }
+		inline int getWidth() { return width; }
+		inline int getHeight() { return height; }
+		
+	protected:
+		TerrainQuad( ) {}
+		Terrain			*owner;
+		int				xOffset, zOffset;
+		int				width,	height;
+		Triple			scale;
+		pTerrainQuad 	children[4];
+		ABox			bounds;
+};
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/types.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/types.h	(revision 8319)
+++ branches/terrain/src/lib/graphics/importer/terrain/types.h	(revision 8319)
@@ -0,0 +1,141 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 	This files needs to be removed after code-revision...
+ */
+#ifndef TYPES_H
+#define TYPES_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+#include <math.h>
+
+
+struct Triple {
+	Triple( float _x, float _y, float _z ) 
+	{ 
+		x = _x; y = _y; z = _z; 
+	}
+	Triple() { x = y = z = 0.0f; }
+	inline float length() const
+	{ return sqrt( x*x+y*y+z*z ); } 
+	float x, y, z;
+};
+
+struct TexCoord {
+	TexCoord( float _u, float _v )
+	{
+		u = _u; v = _v;
+	}
+	TexCoord() { u = v = 0.0f; }
+	float u, v;
+};
+
+/**
+ * Defines an axis aligned box.
+ */
+struct ABox {
+	
+	ABox( Triple _min, Triple _max)
+	{
+		corner = _min;
+		x = _max.x-_min.x;
+		y = _max.y-_min.y;
+		z = _max.z-_min.z;
+	}
+	
+	ABox() 
+	{
+		corner = Triple( 0.0f, 0.0f, 0.0f );
+		x = y = z = 0.0f;
+	}
+	inline void set( const Triple& _min, const Triple& _max )
+	{
+		setMin( _min ); setMax( _max );
+	}
+	inline void setMax( const Triple& _max )
+	{
+		x = _max.x-corner.x;
+		y = _max.y-corner.y;
+		z = _max.z-corner.z;
+	}
+	inline void setMin( const Triple& _min )
+	{
+		corner = _min;
+	}
+	inline Triple vertexP( const Triple& _normal ) const 
+	{
+		Triple res = corner;
+		if ( _normal.x > 0 )
+			res.x+= x;
+		if ( _normal.y > 0 )
+			res.y+= y;
+		if ( _normal.z > 0 )
+			res.z+= z;			
+			
+		return res;
+	}
+	inline Triple vertexN( const Triple& _normal ) const
+	{		
+		Triple res = corner;
+		if ( _normal.x < 0 )
+			res.x+= x;
+		if ( _normal.y < 0 )
+			res.y+= y;
+		if ( _normal.z < 0 )
+			res.z+= z;			
+			
+		return res;
+	
+	}
+	inline Triple min() const { return Triple(corner); }
+	inline Triple max() const { return Triple( corner.x+x, corner.y+y, corner.z+z ); }
+	Triple corner;
+	float x, y, z;
+	
+};
+
+struct Plane {
+	Plane() { n = Triple( 0.0f, 1.0f, 0.0f ); d = 0.0f; }
+	inline void setCoefficients( float _nx, float _ny, float _nz, float _d )
+	{
+		n = Triple( _nx, _ny, _nz );
+		float l = n.length();
+		n.x /= l; n.y/=l; n.z/=l;
+		d = _d/l;
+	}
+	inline float distance( const Triple& _point ) const
+	{
+		return _point.x*n.x+_point.y*n.y+_point.z*n.z+d;
+	}
+	Triple n;
+	float d;
+};
+
+/**
+ * TODO: Replace this method with the actual matrix multiplication code!
+ */
+inline void multMat(float *res,float *a, float *b) {
+
+
+	for (int i=0;i<4;i++) {
+		for (int j = 0;j < 4;j++) {
+			res[i*4+j] = 0.0;
+			for (int k = 0; k < 4; k++) {
+				res[i*4+j] += a[i*4+k] * b[k*4+j];
+			}
+		}
+	}
+}
+typedef unsigned char UByte;
+#endif
