Index: branches/terrain/src/lib/graphics/effects/volfog_effect.cc
===================================================================
--- branches/terrain/src/lib/graphics/effects/volfog_effect.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/effects/volfog_effect.cc	(revision 9414)
@@ -30,5 +30,5 @@
 //#include <GL/glext.h> //OpenGL Extensions
 //#include <GL/glxext.h> // GLX Extensions
-
+#ifndef __APPLE__
 #ifndef GL_EXT_fog_coord
 #define GL_EXT_fog_coord 1
@@ -45,5 +45,5 @@
 PFNGLFOGCOORDDVEXTPROC glFogCoorddvEXT = 0;
 PFNGLFOGCOORDPOINTEREXTPROC glFogCoordPointerEXT = 0;
-
+#endif
 
 
Index: branches/terrain/src/lib/graphics/graphics_engine.cc
===================================================================
--- branches/terrain/src/lib/graphics/graphics_engine.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/graphics_engine.cc	(revision 9414)
@@ -240,5 +240,6 @@
   // Enable default GL stuff
   glEnable(GL_DEPTH_TEST);
-
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_FRONT);
   Render2D::getInstance();
 
@@ -301,6 +302,5 @@
   }
 
-  glEnable(GL_CULL_FACE);
-  glCullFace(GL_FRONT);
+
 }
 
Index: branches/terrain/src/lib/graphics/importer/Makefile.am
===================================================================
--- branches/terrain/src/lib/graphics/importer/Makefile.am	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/Makefile.am	(revision 9414)
@@ -38,7 +38,11 @@
                            md3/md3_mesh.cc \
                            md3/md3_data.cc \
-                           md3/md3_tag.cc
-
-
+                           md3/md3_tag.cc \
+			   \
+                           terrain/terrain.cc \
+                           terrain/terrain_quad.cc \
+                           terrain/terrain_page.cc \
+                           terrain/frustum.cc \
+                           terrain/buffer_broker.cc
 
 
@@ -81,4 +85,11 @@
                 md3/md3_mesh.h \
                 md3/md3_data.h \
-                md3/md3_tag.h
+                md3/md3_tag.h \
+                \
+		terrain/terrain.h \
+		terrain/terrain_page.h \
+		terrain/terrain_quad.h \
+		terrain/frustum.h \
+		terrain/types.h \
+                terrain/buffer_broker.h
 
Index: branches/terrain/src/lib/graphics/importer/bsp_file.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/bsp_file.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/bsp_file.cc	(revision 9414)
@@ -21,9 +21,9 @@
 #include "bsp_file.h"
 #include "bsp_tree_node.h"
-#include <fstream>
 #include "util/loading/resource_manager.h"
-
+#include <string>
 #include <sys/stat.h>
 #include <string.h>
+#include "filesys/binary_file.h"
 #include "debug.h"
 #include "material.h"
@@ -40,6 +40,17 @@
 #include <vector>
 
-
-
+using namespace std;
+
+static const char* HEADER_SEMANTICS  		= "b4i35";
+static const char* NODE_SEMANTICS  			= "i9";
+static const char* LEAF_SEMANTICS  			= "i12";
+static const char* MODEL_SEMANTICS			= "i10";
+static const char* BRUSH_SEMANTICS  		= "i3";
+static const char* BRUSHSIDE_SEMANTICS  	= "i2";
+static const char* FACE_SEMANTICS  			= "i26";
+static const char* VERTEX_SEMANTICS  		= "i10b4";
+static const char* LIGHTMAP_SEMANTICS 		= "b49152";
+static const char* TEXTURE_SEMANTICS 		= "b64i2";
+static const char* PLANE_SEMANTICS 			= "f4";
 
 // Constructor
@@ -81,5 +92,166 @@
 
 }
-
+void BspFile::readEntities()
+{
+	/* We do nothing here */
+}
+void BspFile::readTextures()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Textures];
+	this->numTextures = lump.length/sizeof(BspTexture);
+	this->textures = new char[lump.length];
+	file.seekg( lump.offset );	
+	file.read( TEXTURE_SEMANTICS, this->numTextures, 
+		this->textures, slurpedBytes );
+}
+void BspFile::readPlanes()
+{	
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Planes];
+	this->numPlanes = lump.length/sizeof(plane);
+	this->planes = new plane[this->numPlanes];
+	file.seekg( lump.offset );
+	file.read( PLANE_SEMANTICS, this->numPlanes, 
+		this->planes, slurpedBytes );
+}
+
+void BspFile::readNodes()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Nodes];
+	this->numNodes = lump.length/sizeof(node);
+	this->nodes = new node[this->numNodes];
+	file.seekg( lump.offset );
+	file.read( NODE_SEMANTICS, this->numNodes, 
+		this->nodes, slurpedBytes );
+}
+
+void BspFile::readLeafs()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Leafs];
+	this->numLeafs = lump.length/sizeof(leaf);
+	this->leaves = new leaf[this->numLeafs];
+	file.seekg( lump.offset );
+	file.read( LEAF_SEMANTICS, this->numLeafs, 
+		this->leaves, slurpedBytes );	
+}
+
+void BspFile::readLeafFaces()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Leaffaces];
+	this->numLeafFaces = lump.length/sizeof(int);
+	this->leafFaces = (char*)( new int[this->numLeafFaces] );
+	file.seekg( lump.offset );
+	file.read( "i", this->numLeafFaces, 
+		this->leafFaces, slurpedBytes );
+}
+
+void BspFile::readLeafBrushes()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Leafbrushes];
+	this->numLeafBrushes = lump.length/sizeof(int);
+	this->leafBrushes = (char*) ( new int[this->numLeafBrushes] );
+	file.seekg( lump.offset );
+	file.read( "i", this->numLeafBrushes, 
+		this->leafBrushes, slurpedBytes );	
+}
+
+void BspFile::readModels()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Models];
+	this->numBspModels = lump.length/sizeof(model);
+	this->bspModels = new model[this->numBspModels];
+	file.seekg( lump.offset );
+	file.read( MODEL_SEMANTICS, this->numBspModels, 
+		this->bspModels, slurpedBytes );
+}
+
+void BspFile::readBrushes()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Brushes];
+	int numBrushes = lump.length/sizeof(brush);
+	this->brushes = new brush[numBrushes];
+	file.seekg( lump.offset );
+	file.read( BRUSH_SEMANTICS, numBrushes, 
+		this->brushes, slurpedBytes );
+}
+void BspFile::readVertices()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Vertices];
+	this->numVertex = lump.length/sizeof(BspVertex);
+	this->vertice = (char*)( new BspVertex[this->numVertex] );
+	file.seekg( lump.offset );
+	file.read( VERTEX_SEMANTICS, this->numVertex, 
+		this->vertice, slurpedBytes );
+}
+
+void BspFile::readMeshVerts()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Meshverts];
+	int num = lump.length / sizeof( meshvert );
+	this->meshverts = new meshvert[num];
+	file.seekg( lump.offset );
+	file.read( "i", num, this->meshverts, slurpedBytes );
+}
+
+void BspFile::readEffects()
+{
+	/* not loaded atm */
+}
+
+void BspFile::readFaces()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Faces];
+	this->numFaces = lump.length/sizeof(face);
+	this->faces = new face[this->numFaces];
+	file.seekg( lump.offset );
+	file.read( FACE_SEMANTICS, this->numFaces, 
+		this->faces, slurpedBytes );
+}
+
+void BspFile::readLightmaps()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Lightmaps];
+	this->numLightMaps = lump.length/sizeof(lightmap);
+	this->lightMaps = new lightmap[this->numLightMaps];
+	file.seekg( lump.offset );
+	file.read( LIGHTMAP_SEMANTICS, this->numLightMaps, 
+		this->lightMaps, slurpedBytes );
+}
+void BspFile::readLightvols()
+{
+	/* not loaded atm */	
+}
+void BspFile::readBrushSides()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Brushsides];
+	this->numBrushSides = lump.length/sizeof(brushside);
+	printf( "numBrushSides: %d\n", numBrushSides );
+	this->brushSides = new brushside[this->numBrushSides];
+	file.seekg( lump.offset );
+	file.read( BRUSHSIDE_SEMANTICS, this->numBrushSides, 
+		this->brushSides, slurpedBytes );
+}
+void BspFile::readVisdata()
+{
+	size_t slurpedBytes;
+	bsp_lump& lump = header.lumps[Visdata];
+	this->visData = new char[lump.length];
+	file.seekg( lump.offset );
+	file.read( "i2", 1, this->visData, slurpedBytes );
+	file.read( "b", lump.length-8, 
+		this->visData+8, slurpedBytes );	
+}
 /**
  *  Loads a quake3 level (*.bsp)
@@ -88,269 +260,111 @@
 int BspFile::read(const char* name)
 {
-  this->scale = 1.0;
-  int offset;
-  int size;
-  struct stat results;
-
-
-  if (stat( name , &results) == 0) {
-    PRINTF(0)("BSP FILE: Datei %s gefunden. \n", name);
-    std::ifstream bspFile (name, std::ios::in | std::ios::binary);
-    bspFile.read(this->header, 260);
-    PRINTF(0)("BSP FILE: BSPVersion: %i. \n", ((int *)(header) )[1]);
-    if(SDL_SwapLE32(((int *)(header) )[1]) == 46)    PRINTF(0)("BSP FILE: This is the good one! :-)  \n");
-    else  PRINTF(0)("BSP FILE: Wrong BSPVersion.\n");   //!< now, we should do some error handling
-
-    // Get the Nodes
-    offset = SDL_SwapLE32(((int *)(header) )[8]);
-    size    = SDL_SwapLE32(((int *)(header))[9]);
-    PRINTF(4)("BSP FILE: NodeSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumNodes: %i. \n", size / sizeof(node));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(node));
-    PRINTF(4)("BSP FILE: NodeOffset: %i. \n", offset);
-    this->numNodes = size/sizeof(node);
-    this->nodes = new node [this->numNodes];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->nodes, size);
-
-    // and their Planes
-    offset = SDL_SwapLE32(((int *)(header) )[6]);
-    size    = SDL_SwapLE32(((int *)(header))[7]);
-    PRINTF(4)("BSP FILE: PlanesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumPlanes: %i. \n", size / sizeof(plane));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", sizeof(plane));
-    PRINTF(4)("BSP FILE: PlanesOffset: %i. \n", offset);
-    this->numPlanes = size/sizeof(plane);
-    this->planes = new plane [this->numPlanes];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->planes, size);
-
-    // Get the Leafs
-    offset = SDL_SwapLE32(((int *)(header) )[10]);
-    size    = SDL_SwapLE32(((int *)(header))[11]);
-    PRINTF(4)("BSP FILE: LeaveSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumLeaves: %i. \n", size / sizeof(leaf));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(leaf));
-    PRINTF(4)("BSP FILE: LeaveOffset: %i. \n", offset);
-    this->numLeafs = size/sizeof(leaf);
-    this->leaves = new leaf [this->numLeafs];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->leaves, size);
-
-    // Get the Models
-    offset = SDL_SwapLE32(((int *)(header))[16]);
-    size    = SDL_SwapLE32(((int *)(header))[17]);
-    PRINTF(4)("BSP FILE: ModelsSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumModels: %i. \n", size / sizeof(model));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(model));
-    PRINTF(4)("BSP FILE: ModelsOffset: %i. \n", offset);
-    this->numBspModels = size/sizeof(model);
-    this->bspModels = new model [this->numBspModels];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->bspModels, size);
-
-    // Get the leafFaces
-    offset = SDL_SwapLE32(((int *)(header))[12]);
-    size    = SDL_SwapLE32(((int *)(header))[13]);
-    PRINTF(4)("BSP FILE: leafFacesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumleafFaces: %i. \n", size / 4);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 4);
-    PRINTF(4)("BSP FILE: leafFacesOffset: %i. \n", offset);
-    this->numLeafFaces = size/4;
-    this->leafFaces = new char [size];
-    bspFile.seekg(offset);
-    bspFile.read(this->leafFaces, size);
-
-    // Get the leafBrushes
-    offset = SDL_SwapLE32(((int *)(header))[14]);
-    size    = SDL_SwapLE32(((int *)(header))[15]);
-    PRINTF(4)("BSP FILE: leafBrushesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumleafBrushes: %i. \n", size / 4);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 4);
-    PRINTF(4)("BSP FILE: leafBrushesOffset: %i. \n", offset);
-    this->numLeafBrushes = size/4;
-    this->leafBrushes = new char [size];
-    bspFile.seekg(offset);
-    bspFile.read(this->leafBrushes, size);
-
-    // Get the brushes
-    offset = SDL_SwapLE32(((int *)(header))[18]);
-    size    = SDL_SwapLE32(((int *)(header))[19]);
-    PRINTF(4)("BSP FILE: BrushesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumBrushes: %i. \n", size / sizeof(brush));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(brush));
-    PRINTF(4)("BSP FILE: BrushesOffset: %i. \n", offset);
-    this->brushes = new brush [size/sizeof(brush)];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->brushes, size);
-
-    // Get the brushSides
-    offset =   SDL_SwapLE32(((int *)(header))[20]);
-    size    = SDL_SwapLE32(((int *)(header))[21]);
-    PRINTF(4)("BSP FILE: BrushSidesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumBrushSides: %i. \n", size / 8);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 8);
-    PRINTF(4)("BSP FILE: BrushSidesOffset: %i. \n", offset);
-    this->numBrushSides = size/sizeof(brushside);
-    this->brushSides = new brushside [this->numBrushSides];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->brushSides, size);
-
-    // Get the Vertice
-    offset = SDL_SwapLE32(((int *)(header))[22]);
-    size    = SDL_SwapLE32(((int *)(header))[23]);
-    PRINTF(4)("BSP FILE: VerticeSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumVertice: %i. \n", size / 44);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 44);
-    PRINTF(4)("BSP FILE: VerticeOffset: %i. \n", offset);
-    this->numVertex = size/44;
-    this->vertice = new char [size];
-    bspFile.seekg(offset);
-    bspFile.read(this->vertice, size);
-
-    // Get the MeshVerts
-    offset = SDL_SwapLE32(((int *)(header))[24]);
-    size    = SDL_SwapLE32(((int *)(header))[25]);
-    PRINTF(4)("BSP FILE: MeshVertsSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumMeshVerts: %i. \n", size / sizeof(meshvert));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(meshvert));
-    PRINTF(4)("BSP FILE: MeshVertsOffset: %i. \n", offset);
-    this->meshverts = new meshvert [size / sizeof(meshvert)];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->meshverts, size);
-
-    // Get the Faces
-    offset = SDL_SwapLE32(((int *)(header))[28]);
-    size    = SDL_SwapLE32(((int *)(header))[29]);
-    PRINTF(4)("BSP FILE: FacesSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumFaces: %i. \n", size / sizeof(face));
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % sizeof(face));
-    PRINTF(4)("BSP FILE: FacesOffset: %i. \n", offset);
-    this->numFaces = size/sizeof(face);
-    this->faces = new face [this->numFaces];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->faces, size);
-
-    //Get the lightmaps
-    offset = SDL_SwapLE32(((int *)(header))[30]);
-    size    = SDL_SwapLE32(((int *)(header))[31]);
-    this->numLightMaps = size/ sizeof(lightmap);
-    this->lightMaps = new lightmap [this->numLightMaps];
-    bspFile.seekg(offset);
-    bspFile.read((char*)this->lightMaps, size);
-
-
-    // Get the Visdata
-    offset = SDL_SwapLE32(((int *)(header))[34]);
-    size    = SDL_SwapLE32(((int *)(header))[35]);
-
-    this->visData = new char [size];
-    bspFile.seekg(offset);
-    bspFile.read(this->visData, size);
-
-    PRINTF(4)("BSP FILE: VisDataSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumVisData: %i. \n", size /1 - 8);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 1);
-    PRINTF(4)("BSP FILE: VisDataOffset: %i. \n", offset);
-
-    // Get the Textures
-    offset = SDL_SwapLE32(((int *)(header))[4]);
-    size    = SDL_SwapLE32(((int *)(header))[5]);
-
-    this->textures= new char [size];
-    bspFile.seekg(offset);
-    bspFile.read(this->textures, size);
-
-    PRINTF(4)("BSP FILE: TextureSize: %i Bytes. \n", size);
-    PRINTF(4)("BSP FILE: NumTextures: %i. \n", size /72);
-    PRINTF(4)("BSP FILE: Remainder: %i. \n", size % 72);
-    PRINTF(4)("BSP FILE: TextureOffset: %i. \n", offset);
-    this->numTextures = size/72;
-
-    bspFile.close();
-
-    for(int i = 0 ; i < this->numTextures; i++)
-      PRINTF(4)("BSP FILE: Texture 0: %s. \n", &this->textures[8+ 72*i]);
-    this->load_textures();
-
-    // Load the lightMaps
-    this->glLightMapTextures = new GLuint[this->numLightMaps];
-    for(int i = 0; i < this->numLightMaps; i++)
-      this->glLightMapTextures[i] = this->loadLightMapToGL(this->lightMaps[i]);
-
-    //Create white texture for if no lightmap specified
-    glGenTextures(1, &this->whiteLightMap);
-    glBindTexture(GL_TEXTURE_2D, this->whiteLightMap);
-        //Create texture
-    this->whiteTexture[0]=255;
-    this->whiteTexture[1]=255;
-    this->whiteTexture[2]=255;
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_PRIORITY, 2);
-
-
-
-    /* control the mipmap levels */
-    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MIN_LOD, 5);
-    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MAX_LOD, 0);
-
-    /* build the Texture  OpenGL V >= 1.1 */
-    glTexImage2D(GL_TEXTURE_2D,
-                 0,
-                 GL_RGBA8,
-                 1,
-                 1,
-                 0,
-                 GL_RGB,
-                 GL_UNSIGNED_BYTE,
-                 (const GLvoid *)&(this->whiteTexture));
-
-   gluBuild2DMipmaps(   GL_TEXTURE_2D, GL_RGBA8, 1, 1,
-                      GL_RGB, GL_UNSIGNED_BYTE,(const GLvoid *) &(this->whiteTexture));
-
-
-
-    // Get the number of patches
-    this->numPatches = 0;
-    this->patchOffset   = 0;
-
-    for( int i = 0; i < this->numFaces; i++) {
-      face& cFace = ((face *)(this->faces))[i];
-      if (SDL_SwapLE32(cFace.type) == 2)
-        this->numPatches += (SDL_SwapLE32(cFace.size[0]) -1 ) / 2  * (SDL_SwapLE32(cFace.size[1]) -1) / 2;
-    }
-
-    // Allocate Memory
-    this->patchVertice = new char[8*8*44*(this->numPatches+10)];
-    this->patchIndexes = new char[7*8*2*4*(this->numPatches+10)];
- // this->patchRowIndexes = new int*[7*4*this->numPatches]; Not needed?
-    this->patchTrianglesPerRow = new char[7*4*this->numPatches];
-    this->VertexArrayModels  = new VertexArrayModel*[this->numPatches];
-
-    PRINTF(4)("BSP FILE:NumberOfPatches: %i . \n", numPatches);
-
-    this->swapAllBspCoordinates();
-
-    // Do tesselation for all Faces of type 2
-    for( int i = 0; i < this->numFaces; i++) {
-      if (SDL_SwapLE32((this->faces)[i].type) == 2)
-        this->tesselate(i);
-    }
-
-    PRINTF(4)("BSP FILE:PatchOffset: %i . \n", this->patchOffset);
-
-    return  1;
-  } else {
-    PRINTF(4)("BSP FILE: Datei nicht gefunden. \n");
-    return -1;
-  }
-
-
-
+	this->scale = 1.0;
+
+	size_t slurpedBytes;
+	string theBSPFile( name );
+	file.setFileName( theBSPFile );
+	if (file.exists() && file.open( File::ReadOnly ) ) {
+    	PRINTF(0)("BSP FILE: Datei %s gefunden. \n", name);
+    	
+		//BSP-Files have little endian order.
+		file.setByteorder( LittleEndian );
+		file.read( HEADER_SEMANTICS, (void*)&header, slurpedBytes );
+		if ( header.version != 46 ) {
+			PRINTF(0)("BSP FILE: Wrong BSPVersion. We only handle 0x2e-files!\n");   
+			//!< now, we should do some error handling		
+			return ( -1 );
+		}
+		readEntities();
+		readTextures();
+		readPlanes();
+		readNodes();
+		readLeafs(); readLeafFaces(); readLeafBrushes(); 
+		readModels(); 
+		readVertices(); readMeshVerts();
+		readBrushSides(); readBrushes();
+		readEffects();
+		readFaces();
+		readLightmaps(); readLightvols();
+		readVisdata(	
+    	file.close();
+
+	    for(int i = 0 ; i < this->numTextures; i++)
+	    	PRINTF(4)("BSP FILE: Texture 0: %s. \n", &this->textures[8+ 72*i]);
+	    this->load_textures();
+
+	    // Load the lightMaps
+	    this->glLightMapTextures = new GLuint[this->numLightMaps];
+	    for(int i = 0; i < this->numLightMaps; i++)
+	    	this->glLightMapTextures[i] = this->loadLightMapToGL(this->lightMaps[i]);
+
+	    //Create white texture for if no lightmap specified
+	    glGenTextures(1, &this->whiteLightMap);
+	    glBindTexture(GL_TEXTURE_2D, this->whiteLightMap);
+	        //Create texture
+	    this->whiteTexture[0]=255;
+	    this->whiteTexture[1]=255;
+	    this->whiteTexture[2]=255;
+
+	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
+	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_PRIORITY, 2);
+	    /* control the mipmap levels */
+	    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MIN_LOD, 5);
+	    glTexParameterf(GL_TEXTURE_ENV, GL_TEXTURE_MAX_LOD, 0);
+
+	    /* build the Texture  OpenGL V >= 1.1 */
+	    glTexImage2D(GL_TEXTURE_2D,
+	                 0,
+	                 GL_RGBA8,
+	                 1,
+	                 1,
+	                 0,
+	                 GL_RGB,
+	                 GL_UNSIGNED_BYTE,
+	                 (const GLvoid *)&(this->whiteTexture));
+
+	   gluBuild2DMipmaps(   GL_TEXTURE_2D, GL_RGBA8, 1, 1,
+	                      GL_RGB, GL_UNSIGNED_BYTE,(const GLvoid *) &(this->whiteTexture));
+
+
+
+	    // Get the number of patches
+	    this->numPatches = 0;
+	    this->patchOffset   = 0;
+
+	    for( int i = 0; i < this->numFaces; i++) {
+	      face& cFace = ((face *)(this->faces))[i];
+	      if ( cFace.type  == 2)
+	        this->numPatches += ( cFace.size[0] -1 ) / 2  * ( cFace.size[1] -1 ) / 2;
+	    }
+
+	    // Allocate Memory
+	    this->patchVertice = new char[8*8*44*(this->numPatches+10)];
+	    this->patchIndexes = new char[7*8*2*4*(this->numPatches+10)];
+	 // this->patchRowIndexes = new int*[7*4*this->numPatches]; Not needed?
+	    this->patchTrianglesPerRow = new char[7*4*this->numPatches];
+	    this->VertexArrayModels  = new VertexArrayModel*[this->numPatches];
+
+	    PRINTF(4)("BSP FILE:NumberOfPatches: %i . \n", numPatches);
+
+	    this->swapAllBspCoordinates();
+
+	    // Do tesselation for all Faces of type 2
+	    for( int i = 0; i < this->numFaces; i++) {
+	      if (  (this->faces)[i].type  == 2)
+	        this->tesselate(i);
+	    }
+
+	    PRINTF(4)("BSP FILE:PatchOffset: %i . \n", this->patchOffset);
+
+	    return  1;
+  	} else {
+    	PRINTF(0)("BSP FILE: Datei nicht gefunden. \n");
+    	return -1;
+  	}
 }
 
@@ -430,5 +444,5 @@
   char fileName [500];
   char ext [500];
-  struct stat results;
+  //struct stat results;
 
 
@@ -660,7 +674,7 @@
   int      errorCode = 0;           //!< the error code for the texture loading functions
   unsigned int   lightMap;          //!< the OpenGL texture handle
-  int      mipmapLevel = 0;         //!< the maximum mipmap level for this texture
+ /* int      mipmapLevel = 0;         //!< the maximum mipmap level for this texture
   int      mipmapWidth = 0;         //!< the width of the mipmap
-  int      mipmapHight = 0;         //!< the height of the mipmap3
+  int      mipmapHight = 0;         //!< the height of the mipmap3*/
   float sc, scale, temp;
   for(int i = 0; i < 128*128*3 ; i++)
Index: branches/terrain/src/lib/graphics/importer/bsp_file.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/bsp_file.h	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/bsp_file.h	(revision 9414)
@@ -19,4 +19,5 @@
 
 #include <vector>
+#include "filesys/binary_file.h"
 class SDL_Surface;
 class BspTreeNode;
@@ -27,5 +28,38 @@
 
 
- struct plane
+struct bsp_lump {
+	int			offset;
+	int			length;
+};
+
+enum bsp_lumps {
+	Entities	 	=      0,
+	Textures	 	=      1,
+	Planes 			=      2,
+	Nodes		  	=      3,
+	Leafs		  	=      4,
+	Leaffaces	 	=      5,
+	Leafbrushes		=      6,
+	Models	 		=      7,
+	Brushes	 		=      8,
+	Brushsides		=      9,
+	Vertices	 	=     10,
+	Meshverts	 	=     11,
+	Effects		 	=     12,
+	Faces	 		=     13,
+	Lightmaps	 	=     14,
+	Lightvols	 	=     15,
+	Visdata			=     16
+};
+
+struct bsp_header {
+	// The magic number always "IBSP"
+	char		magic[4];
+	// The version, 0x2e for quake 3 models 
+	int			version;
+	bsp_lump	lumps[17];
+};
+
+struct plane
 {
   float x;     //!< 1st component of the plane's normal
@@ -34,4 +68,5 @@
   float d;     //!< distance of the plane to the origin
 };
+
 
 typedef struct
@@ -82,4 +117,5 @@
 }
 brushside;
+
 
 struct face
@@ -101,4 +137,5 @@
 } ;
 
+
 typedef struct
 {
@@ -130,5 +167,4 @@
 }
 AMat;
-
 typedef struct
 {
@@ -144,4 +180,5 @@
 }
 BspTexture;
+
 
 class BspFile
@@ -162,57 +199,75 @@
 
 private:
-  BspTreeNode* root;
-  char header [ 280 ];       //!< Buffer for header of BSP-File
-  node* nodes;               //!< Buffer to store BSP-Tree-Nodes
-  leaf* leaves;              //!< Buffer to store BSP-Tree-Leaves
-  plane* planes;             //!< Buffer to store planes separateing the space
-  model* bspModels;          //!< Buffer to store BSP-Model-List
-  char* leafFaces;           //!< Buffer to store leafFaces
-  face* faces;               //!<
-  char* leafBrushes;         //!< Buffer to store brush indice
-  brush* brushes;            //!< Buffer to store  brushes
-  brushside* brushSides;     //!<
-  char* vertice;             //!<
-  meshvert* meshverts;       //!< Buffer to store meshverice
-  char* visData;             //!< Buffer to store visibility data
-  char* textures;            //!< Holds all the texture filename strings
-  char* patchVertice;        //!<
-  char* patchIndexes;
-  char* patchTrianglesPerRow;
-  lightmap* lightMaps;       //!< Buffer to store lightmap-images
-
-
-  int** patchRowIndexes;
-  VertexArrayModel** VertexArrayModels; 
-  int patchOffset;
-
-  int numNodes;
-  int numLeafs;
-  int numVertex;
-  int numPlanes;
-  int numBspModels;
-  int numLeafFaces;
-  int numFaces;
-  int numLeafBrushes;
-  int numTextures;
-  int numPatches;
-  int numBrushSides;
-  int numLightMaps;
-  
-  float  scale;
-
-  BspTreeNode* build_tree_rec( int i );
-  unsigned int loadLightMapToGL(lightmap&);
-  AMat* Materials;
-  unsigned int* glLightMapTextures;
-  unsigned int whiteLightMap;
-  unsigned char whiteTexture[3];
-  void swapAllBspCoordinates();
-  void swapCoords(int * array);
-  void swapCoords(float * array);
-  SDL_Surface* testSurf;
-
- 
-  ::std::vector<MoviePlayer* > MovieMaterials; //!< Movieplayer Materials
-};
-
+	void readEntities();
+	void readTextures();
+	void readPlanes();
+	void readNodes();
+	void readLeafs();
+	void readLeafFaces();
+	void readLeafBrushes();
+	void readBrushSides();
+	void readModels();
+	void readBrushes();
+	void readVertices();
+	void readMeshVerts();
+	void readEffects();
+	void readFaces();
+	void readLightmaps();
+	void readLightvols();
+	void readVisdata();
+  	BinaryFile file;
+	BspTreeNode* root;
+	bsp_header header;       	 //!< Buffer for header of BSP-File
+	node* nodes;               //!< Buffer to store BSP-Tree-Nodes
+	leaf* leaves;              //!< Buffer to store BSP-Tree-Leaves
+	plane* planes;             //!< Buffer to store planes separateing the space
+	model* bspModels;          //!< Buffer to store BSP-Model-List
+	char* leafFaces;           //!< Buffer to store leafFaces
+	face* faces;               //!<
+	char* leafBrushes;         //!< Buffer to store brush indice
+	brush* brushes;            //!< Buffer to store  brushes
+	brushside* brushSides;     //!<
+	char* vertice;             //!<
+	meshvert* meshverts;       //!< Buffer to store meshverice
+	char* visData;             //!< Buffer to store visibility data
+	char* textures;            //!< Holds all the texture filename strings
+	char* patchVertice;        //!<
+	char* patchIndexes;
+	char* patchTrianglesPerRow;
+	lightmap* lightMaps;       //!< Buffer to store lightmap-images
+
+
+	int** patchRowIndexes;
+	VertexArrayModel** VertexArrayModels; 
+	int patchOffset;
+
+	int numNodes;
+	int numLeafs;
+	int numVertex;
+	int numPlanes;
+	int numBspModels;
+	int numLeafFaces;
+	int numFaces;
+	int numLeafBrushes;
+	int numTextures;
+	int numPatches;
+	int numBrushSides;
+	int numLightMaps;
+
+	float  scale;
+
+	BspTreeNode* build_tree_rec( int i );
+	unsigned int loadLightMapToGL(lightmap&);
+	AMat* Materials;
+	unsigned int* glLightMapTextures;
+	unsigned int whiteLightMap;
+	unsigned char whiteTexture[3];
+	void swapAllBspCoordinates();
+	void swapCoords(int * array);
+	void swapCoords(float * array);
+	SDL_Surface* testSurf;
+
+
+	::std::vector<MoviePlayer* > MovieMaterials; //!< Movieplayer Materials
+};
+
Index: branches/terrain/src/lib/graphics/importer/bsp_manager.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/bsp_manager.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/bsp_manager.cc	(revision 9414)
@@ -199,5 +199,6 @@
   this->outputFraction = 1.0f;
 
-  if ( viscluster < 0  || ((int *)(this->bspFile->header))[35] == 0 )  //!< if (sizeof(Visdata) == 0)
+  if ( ( viscluster < 0  ) ||
+ 		( bspFile->header.lumps[Visdata].length == 0 ) )  //!< if (sizeof(Visdata) == 0)
   {
 
Index: branches/terrain/src/lib/graphics/importer/md2/md2Model.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/md2/md2Model.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/md2/md2Model.cc	(revision 9414)
@@ -17,5 +17,12 @@
 #include "md2Model.h"
 #include "material.h"
-
+#include "config.h"
+#ifdef HAVE_SDL_SDL_H
+#include <SDL/SDL.h>
+#include <SDL/SDL_endian.h>
+#else
+#include <SDL.h>
+#include <SDL_endian.h>
+#endif
 #include "debug.h"
 #include "util/loading/resource_manager.h"
@@ -67,5 +74,21 @@
   };
 
-
+#ifdef SDL_LIL_ENDIAN
+#define BULK_CONV( _ptr, _num ) do { \
+	int  _cnt = _num;\
+	int* _iptr = (int*)_ptr;\
+	for( int _l = 0; _l<_cnt; ++_l )\
+		_iptr[_l] = SDL_SwapLE32( _iptr[_l] );\
+} while( 0 )
+#define BULK_CONV16( _ptr, _num ) do { \
+	short  _cnt = _num;\
+	short* _iptr = (short*)_ptr;\
+	for( int _l = 0; _l<_cnt; ++_l )\
+		_iptr[_l] = SDL_SwapLE16( _iptr[_l] );\
+} while( 0 )
+#else
+#define BULK_CONV( _ptr, _num )
+#define BULK_CONV16( _ptr, _num )
+#endif
 
 /********************************************************************************
@@ -468,6 +491,7 @@
   this->header = new MD2Header;
   fread(this->header, 1, sizeof(MD2Header), pFile);
+	BULK_CONV( this->header, sizeof(MD2Header)/4 );
   /* check for the header version: make sure its a md2 file :) */
-  if( unlikely(this->header->version != MD2_VERSION) && unlikely(this->header->ident != MD2_IDENT))
+  if( unlikely( this->header->version != MD2_VERSION) && unlikely( this->header->ident != MD2_IDENT))
     {
       PRINTF(1)("Couldn't load file %s: invalid file format: stop loading\n", fileName.c_str());
@@ -475,5 +499,5 @@
     }
 
-  this->fileName =fileName;
+  this->fileName = fileName;
   /* got the data: map it to locals */
   this->numFrames = this->header->numFrames;
@@ -494,18 +518,26 @@
   fseek(pFile, this->header->offsetFrames, SEEK_SET);
   fread(buffer, this->header->frameSize, this->numFrames, pFile);
+	//BULK_CONV( buffer, this->header->frameSize*this->numFrames*sizeof(char)/4 );
   /* read opengl commands */
   fseek(pFile, this->header->offsetGlCommands, SEEK_SET);
+
   fread(this->pGLCommands, sizeof(int), this->numGLCommands, pFile);
+	BULK_CONV( this->pGLCommands, this->numGLCommands );
   /* triangle list */
   fseek(pFile, this->header->offsetTriangles, SEEK_SET);
-  fread(this->pTriangles, sizeof(sTriangle), this->numTriangles, pFile);
+  fread(this->pTriangles, sizeof(sTriangle), this->numTriangles, pFile);	
+	BULK_CONV16( this->pTriangles, this->numTriangles*sizeof(sTriangle)/2 );
+
   /*  read in texture coordinates */
   fseek(pFile, this->header->offsetTexCoords, SEEK_SET);
   fread(this->pTexCoor, sizeof(sTexCoor), this->numTexCoor, pFile);
-
+	BULK_CONV16( this->pTexCoor, this->numTexCoor*sizeof(sTexCoor)/2 );
 
   for(int i = 0; i < this->numFrames; ++i)
     {
       frame = (sFrame*)(buffer + this->header->frameSize * i);
+			//Convert the translate and scale Vec3D if needed.
+			BULK_CONV( frame, 6 );
+			BULK_CONV( frame->pVertices, 3 );
       pVertex = this->pVertices + this->numVertices  * i;
       pNormals = this->pLightNormals + this->numVertices * i;
Index: branches/terrain/src/lib/graphics/importer/md3/md3_animation_cfg.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/md3/md3_animation_cfg.cc	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/md3/md3_animation_cfg.cc	(revision 9414)
@@ -173,5 +173,5 @@
         }
 	}
-    }
+    }*/
       */
   }
Index: branches/terrain/src/lib/graphics/importer/md3/md3_data.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/md3/md3_data.h	(revision 9413)
+++ branches/terrain/src/lib/graphics/importer/md3/md3_data.h	(revision 9414)
@@ -70,5 +70,4 @@
   };
 
-
   //! class to store the md2 data in
   class MD3Data : public BaseObject
Index: branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h	(revision 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h	(revision 9414)
@@ -0,0 +1,136 @@
+/*
+        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 _BUFFERBROKER_H
+#define _BUFFERBROKER_H
+
+#include "glincl.h"
+#include "debug.h"
+#include "types.h"
+/**
+ * @brief       Manages the streaming of the vertex buffer objects for the terrain page.
+ */
+
+struct BufferPair {
+        BufferPair( int _i, int _v ) { indexName = _i; vertexName = _v; next = NULL; }
+        BufferPair() { indexName = vertexName = 0; next = NULL; }
+        GLuint                  indexName;
+        GLuint                  vertexName;
+        BufferPair              *next;
+};
+
+typedef BufferPair *pBufferPair;
+
+class BufferBroker {
+        public:
+
+                BufferBroker( int _num, int _vbSize, int _ibSize )
+                {
+                        capacity = _num;
+                        freeIndexBuffers = new GLuint[capacity];
+                        freeVertexBuffers =     new GLuint[capacity];
+                        lastAcquired = 0;
+                        vbSize = _vbSize; ibSize = _ibSize;
+                        glGenBuffersARB( capacity, freeIndexBuffers );
+                        glGenBuffersARB( capacity, freeVertexBuffers );
+                        for ( int i = 0; i < capacity; ++i ) {
+                                glBindBufferARB( GL_ARRAY_BUFFER_ARB, freeVertexBuffers[i] );
+                                glBufferDataARB( GL_ARRAY_BUFFER_ARB, vbSize,
+                                        NULL, GL_DYNAMIC_DRAW_ARB );
+                                glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, freeIndexBuffers[i] );
+                                glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibSize,
+                                        NULL, GL_DYNAMIC_DRAW_ARB );
+                        }
+                        head = tail = NULL;
+                }
+                ~BufferBroker()
+                {
+                        pBufferPair bp = head;
+                        while ( bp ) {
+                                pBufferPair tmp = bp->next;
+                                release( bp->vertexName, bp->indexName );
+                                bp = tmp;
+                        }
+                        glDeleteBuffersARB( capacity, freeVertexBuffers );
+                        glDeleteBuffersARB( capacity, freeIndexBuffers );
+                        SAVE_DELETE_ARRAY( freeIndexBuffers );
+                        SAVE_DELETE_ARRAY( freeVertexBuffers );
+                }
+                inline int getIBSize() { return ibSize; }
+                inline int getVBSize() { return vbSize; }
+                inline void acquire( GLuint &_vbName, GLuint &_ibName );
+
+                inline void release( const GLuint &_vbName, const GLuint &_ibName );
+        protected:
+
+                int                                             capacity;
+
+                int                                             vbSize,
+                                                                ibSize;
+                int                                             lastAcquired;
+
+                GLuint                                  *freeIndexBuffers,
+                                                                *freeVertexBuffers;
+
+                BufferPair                              *head, *tail;
+};
+
+inline void BufferBroker::release( const GLuint &_vbName, const GLuint &_ibName )
+{
+        pBufferPair bp = head, prev = NULL;
+        bool removed = false;
+        while ( bp ) {
+
+                if ( bp->indexName == _ibName && bp->vertexName == _vbName ) {
+                        if ( prev ) {
+                                prev->next = bp->next;
+                        }
+                        else {
+                                head = bp->next;
+                        }
+                        if ( bp->next == NULL )
+                                tail = prev;
+                        int index = capacity-lastAcquired;
+                        lastAcquired--;
+                        freeIndexBuffers[index] = bp->indexName;
+                        freeVertexBuffers[index] = bp->vertexName;
+                        delete bp;
+                        removed = true;
+                        break;
+                }
+                prev = bp;
+                bp = bp->next;
+        }
+        assert( removed );
+}
+
+inline void BufferBroker::acquire( GLuint &_vbName, GLuint &_ibName )
+{
+        assert( capacity > lastAcquired );
+        int index = capacity-lastAcquired-1;
+        _vbName = freeVertexBuffers[index]; _ibName = freeIndexBuffers[index];
+        lastAcquired++;
+        if ( tail ) {
+                tail->next = new BufferPair( _ibName, _vbName );
+                tail = tail->next;
+        }
+        else {
+                tail = head = new BufferPair( _ibName, _vbName );
+        }
+}
+
+typedef BufferBroker *pBufferBroker;
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/frustum.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/frustum.cc	(revision 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/frustum.cc	(revision 9414)
@@ -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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/frustum.h	(revision 9414)
@@ -0,0 +1,140 @@
+/*
+	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 "plane.h"
+#include "vector.h"
+#include "types.h"
+#include "glincl.h"
+#include <stdio.h>
+
+
+#define MAX_CLIP_DISTANCE 800.0f
+#define m( _col, _row )  _m[_row*4+_col]
+
+#define CHECK_GL_ERROR( _d ) do { \
+	GLenum __err = glGetError(); \
+	if ( __err != GL_NO_ERROR ) \
+		printf( "check%s: %s\n", _d, (char*)gluErrorString( __err ) );\
+	}\
+	while ( 0 )
+	
+/** 
+ * Code borrowed from Lighthouse 3D. Its a very good tutorial on culling.
+ */
+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 each plane do ...
+			for( int i = 0; i < 6; ++i ) {
+
+				// is the positive vertex outside?
+				if ( planes[i].distancePoint( _box.vertexP( planes[i].n ) ) < 0 )
+					return OUTSIDE;
+				// is the negative vertex outside?	
+				else if ( planes[i].distancePoint( _box.vertexN( planes[i].n ) ) < 0 )
+					result = INTERSECT;
+			}
+			return result;
+		}
+		
+		inline int pointInFrustum( const Vector& _point)
+		{
+			int result = INSIDE;
+			for(int i=0; i < 6; i++) {
+				if (planes[i].distancePoint( _point ) < 0)
+					return OUTSIDE;
+			}
+			return result;		
+		}
+		
+		inline Plane getPlane( int _plane ) { return planes[_plane]; }
+		
+		inline void setFrustum( float *_m )
+		{
+			planes[NEAR] =  Plane( Vector( 
+				m(2,0) + m(3,0), 
+				m(2,1) + m(3,1), 
+				m(2,2) + m(3,2) ), 
+				m(2,3) + m(3,3) );
+				
+			planes[FAR] = Plane( Vector( 
+				-m(2,0) + m(3,0),
+				-m(2,1) + m(3,1),
+				-m(2,2) + m(3,2) ),
+				-m(2,3) + m(3,3) );
+									
+			planes[BOTTOM] = Plane( Vector( 
+				m(1,0) + m(3,0), 
+				m(1,1) + m(3,1), 
+				m(1,2) + m(3,2) ), 
+				m(1,3) + m(3,3) );
+			planes[TOP] = Plane( Vector(  
+				-m(1,0) + m(3,0),
+				-m(1,1) + m(3,1),
+				-m(1,2) + m(3,2) ),
+				-m(1,3) + m(3,3) );
+			planes[LEFT] = Plane( Vector(  
+				m(0,0) + m(3,0),
+				m(0,1) + m(3,1),
+				m(0,2) + m(3,2) ),
+				m(0,3) + m(3,3) );
+			planes[RIGHT] =  Plane( Vector( 
+				-m(0,0) + m(3,0),
+				-m(0,1) + m(3,1),
+				-m(0,2) + m(3,2) ),
+				-m(0,3) + m(3,3) );
+							
+			if ( planes[NEAR].k +planes[FAR].k  > MAX_CLIP_DISTANCE ) {
+				planes[FAR].k = -planes[NEAR].k+MAX_CLIP_DISTANCE;
+			}
+		}
+		
+	protected:
+		Plane		*planes;
+};
+
+#endif
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 9414)
@@ -0,0 +1,473 @@
+
+#include "terrain.h"
+#include "terrain_page.h"
+#include "glincl.h"
+#include "util/loading/resource_manager.h"
+#include "debug.h"
+#include <math.h>
+#ifdef HAVE_SDL_SDL_IMAGE_H
+#include <SDL/SDL_image.h>
+#else
+#include <SDL_image.h>
+#endif
+
+bool validateSize( int _s ) {
+	_s-=1;
+	int s = 16;
+	while ( s <= _s ) {
+		if (s == _s )
+			return true;
+		s*=2;
+	}
+	return false;
+}
+void Terrain::build()
+{
+	ResourceManager *MANAGER = ResourceManager::getInstance();
+	std::string full = MANAGER->getFullName( heightmapSource );
+	SDL_Surface *tmpData = IMG_Load( full.c_str() );
+ 	if ( !tmpData ) {
+		PRINT(0)( "I' sorry, I can't load %s\n", full.c_str() );
+		return;
+	}		
+	if ( !validateSize( tmpData->h ) || !validateSize( tmpData->w ) ) {
+		PRINT(0)( "The size of the elevation map must be 2^n+1x2^m+1. and at least 17x17" );
+		return;
+	}
+	if ( tmpData->format->BytesPerPixel != 1 ) {
+		PRINT(0)( "The elevetation map must be an 8bit image not %d", 
+			tmpData->format->BytesPerPixel*8 );
+		return;
+	}
+	PRINTF(2)( "Loaded the elevation map\n" );
+	heightfield.height = tmpData->h;
+	heightfield.width = tmpData->w;
+	heightfield.pitch = tmpData->pitch;
+	int dataSize = heightfield.pitch*heightfield.height;
+	heightfield.data = new Uint8[dataSize];
+	memcpy( heightfield.data, tmpData->pixels, sizeof(Uint8)*dataSize );
+	SDL_FreeSurface( tmpData );
+	pagesX = (heightfield.width/(pageSize-1) );
+	pagesZ = (heightfield.height/(pageSize-1) );
+	
+	
+	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 );
+	//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 < pagesZ-1	? getPage( x+0, z+1 ) : NULL,
+				z > 0 			? getPage( x+0, z-1 ) : NULL );
+	
+	root = createQuadTree( 0, 0, pagesX, pagesZ );
+	
+	for ( unsigned int i = 0; i < layers.size(); ++i ) {
+		determineLayerVisibility( i );
+	}	
+	activePages = NULL;
+}
+
+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 {	
+		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( Vector( scale.x*_xOffset, 0.0f, scale.z*_zOffset ) );
+	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 );
+		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 ) );
+	//The indices need to be updated with an offset :(
+	unsigned short *dst= &indices[bi.numIndices];
+	unsigned short offset = bi.numVertices;
+	unsigned short *src= _indices;
+	unsigned short *end= src+_numIndices;
+	bi.numVertices+=_numVertices;		
+	if ( bi.numIndices ) {
+		dst[0] = *(dst-1);
+		dst[1] = *src+offset;
+		dst+=2; bi.numIndices+=2;
+	}
+	while ( src < end ) {
+		*dst= *src+offset;
+		dst++;
+		src++;
+	}
+	bi.numIndices+=_numIndices;
+	buffers[current] = bi;
+}
+
+void Terrain::determineVisiblePages( pTerrainQuad _node )
+{
+	switch( _node->cull() ) {
+		case Frustum::INTERSECT:
+			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:
+			showPages( _node->getXOffset(), 
+					   _node->getZOffset(), 
+					   _node->getWidth() , 
+					   _node->getHeight() );
+			break;
+		case Frustum::OUTSIDE:
+			break;
+	}
+}
+
+void Terrain::tick( float _dt )
+{
+	for ( unsigned int i = 0; i < buffers.size(); ++i )
+		broker->release( buffers[i].vbIdentifier, buffers[i].ibIdentifier );
+	buffers.clear();	
+	pTerrainPage page = NULL;
+	//Extract the frustum planes out of the modelview matrix.
+	frustum->extractPlanes();	
+	// Lets see which pages are visible.
+	determineVisiblePages( root );
+	int wantedLeft, wantedRight, wantedBottom, wantedTop, minLOD;
+	pTerrainPage neighbor = NULL;
+	page = activePages;
+	bool dirty;
+	current = 0;
+	BufferInfo bi;
+	broker->acquire( bi.vbIdentifier, bi.ibIdentifier );
+	buffers.push_back( bi );
+	int dirtyRounds = 0;
+	do {
+		dirtyRounds++;
+		dirty = false;
+		page = activePages;
+		while ( page ) {
+			if ( !page->isActive() ) {
+				pTerrainPage tmp = page;
+				page = tmp->getNext();
+				tmp->setVisibility( false );
+				continue;
+			}
+			wantedLeft = wantedRight = wantedBottom = wantedTop = page->getWantedLOD();
+			if ( ( neighbor = page->getLeft() ) && ( neighbor->isActive() ) ) 
+				wantedLeft = neighbor->getWantedLOD();
+			if ( ( neighbor = page->getRight() ) && ( neighbor->isActive() ) ) 
+				wantedRight = neighbor->getWantedLOD();
+			if ( ( neighbor = page->getTop() ) && ( neighbor->isActive() ) ) 
+				wantedTop = neighbor->getWantedLOD();
+			if ( ( neighbor = page->getBottom() ) && ( neighbor->isActive() ) ) 
+				wantedBottom = neighbor->getWantedLOD();			
+		
+			minLOD = std::min( std::min( wantedBottom, wantedTop ), 
+				std::min( wantedLeft, wantedRight ) );	
+			if ( minLOD < page->getWantedLOD()-1 ) {
+				page->setWantedLOD( minLOD+1 );
+				dirty = true;
+			}	
+			page = page->getNext();
+		}
+	} while ( dirty );
+	
+	page = activePages;
+	while ( page ) {
+		assert( page->isActive() );
+		page->updateTesselation();
+		page = page->getNext();
+	}
+	//If there is some data in the buffer, we need to upload the data
+	//into the vram...
+	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 );
+	}	
+}
+
+void Terrain::draw( )
+{
+	pTerrainPage page = NULL;
+	glGetError();
+	/*pTerrainPage page = NULL;
+	frustum->extractPlanes();*/
+	Plane far = frustum->getPlane( Frustum::FAR );
+	//Due to some reason, the OpenGL implementors chose the plane equation
+	//to an array of doubles. So we will make them happy.
+	double farPlane[] = { far.n.x, far.n.y, far.n.z, far.k };
+	glEnable( GL_CLIP_PLANE0 );
+	glClipPlane( GL_CLIP_PLANE0, farPlane );
+	glPushAttrib( GL_ALL_ATTRIB_BITS );
+	glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
+	/*
+	 * Enable texture and vertex arrays for the first and the second texture
+	 * units and disable the normal arrays.
+	 */
+	glClientActiveTextureARB( GL_TEXTURE0_ARB );	
+		glEnableClientState( GL_VERTEX_ARRAY );
+		glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 
+		glDisableClientState( GL_NORMAL_ARRAY );
+				
+	glClientActiveTextureARB( GL_TEXTURE1_ARB );	
+		glEnableClientState( GL_VERTEX_ARRAY );
+		glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+		glDisableClientState( GL_NORMAL_ARRAY ); 
+	glDisable( GL_CULL_FACE );
+	glDisable( GL_LIGHTING );
+	glColor3f( 1.0f, 1.0f, 1.0f );
+	//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+	cullCount = 0;
+	glEnable( GL_BLEND );
+	glDepthFunc( GL_LEQUAL );
+	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+	for ( unsigned int i = 0; i < layers.size(); ++i ) {
+		LayerInfo* layer= layers[i];
+		page = activePages;	
+				
+		glActiveTextureARB( GL_TEXTURE1_ARB );
+		glClientActiveTextureARB( GL_TEXTURE1_ARB );
+		if ( layer->detail ) {
+			//glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND );
+			glEnable( GL_TEXTURE_2D );
+			glBindTexture( GL_TEXTURE_2D, layer->detail->getTexture() );
+			glMatrixMode( GL_TEXTURE );
+			glLoadIdentity();
+			glScalef( layer->repeatX, layer->repeatZ, 1.0f );
+		}	
+		else {
+			glDisable( GL_TEXTURE_2D );
+		}
+		glEnable( GL_CULL_FACE );
+		glCullFace( GL_BACK );
+		glClientActiveTextureARB( GL_TEXTURE0_ARB );
+		glActiveTextureARB( GL_TEXTURE0_ARB );
+		glEnable( GL_TEXTURE_2D );
+		if ( layer->alpha ) {
+			//glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND );			
+			glBindTexture( GL_TEXTURE_2D, layer->alpha->getTexture() );
+		}
+		else {
+		
+			glBindTexture( GL_TEXTURE_2D, lightmap->getTexture() );			
+		}
+		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 ) {
+			if ( page->hasMaterial( i ) )
+				page->draw();
+			page = page->getNext();
+		}
+	}
+	glClientActiveTextureARB( GL_TEXTURE1_ARB );	
+	glActiveTextureARB( GL_TEXTURE1_ARB );
+	glDisable( GL_TEXTURE_2D );
+	glActiveTextureARB( GL_TEXTURE0_ARB );
+	glEnable( GL_LIGHTING );
+	glMatrixMode( GL_TEXTURE );
+	glLoadIdentity();
+	glPopAttrib();
+	glPopClientAttrib();
+	glCullFace( GL_FRONT );
+	glDisable( GL_CLIP_PLANE0 );
+}
+
+inline Uint8 getAlpha( const SDL_Surface *_s, int _x, int _y )
+{
+    int bpp = _s->format->BytesPerPixel;
+    Uint8 *p = (Uint8 *)_s->pixels + _y*_s->pitch + _x * bpp;
+	Uint32 pixel = 0;
+    switch( bpp ) {
+    case 1:
+        pixel = *p;
+		break;
+    case 2:
+		if ( SDL_BYTEORDER == SDL_BIG_ENDIAN )
+			pixel = p[0] << 8 | p[1]; 
+		else
+        	pixel = *(Uint16 *)p;
+		break;
+    case 3:
+        if( SDL_BYTEORDER == SDL_BIG_ENDIAN )
+            pixel = p[0] << 16 | p[1] << 8 | p[2];
+        else
+            pixel = p[0] | p[1] << 8 | p[2] << 16;
+		break;
+    case 4:
+        pixel = *(Uint32 *)p;
+		break;
+    default:
+        return 255; /* shouldn't happen, but avoids warnings */
+    }
+	Uint8 r,g,b,a;
+	SDL_GetRGBA( pixel, _s->format, &r, &g, &b, &a );
+	return a;
+}
+
+void Terrain::determineLayerVisibility( int _layer )
+{
+	LayerInfo * layer = layers[_layer];
+	if ( !layer->alpha ) {
+		int numPages = pagesX*pagesZ;
+		for ( int i = 0; i < numPages; ++i )
+			pages[i]->setLayerVisibility( _layer, LV_FULL );
+			
+		return;
+	}
+	SDL_Surface *alpha = const_cast<SDL_Surface*>( layer->alpha->getStoredImage() );	
+	SDL_LockSurface( alpha );
+	float du = ( (float)alpha->w)/pagesX;
+	float dv = ( (float)alpha->h)/pagesZ;
+	float u = 0.0f, v = 0.0f;
+	for ( int pageX = 0; pageX < pagesX; ++pageX ) {
+		v = 0.0f;
+		for ( int pageZ = 0; pageZ < pagesZ; ++pageZ ) {
+			bool full = true; bool has = false;
+			for ( int x = 0; x < (int)PAGE_SIZE; ++x ) {
+				for ( int z = 0; z < (int)PAGE_SIZE; ++z ) {
+					Uint8 a = getAlpha( alpha, (int)u, (int)v );
+					if ( a ) 
+						has = true;
+					if ( a < 255 )
+						full = false;
+				}
+			}
+			LayerVisibility lv;
+			if ( has ) {
+				if ( full )
+					lv = LV_FULL;
+				else
+					lv = LV_PARTIAL;
+			}
+			else {
+				lv = LV_NO;
+			}
+			getPage( pageX, pageZ )->setLayerVisibility( _layer, lv );
+			v+= dv;
+		}
+		u+= du;
+	}
+	SDL_UnlockSurface( alpha );
+}
+
+void Terrain::getAltitude( Vector& _alt, Vector& _normal )
+{
+	float xScaled = _alt.x / scale.x, zScaled = _alt.z / scale.z;
+	//The offset on the map
+	int xOff =  (int)xScaled, zOff = (int)zScaled;
+	//The interpolation values.
+	float u = xScaled-xOff, v = zScaled-zOff;
+	
+	float dX = scale.x / ( pageSize-1 );
+	float dZ = scale.z / ( pageSize-1 );
+	
+	//If u is bigger than v, we are on the lower triangle...
+	if ( u > v ) {
+		
+		float alt[] = {
+			getAltitude( xOff+0, zOff+0 )*scale.y,
+			getAltitude( xOff+1, zOff+0 )*scale.y,
+			getAltitude( xOff+1, zOff+1 )*scale.y };
+		_alt.y = (1.0f-u-v)*alt[0]+u*alt[1]+v*alt[2];
+		
+		//Since we know about the directions of some x and z-coordinates, 
+		//not the whole cross products needs to be calculated. Grab yourself
+		//pen and paper :)
+		_normal.x =  dZ*( alt[0] - alt[1] );				
+		_normal.y =  dZ*dX;
+		_normal.z = -dX*( alt[2] - alt[1] );
+	}
+	else {
+		float alt[] = {
+			getAltitude( xOff+0, zOff+0 )*scale.y,
+			getAltitude( xOff+0, zOff+1 )*scale.y,
+			getAltitude( xOff+1, zOff+1 )*scale.y };			
+		_alt.y = (1.0f-u-v)*alt[0]+v*alt[1]+u*alt[2];
+		//Since we know about the directions of some x and z-coordinates, 
+		//not the whole cross products needs to be calculated. Grab yourself
+		//pen and paper :)
+		_normal.x = -dZ*( alt[2] - alt[1] );				
+		_normal.y =  dZ*dX;
+		_normal.z =  dX*( alt[0] - alt[1] );
+	}
+}
+
+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->setVisibility( true );			
+			page->chooseLOD();
+
+		}
+	}
+}
Index: branches/terrain/src/lib/graphics/importer/terrain/terrain.h
===================================================================
--- branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 9414)
@@ -0,0 +1,233 @@
+/*
+	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
+
+#define USE_VBO
+#ifdef USE_VBO
+#include "buffer_broker.h"
+#endif
+
+#include "vector.h"
+#include "terrain_page.h"
+#include "terrain_quad.h"
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include "texture.h"
+#include "frustum.h"
+
+class Texture;
+class Terrain;
+typedef Terrain *pTerrain;
+	
+class Terrain {
+	public:
+		const static unsigned int PAGE_SIZE 		= 17;
+		const static unsigned int MAX_VERTICES 		= PAGE_SIZE*PAGE_SIZE;
+		const static unsigned int MAX_INDICES		= 2*( PAGE_SIZE*PAGE_SIZE + PAGE_SIZE -2 );
+		/**
+		 * The amount of geometry rendered is largely depending on this constant. So chose a
+		 * reasonable value...
+		 */
+		inline float getDetail() { return 0.02f; }
+
+	
+		inline bool debug()
+		{
+			return false;
+		}
+		
+		inline pTerrainPage getActiveList() { return activePages; }
+
+	
+		inline void setCameraPosition( const Vector& _cameraPosition ) 
+		{ 
+			cameraPosition = _cameraPosition; 
+		}
+		
+		inline const Vector& getCameraPosition() const
+		{
+			return cameraPosition;
+		}
+	
+		void getAltitude( Vector& _alt, Vector& _normal );
+		
+		inline void setLightmap( Texture *_lightmap )
+		{
+			lightmap = _lightmap;
+		}
+		//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 );
+					
+		/**
+		 * Create a new terrain.
+		 */
+		Terrain( )
+		{ 
+			pageSize = 17;
+			pagesX = pagesZ = 0;
+			lightmap = NULL;
+			heightmapSource = "";
+			root = NULL;
+			current = 0;
+			activePages = NULL;
+			scale  = Vector( 1.0f, 3.0f, 1.0f );
+			frustum = new Frustum();
+			activatedCount = deactivatedCount = 0;
+			vertices = new Vertex[MAX_VERTICES];
+			indices = new unsigned short[MAX_INDICES];
+#ifdef USE_VBO
+			broker = new BufferBroker( 300, MAX_VERTICES*sizeof( Vertex ), 
+				MAX_INDICES*sizeof( short ) );
+#endif			
+		}
+		
+		~Terrain( ) 
+		{
+			//The pages are deleted through the SAVE_DELETE( root ) call.
+			SAVE_DELETE_ARRAY( pages );
+			SAVE_DELETE_ARRAY( vertices );
+			SAVE_DELETE_ARRAY( indices );
+			SAVE_DELETE( lightmap );
+			SAVE_DELETE( root );
+#ifdef USE_VBO
+			SAVE_DELETE( broker );
+#endif			
+		}
+		/**
+		 * Draws the terrain.
+		 */
+		void draw( );
+
+		void setPageSize( const Vector& _page ) { }
+		
+		void build();
+		void tick( float _dt );
+		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 float getAltitude( int _x, int _z ) const;
+		
+		inline void addMaterialLayer( LayerInfo *_layer )
+		{ layers.push_back( _layer ); }
+		
+		inline void setHeightmap( const std::string &_heightmap ) 
+		{ 
+			heightmapSource = _heightmap; 
+		}
+		
+		inline void setPageSize( int _pageSize )
+		{
+			pageSize = _pageSize;
+		}
+		
+		inline const Vector 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 Vector& _scale )
+		{ scale = _scale; }
+#ifdef USE_VBO
+		inline pBufferBroker getBufferBroker() { return broker; }
+#endif		
+		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 );			
+		void determineLayerVisibility( int _layer );			
+		
+#ifdef USE_VBO
+		pBufferBroker				broker;
+#endif
+		pTerrainQuad				root;		// The quad-tree root node.
+		pTerrainPage				*pages;		// the references to all pages
+		std::string					heightmapSource;
+		Texture						*lightmap;
+		Heightfield					heightfield;
+		Vector						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;			
+			
+		Vector						cameraPosition;
+		pFrustum					frustum;
+		pTerrainPage				activePages;
+		std::vector<LayerInfo*>		layers;
+};
+
+inline float Terrain::getAltitude( int _x, int _z ) const
+{
+	assert( heightfield.data );
+	if ( _x < 0 || _x >= heightfield.width || _z < 0 || _z >= heightfield.height ) {
+		return 0.0f;
+		printf( "outside!\n" );
+	}	
+	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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 9414)
@@ -0,0 +1,803 @@
+/*
+	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 USE_VBO
+
+#define CHECK_GL_ERROR( _d ) do { \
+	GLenum __err = glGetError(); \
+	if ( __err != GL_NO_ERROR ) \
+		printf( "check%s: %s\n", _d, (char*)gluErrorString( __err ) );\
+	}\
+	while ( 0 )
+	
+TerrainPage::~TerrainPage( )
+{ 
+	SAVE_DELETE_ARRAY( indices );
+	SAVE_DELETE_ARRAY( vertices );
+	SAVE_DELETE_ARRAY( indexHash );		
+	SAVE_DELETE_ARRAY( errors );	
+}
+
+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; 
+	left = top = bottom = right = NULL;
+	for ( int i = 0; i < 8; ++i )
+		layerVisibility[i] = LV_NO;	
+		
+	position = Vector( scale.x*_xOffset, 
+		0.0f, scale.z*_zOffset );
+	isVisible = false;
+	next = NULL;
+	active = false;
+	previous = NULL; 
+	currentLOD = -1; wantedLOD = -1;
+	hasfull = false;
+	forceTesselation = true;
+	vbIdentifier = 0; ibIdentifier = 0;
+}
+
+void TerrainPage::tesselateRow( int _z, int _xStride, int _zStride, 
+	bool _adaptLeft, bool _adaptRight )
+{
+	
+	int xStart = 0, xEnd = owner->getPageSize();	
+	int halfStride = _zStride >> 1;
+	assert( _xStride > 0 ); 	assert( _zStride > 0 );
+	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( xEnd-1, _z ) );
+		addAgain();
+		addIndex( getIndex( w, _z ) );
+		addIndex( getIndex( xEnd-1, _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->isActive() ) {
+		_adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0;
+		assert( std::abs( wantedLOD - left->wantedLOD ) < 2 );		
+	}	
+	if ( right && right->isActive() ) {
+		_adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0;
+		assert( std::abs( wantedLOD - right->wantedLOD ) < 2 );		
+	}	
+		
+	if ( top && top->isActive() ) {
+		_adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0;				
+		assert( std::abs( wantedLOD - top->wantedLOD ) < 2 );		
+	}	
+	if ( bottom && bottom->isActive() ) {
+		_adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0;		
+		assert( std::abs( wantedLOD - bottom->wantedLOD ) < 2 );
+	}	
+}
+
+int TerrainPage::chooseLOD()
+{
+	wantedLOD = -1;
+	Vector cam( owner->getCameraPosition() );
+	
+	for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) {
+		Vector distance( cam.x-errors[i].correct.x,
+						 cam.y-errors[i].correct.y,
+						 cam.z-errors[i].correct.z );
+		
+		float d = distance.len();
+		
+		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->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;
+	previous = NULL;
+	
+}
+
+void TerrainPage::calculateError( int _lod )
+{
+	float	sumError = 0.0f;
+	int		numErrors = 0;
+	int size = owner->getPageSize();
+	if( _lod!=0 )
+	{
+		int stride = 1 << _lod, x0, y0, xi, yi;
+		// Altough these four nested loops look very scary, they're not 
+		// 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 )stride, fx1 = 1.0f-fx0,
+								fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0;
+						
+						float	height00 = getAltitude( x0, y0 ),
+								height10 = getAltitude( x0+stride,y0 ),
+								height01 = getAltitude( x0,y0+stride ),
+								height11 = getAltitude( x0+stride, y0+stride );
+						
+						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;
+	
+	Vector	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-1.0f );
+			max.y = fmax( max.y, alt+1.0f );
+		}
+	}
+	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 );
+}
+
+bool TerrainPage::needsRetesselation()
+{
+	
+	bool 	leftChanged 	= ( left && left->isActive() ) &&
+	 			( left->wantedLOD != left->currentLOD ),
+			rightChanged	= ( right && right->isActive() ) && 
+				( right->wantedLOD != right->currentLOD ),
+			topChanged		= ( top && top->isActive() ) && 
+				( top->wantedLOD != currentLOD ),
+			bottomChanged	= ( bottom && bottom->isActive() ) && 
+				( bottom->wantedLOD != bottom->currentLOD ),
+			iChanged		=  wantedLOD != currentLOD;
+				
+	return ( leftChanged || rightChanged || topChanged || bottomChanged || 
+		forceTesselation || iChanged );
+}
+
+void TerrainPage::updateTesselation( )
+{
+	assert( wantedLOD < 5 && wantedLOD >= 0 );
+	if ( needsRetesselation() ) {
+		tesselate( wantedLOD );
+	}	
+	currentLOD = wantedLOD;
+	
+	//Check if the page is a level four page. If yes, copy the vertex and index data into 
+	//the shared level four page buffers.
+	if ( currentLOD == TerrainPage::MAX_LODS-1 ) {
+		owner->addLevelFourPage( numVertices, vertices, 
+			numIndices, indices );
+	}
+	forceTesselation = false;
+}
+
+void TerrainPage::tesselateTopRow(  int _z, int _stride, 
+	bool _adaptLeft,  bool _adaptRight )
+{
+	int halfStride = _stride/2;
+	int xStart = 0, xEnd= owner->getPageSize()-1;
+	int size = xEnd;
+	int z = xEnd-_stride ;	
+	addAgain();
+	addIndex( getIndex( 0, z ) );
+	assert(halfStride>=1);
+
+	if( _adaptLeft ) {
+		addIndex( getIndex( 0, z ) );
+		addIndex( getIndex( 0, z+halfStride ) );
+		addIndex( getIndex( _stride, z ) );
+		addIndex( getIndex( 0, size ) );
+		addIndex( getIndex( halfStride, size ) );
+		addAgain();
+		addIndex( getIndex( _stride, z ) );
+		addIndex( getIndex( _stride, size ) );
+		xStart = _stride;
+	}
+
+	if ( _adaptRight )
+		xEnd -= _stride;
+	for ( int x = xStart; x < xEnd; x+=_stride ) {
+		addIndex( getIndex( x, z ) );
+		addIndex( getIndex( x, size ) );
+		addIndex( getIndex( x+_stride, z ) );
+		addIndex( getIndex( x+halfStride, size ) );
+		addIndex( getIndex( x+_stride, size ) );
+		addAgain();
+	}
+
+	if ( _adaptRight ) {
+		addIndex( getIndex( xEnd, z ) );
+		addIndex( getIndex( xEnd, size ) );
+		addIndex( getIndex( size, z ) );
+		addIndex( getIndex( xEnd+halfStride, size ) );
+		addIndex( getIndex( size, size-halfStride ) );
+		addIndex( getIndex( size, size ) );
+	}
+
+}
+void TerrainPage::tesselateBottomRow(  int _z,  int _stride,  
+	bool _adaptLeft,  bool _adaptRight  )
+{
+	int halfStride = _stride/2;
+	int xStart=0, xEnd=owner->getPageSize()-1;
+	int size = xEnd;
+	assert( halfStride>=1 );
+
+	if ( _adaptLeft ) {
+		addIndex( getIndex( 0, 0 ) );
+		addIndex( getIndex( 0, halfStride ) );
+		addIndex( getIndex( halfStride, 0 ) );
+		addIndex( getIndex( 0, _stride ) );
+		addIndex( getIndex( _stride, 0 ) );
+		addIndex( getIndex( _stride, _stride ) );
+		xStart = _stride;
+	}
+
+
+	if ( _adaptRight )
+		xEnd -= _stride;
+
+	for ( int x = xStart; x < xEnd; x+=_stride ) {
+		addIndex( getIndex( x, 0 ) );
+		addAgain();
+		addIndex( getIndex( x+halfStride, 0 ) );
+		addIndex( getIndex( x, _stride ) );
+		addIndex( getIndex( x+_stride ,0 ) );
+		addIndex( getIndex( x+_stride, _stride ) );
+	}
+
+
+	if( _adaptRight ) {
+		addIndex( getIndex( xEnd,0 ) );
+		addIndex( getIndex( xEnd,_stride ) );
+		addIndex( getIndex( xEnd+halfStride, 0 ) );
+		addIndex( getIndex( size ,0 ) );
+		addAgain();
+		addIndex( getIndex( xEnd, _stride ) );
+		addIndex( getIndex( size, halfStride ) );
+		addIndex( getIndex( size, _stride ) );
+	}
+}
+
+void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
+{
+	assert( indices ); assert( vertices );
+	numIndices = numVertices = 0;
+	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;
+	}
+	assert( numIndices % 2 == 0 );
+}
+
+
+void TerrainPage::tesselate( int _lod )
+{
+
+	memset( indexHash, 0xffff, 
+			sizeof(unsigned short)*Terrain::MAX_VERTICES );
+	
+	numVertices = 0; numIndices = 0;
+	
+	//Calculate the pace, based on the lod.
+	int stride = 1 << _lod;
+		
+	bool adapt[4];
+	determineBorderAdaption( adapt );
+	assert( isVisible );
+#ifdef USE_VBO
+	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 ) {
+		tesselateLevelFourPage( adapt );
+		return;
+	}
+	
+	int zStart = 0, zEnd = owner->getPageSize()-stride;
+	
+	if ( adapt[TP_BOTTOM] ) {
+		tesselateBottomRow( 0, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+		zStart+= stride;
+	}
+	
+	if ( adapt[TP_TOP] )
+		zEnd-= stride;
+		
+	for ( int z = zStart; z < zEnd; z+=stride )
+		tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+	
+
+	if ( adapt[TP_TOP] ) {
+		tesselateTopRow( owner->getPageSize()-stride-1, 
+			stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
+	}
+	
+#ifdef USE_VBO
+	if ( vbIdentifier && ibIdentifier ) {
+		glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
+		indices = NULL;
+		glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB );
+		vertices = NULL;
+	}	
+#endif
+
+}
+
+
+void TerrainPage::show( )
+{
+	
+#ifdef USE_VBO	
+	//This is done later on...
+	//owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
+	vertices = NULL;
+	indices = NULL;
+#else
+	vertices = new Vertex[Terrain::MAX_VERTICES];
+	indices = new unsigned short[Terrain::MAX_INDICES];
+#endif	
+	vbIdentifier = 0; ibIdentifier = 0;
+	indexHash = new unsigned short[Terrain::MAX_VERTICES];	
+	forceTesselation = true;
+	activate();
+	active = true;
+}
+
+void TerrainPage::hide( )
+{
+#ifdef USE_VBO
+	owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );	
+#endif
+	SAVE_DELETE_ARRAY( vertices );
+	numVertices = 0;
+	SAVE_DELETE_ARRAY( indices );
+	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();
+}
+//TODO: put all the pages that have a coarses tesselation level than 4 into a
+//		separate list!
+void TerrainPage::draw( )
+{
+	assert( glIsEnabled( GL_VERTEX_ARRAY ) );
+	assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
+	
+	if ( currentLOD == TerrainPage::MAX_LODS-1 )
+		return;
+		
+	assert( isVisible ); assert( numIndices > 0 );
+	active = false;
+	CHECK_GL_ERROR( "1" );	
+#ifdef USE_VBO
+	
+	glBindBufferARB( GL_ARRAY_BUFFER_ARB, 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, ibIdentifier );	
+	
+	glDrawElements( GL_TRIANGLE_STRIP, numIndices, 
+					GL_UNSIGNED_SHORT, NULL );	
+#else	
+	glClientActiveTextureARB( GL_TEXTURE0_ARB );
+	glInterleavedArrays( GL_T2F_V3F, 0, vertices );
+	
+	glClientActiveTextureARB( GL_TEXTURE1_ARB );
+	glInterleavedArrays( GL_T2F_V3F, 0, vertices );
+	
+	glDrawElements( GL_TRIANGLE_STRIP, numIndices, 
+					GL_UNSIGNED_SHORT, indices );	
+#endif
+	
+
+	
+	if ( owner->debug() )
+		drawBox( );
+		
+	CHECK_GL_ERROR( "2" );	
+}
+
+unsigned 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].p );
+		getCoord( _x, _z, vertices[numVertices].t );
+		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, Vector& _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::setLayerVisibility( int _layer, LayerVisibility _lv )
+{
+	if ( hasfull ) return;
+	if ( _lv == LV_FULL ) {
+		for ( int i = 0; i < 8; ++i )
+			layerVisibility[i] = LV_NO;
+		if ( _layer )
+			hasfull = true;
+	}	
+	layerVisibility[_layer] = _lv;	
+}
+
+bool TerrainPage::hasMaterial( int _layer )
+{ 
+	return ( layerVisibility[_layer] != LV_NO );
+}
+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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 9414)
@@ -0,0 +1,320 @@
+/*
+	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
+#define USE_VBO
+#include "terrain_quad.h"
+#include <stdio.h>
+
+
+class TerrainPage;
+class Terrain;
+typedef TerrainPage *pTerrainPage;
+
+struct Vertex {
+	TexCoord 	t;	
+	Vector 		p;
+};
+
+typedef Vertex *pVertex;
+
+typedef struct {
+	Vector	correct;
+	Vector	real;
+	float	diff;
+} LODError, *pLODError;
+
+class TerrainPage : public TerrainQuad {
+	public:
+		enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 };
+		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 );
+		
+		/**
+		 * This is used only internally for communication between the TerrainPage and
+		 * the Terrain class itself.
+		 */
+		inline bool isActive() { return active; }
+		
+		virtual ~TerrainPage();
+		/**
+		 * @brief Makes the terrain look as if it were created with the given level of 
+		 * detail.
+		 */
+		void mimick( int _level ) {}
+		
+		/**
+		 * @brief Draws a box around the TerrainPage. For debugging purposes.
+		 */
+		void drawBox();
+		
+		/** 
+		 * @brief Calculates the smallest fitting axis aligned bounding box for this TerrainPage.
+		 */
+		virtual void calculateBounds();		
+		
+		
+		/**
+		 * @brief Sets the visibility to _flag. If the visibility changed, the vertex and 
+		 * index arrays are allocated or freed, respectively.
+		 */
+		inline void setVisibility( bool _flag );
+
+		/**
+		 * @brief Prepares the page for rendering.
+		 */
+		void show( );
+		
+		/**
+		 * @brief Frees most of the memory for economomical reasons.
+		 */
+		void hide( ); 
+		
+		/**
+		 * @brief Updates the tesselation if necessary.
+		 */
+		void updateTesselation( );
+		
+		/**
+		 * @return The current tesselation level.
+		 */
+		int getLOD() { return currentLOD; }
+		
+		/**
+		 * @return The curren tween factor. This is a floating point value  between 0.0f 
+		 * and 1.0f
+		 */
+		float getTween() { return 0.0f; }
+		
+		/**
+		 * @brief Determines the new LOD which should be used by this terrain page based on
+		 * the distance from the camera. 
+		 *
+		 * 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 recommondation for the LOD. It might be invalid due to outer 
+		 * constraints.
+		 */
+		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.
+		 * @return True if the page needs an update and false if not.
+		 */
+		bool isDirty() { return forceTesselation; }
+		
+		/**
+		 * @brief Calculates the maximal errors for every LOD.
+		 */
+		void calculateErrors();
+		
+		/**
+		 * @brief 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( );
+
+		bool needsRetesselation();
+		/**
+		 * 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;
+		}
+		
+		/**
+		 * Sets the position of the TerrainPage. Is this needed?
+		 */
+		inline void setPosition( const Vector& _pos )
+		{
+			position.x = _pos.x;
+			position.y = _pos.y;
+			position.z = _pos.z;
+		}
+
+		pTerrainPage getLeft() { return left; }
+		pTerrainPage getRight() { return right; }
+		pTerrainPage getBottom() { return bottom; }
+		pTerrainPage getTop() { return top; }						
+		
+		/**
+		 *  Does what exactly what the name says and nothing more.
+		 */
+		void draw( );
+		
+		/**
+		 * @return the next active page
+		 */
+		inline pTerrainPage getNext() { return next; }
+		void setLayerVisibility( int _layer, LayerVisibility _lv );
+		bool hasMaterial( int _layer );		
+		/**
+		 * Returns the previous active page
+		 */
+		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
+		 * chooseLOD() or you will get screwed values.
+		 */
+		inline int getWantedLOD() { return wantedLOD; }
+		
+		/**
+	 	 * @brief Removes the page from the active page list.
+		 */
+		void deactivate();
+		
+		/** 
+		 * @brief Inserts the page into the active page list.
+		 */
+		void activate();		
+
+		inline void setWantedLOD( int _lod )
+		{
+			if ( _lod >= TerrainPage::MAX_LODS )
+				wantedLOD = TerrainPage::MAX_LODS-1;
+			else if ( _lod < 0 )
+				wantedLOD = 0;
+			else
+				wantedLOD = _lod;
+		}
+				
+	protected:
+		
+		/**
+		 * @brief Tesselates one row of the terrain page.
+		 * @param _z 			The z-offset of the row
+		 * @param _xStride 		Defines the step-size horizontally
+		 * @param _zStride		Defines the step-size vertically.
+		 * @param _adaptLeft	True if the left neighbor has a coarser
+		 *						tesselation level.		
+		 * @param _adaptRight	True if the right neighbor has a coarser
+		 *						tesselation level.
+		 */
+		void tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight );
+		void tesselateTopRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight );
+		void tesselateBottomRow( int _z, int _stride, 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.
+		 */
+		void getVertex( int _x, int _z, Vector& _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. 
+		 */			
+		unsigned short getIndex( int _x, int _z );
+		void tesselateLevelFourPage( bool _adapt[] );
+	   /**
+		* 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;
+		pVertex						vertices;
+		unsigned short				*indices;
+		unsigned short				*indexHash;
+		int							numIndices;
+		int							numVertices;
+		LayerVisibility				layerVisibility[8];
+		bool						hasfull;
+#ifdef	USE_VBO
+		GLuint						ibIdentifier,
+									vbIdentifier;
+#endif		
+		bool						isVisible;
+		pTerrainPage				next;
+		pTerrainPage				previous;
+		LODError					*errors;
+		Vector						position;
+};
+
+inline void TerrainPage::setVisibility( bool _flag )
+{
+	if ( _flag ) {
+		if ( !isVisible ) {
+			isVisible = true;
+			show( );
+		}
+		active = true;
+	}
+	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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.cc	(revision 9414)
@@ -0,0 +1,57 @@
+/*
+	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();
+	children[0] = children[1] = children[2] = children[3] = NULL;
+}
+
+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 );
+	}	
+	Vector min = Vector( children[BL_CHILD]->getBounds().min() );
+	Vector max = Vector( 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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h	(revision 9414)
@@ -0,0 +1,101 @@
+/*
+	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]->isChildless() )
+					SAVE_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( Vector _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;
+		Vector			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 9414)
+++ branches/terrain/src/lib/graphics/importer/terrain/types.h	(revision 9414)
@@ -0,0 +1,182 @@
+/*
+        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>
+#include "texture.h"
+#include "plane.h"
+
+#define SAVE_DELETE_ARRAY( _a ) if ( _a ) { delete[] _a; _a = NULL; }
+#define SAVE_DELETE( _a ) if ( _a ) { delete _a; _a = NULL; }
+
+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( Vector _min, Vector _max)
+  {
+    corner = _min;
+    x = _max.x-_min.x;
+    y = _max.y-_min.y;
+    z = _max.z-_min.z;
+  }
+
+  ABox()
+  {
+    corner = Vector( 0.0f, 0.0f, 0.0f );
+    x = y = z = 0.0f;
+  }
+  inline void set( const Vector& _min, const Vector& _max )
+  {
+    setMin( _min ); setMax( _max );
+  }
+  inline void setMax( const Vector& _max )
+  {
+    x = _max.x-corner.x;
+    y = _max.y-corner.y;
+    z = _max.z-corner.z;
+  }
+  inline void setMin( const Vector& _min )
+  {
+    corner = _min;
+  }
+  inline Vector vertexP( const Vector& _normal ) const
+  {
+    Vector 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 Vector vertexN( const Vector& _normal ) const
+  {
+    Vector 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 Vector min() const { return Vector(corner); }
+  inline Vector max() const { return Vector( corner.x+x, corner.y+y, corner.z+z ); }
+  Vector corner;
+  float x, y, z;
+
+};
+
+// struct Plane
+// {
+//   Plane() { n = Vector( 0.0f, 1.0f, 0.0f ); d = 0.0f; }
+//   inline void setCoefficients( float _nx, float _ny, float _nz, float _d )
+//   {
+//     n = Vector( _nx, _ny, _nz );
+//     float l = n.length();
+//     n.x /= l; n.y/=l; n.z/=l;
+//     d = _d/l;
+//   }
+//   inline float distance( const Vector& _point ) const
+//   {
+//     return _point.x*n.x+_point.y*n.y+_point.z*n.z+d;
+//   }
+//   Vector 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;
+struct Heightfield
+{
+  int                     width;
+  int                     height;
+  int                             pitch;
+  UByte                   *data;
+  Heightfield() { data = NULL; width=0;height=0;pitch=0;}
+};
+
+struct LayerInfo
+{
+
+  int                             envmode;
+  float                   repeatX,
+  repeatZ;
+  Texture                 *alpha;
+  Texture                 *detail;
+
+};
+typedef enum { LV_FULL, LV_PARTIAL, LV_NO } LayerVisibility;
+
+struct BufferInfo
+{
+
+  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;
+  }
+  unsigned int    vbIdentifier,
+  ibIdentifier,
+  numIndices,
+  numVertices;
+};
+#endif
Index: branches/terrain/src/lib/sound/ogg_player.cc
===================================================================
--- branches/terrain/src/lib/sound/ogg_player.cc	(revision 9413)
+++ branches/terrain/src/lib/sound/ogg_player.cc	(revision 9414)
@@ -402,10 +402,10 @@
     if(size == 0)
       return false;
-/*#ifdef SDL_BIG_ENDIAN
-			int cnt = wavLength/2;
-			Uint16* wavBufferAsShorts = ( Uint16* )wavBuffer;
-			for ( int i = 0; i < cnt; ++i, ++wavBufferAsShorts )
-				*wavBufferAsShorts = SDL_Swap16( *wavBufferAsShorts );
-#endif*/
+#ifdef SDL_BIG_ENDIAN
+	int cnt = OGG_PLAYER_BUFFER_SIZE/2;
+	Uint16* wavBufferAsShorts = ( Uint16* )pcm;
+	for ( int i = 0; i < cnt; ++i, ++wavBufferAsShorts )
+		*wavBufferAsShorts = SDL_Swap16( *wavBufferAsShorts );
+#endif
     alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
     if (DEBUG_LEVEL >= 3)
Index: branches/terrain/src/lib/util/Makefile.am
===================================================================
--- branches/terrain/src/lib/util/Makefile.am	(revision 9413)
+++ branches/terrain/src/lib/util/Makefile.am	(revision 9414)
@@ -23,4 +23,5 @@
 		filesys/file.cc \
 		filesys/directory.cc \
+		filesys/binary_file.cc \
 		filesys/net_link.cc \
 		\
@@ -40,7 +41,9 @@
 		executor/executor_lua.h \
 		executor/functor_list.h \
+		byte_order.h \
 		\
 		filesys/file.h \
 		filesys/directory.h \
+		filesys/binary_file.h \
 		filesys/net_link.h \
 		\
Index: branches/terrain/src/lib/util/byte_order.h
===================================================================
--- branches/terrain/src/lib/util/byte_order.h	(revision 9414)
+++ branches/terrain/src/lib/util/byte_order.h	(revision 9414)
@@ -0,0 +1,33 @@
+#ifndef _BYTE_ORDER_H
+#define _BYTE_ORDER_H
+
+enum ByteOrder { LittleEndian = 1, BigEndian = 2 };
+
+#ifdef HAVE_SDL_SDL_H
+#include <SDL/SDL_byteorder.h>
+#else
+#include <SDL_byteorder.h>
+#endif
+
+
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define NATIVE_BYTEORDER LittleEndian
+#else
+#define NATIVE_BYTEORDER BigEndian
+#endif	
+
+
+inline void swap16( short *_s )
+{
+	char *ci = (char*)_s, tmp;
+	tmp = ci[0]; ci[0] = ci[1]; ci[1] = tmp;
+}
+
+inline void swap32( int *_i )
+{
+	char *ci = (char*)_i, tmp;
+	tmp = ci[0]; ci[0] = ci[3]; ci[3] = tmp;
+	tmp = ci[2]; ci[2] = ci[1]; ci[1] = tmp;
+}
+
+#endif
Index: branches/terrain/src/lib/util/filesys/binary_file.cc
===================================================================
--- branches/terrain/src/lib/util/filesys/binary_file.cc	(revision 9414)
+++ branches/terrain/src/lib/util/filesys/binary_file.cc	(revision 9414)
@@ -0,0 +1,205 @@
+#include "binary_file.h"
+#include <ctype.h>
+#include <stdlib.h>
+
+int bytesize( const char _c )
+{
+	switch( _c) {
+		case 'f':
+		case 'i':
+			return 4;
+		case 'b':
+			return 1;
+		case 's':
+			return 2;
+		default:
+			return 0;
+	}
+}
+
+pDataSemantics BinaryFile::compileSemantics( const char *_semantics )
+{
+	const char *curr = _semantics;
+	char *tmp = new char[strlen(_semantics)];
+	//Find out how many subchunks exist.
+	pDataSemantics chunk = new DataSemantics();
+	bool terminated = false;
+	int open = 0;
+	while ( *curr ) {
+		switch( *curr ) {
+			case 'i':
+			case 'f':
+			case 'b':
+			case 's':
+				chunk->numChunkNodes++;
+				break;
+			case '(':
+				terminated = false;
+				chunk->numChunkNodes++;
+				while ( *curr && terminated == false ) {
+					if ( *curr == ')' )
+						terminated = true;
+					curr++;
+				}
+				if ( !terminated ) {
+					printf( "Syntax error: ')' is missing" );
+					delete chunk;
+					return NULL;
+				}	
+				break;
+			default:
+				break;
+		}
+		curr++;
+	}
+	//Compile the chunks...
+	chunk->chunks = new pDataSemantics[chunk->numChunkNodes];
+	int currChunk = 0;
+	curr = _semantics;
+	while ( *curr ) {
+		switch( *curr ) {
+			case 'i':
+			case 'f':
+			case 'b':
+			case 's':
+				chunk->chunks[currChunk] = new DataSemantics();
+				chunk->chunks[currChunk]->isTerminal = true;	
+				chunk->chunks[currChunk]->type = bytesize( *curr );
+				chunk->chunks[currChunk]->totalSize = bytesize( *curr );						
+				currChunk++;
+				break;
+			case '(':
+				curr++;
+				open = 0;
+				memset( tmp, 0, strlen( _semantics ) );
+				char * cp = tmp;
+				while ( *curr ) {
+					if ( *curr == '(' )
+						open++;
+					if ( *curr == ')' ) {
+						if ( open )
+							open--;
+						else
+							break;
+					}
+					*cp = *curr;
+					cp++;
+					curr++;
+				}
+				*cp = '\0';
+				chunk->chunks[currChunk] = compileSemantics( tmp );
+				currChunk++;					
+				break;
+			case ')':
+				printf( "Syntax error: ')' shouldn't appear here\n" );
+				delete[] tmp; delete chunk;
+				return NULL;
+				break;
+			default:
+				int multiplier = 1, quantifier = 0;
+				const char *start = curr;
+				const char *end = curr;
+				while ( isdigit( *end ) ) {
+					end++;
+				}
+				for ( const char *d = end-1; d >=start; --d ) {
+					quantifier+=multiplier*(*d-'0');
+					multiplier*=10;
+				}
+				if ( start == end ) {
+					printf( "Syntax error: '%c' is not known.\n", *curr );
+					delete[] tmp; delete chunk;
+					return NULL;
+				}				
+				if ( currChunk ) {
+					chunk->chunks[currChunk-1]->quantifier = quantifier;
+					chunk->chunks[currChunk-1]->totalSize*= quantifier;					
+				}	
+				else {
+					printf( "Syntax error: Quantifier without a preceding type\n" );
+					delete[] tmp; delete chunk;
+					return NULL;
+				}
+				curr = end-1;
+				break;
+		}
+		curr++;
+	}
+	for ( int i = 0; i < chunk->numChunkNodes; ++i ) {
+		chunk->totalSize+= chunk->chunks[i]->totalSize;
+	}
+	delete[] tmp;
+	return chunk;
+}
+
+void convert_data( pDataSemantics _comp, void *_data )
+{
+	char *ptr = (char*)_data;
+	short *sptr;
+	int *iptr;
+	if ( _comp->isTerminal ) {
+		switch( _comp->type ) {
+			case TT_INT:
+				iptr = (int*)ptr;			
+				for ( int i = 0; i < _comp->quantifier; ++i ) {
+					swap32( iptr );
+					iptr++;
+				}
+				break;
+			case TT_SHORT:
+				sptr = (short*)ptr;
+				for ( int i = 0; i < _comp->quantifier; ++i ) {
+					swap16( sptr );
+					sptr++;
+				}			
+				break;
+			case TT_BYTE:
+				break;
+		}
+	}
+	else {
+		for ( int j = 0; j < _comp->quantifier; ++j ) {
+			for ( int i = 0; i < _comp->numChunkNodes; ++i ) {
+				convert_data( _comp->chunks[i], ptr );
+				ptr+= _comp->chunks[i]->totalSize;
+			}			
+		}
+
+	}	
+}
+void BinaryFile::read( const char *_semantics, int _chunks, 
+	void* _buf, size_t& _bytesRead )
+{
+	pDataSemantics comp = compileSemantics( _semantics );		
+	fread( _buf, comp->totalSize, _chunks, this->handle() );
+	if ( byteorder != NATIVE_BYTEORDER ) {
+		for ( int i = 0; i < _chunks; ++i ) {
+			convert_data( comp, (char*)_buf+i*comp->totalSize );
+		}	
+	}	
+	_bytesRead = comp->totalSize*_chunks;
+	delete comp;	
+}
+void BinaryFile::read( const char *_semantics, 
+	void* _buf, size_t& _bytesRead )
+{
+	pDataSemantics comp = compileSemantics( _semantics );		
+	fread( _buf, comp->totalSize, 1, this->handle() );
+	
+	if ( byteorder != NATIVE_BYTEORDER ) {
+		convert_data( comp, _buf );
+	}	
+	delete comp;		
+}
+
+void BinaryFile::write( const char *_semantics, 
+	void* _buf, size_t& _bytesWritten )
+{
+	pDataSemantics comp = compileSemantics( _semantics );
+	if ( byteorder != NATIVE_BYTEORDER ) {
+		convert_data( comp, _buf );
+	}	
+	_bytesWritten = comp->totalSize;
+	fwrite( _buf, comp->totalSize, 1, this->handle() );
+	delete comp;
+}
Index: branches/terrain/src/lib/util/filesys/binary_file.h
===================================================================
--- branches/terrain/src/lib/util/filesys/binary_file.h	(revision 9414)
+++ branches/terrain/src/lib/util/filesys/binary_file.h	(revision 9414)
@@ -0,0 +1,109 @@
+#ifndef _BINARY_FILE_H
+#define _BINARY_FILE_H
+
+#include <stdio.h>
+#include <string>
+#include "byte_order.h"
+#include "file.h"
+
+enum TerminalType 	{ TT_INT = 4, TT_BYTE = 1, TT_SHORT = 2 };
+
+/**
+ * Holds the compiled semantic-string.
+ */
+struct DataSemantics {
+
+	DataSemantics()
+	{
+		totalSize = 0; chunks = NULL;
+		quantifier = 1;
+		isTerminal = false;
+		numChunkNodes = 0;
+	}
+
+	~DataSemantics() 
+	{
+		delete[] chunks;
+	}
+	
+	int 			totalSize;
+	int 			quantifier;
+	int 			numChunkNodes;
+	bool 			isTerminal;
+	union {
+		int				type;
+		DataSemantics	**chunks; 
+	};	
+};
+
+typedef DataSemantics *pDataSemantics;
+
+class BinaryFile : public File {
+	public:		
+		BinaryFile()
+			: 	File( "" ),
+				byteorder( NATIVE_BYTEORDER )
+		{ /* nothing to be done */ }
+		
+		BinaryFile( const std::string& _file )
+			: 	File( _file ), 
+				byteorder( NATIVE_BYTEORDER )
+		{ /* nothing to be done */ }
+
+		BinaryFile( const BinaryFile& _file )
+			: 	File( _file.name() ), 
+				byteorder( _file.getByteorder() )
+		{ /* nothing to be done */ }
+		
+		/**
+		 * Reads a chunk of data based on the _semantics string. The string contains
+		 * a description of how the bytes are laid out in the file. If you want
+		 * to read out a struct which looks like this
+		 * struct {
+		 *		int 	magic;
+		 *		short	size;
+		 *		float	x, y, z;
+		 * };
+		 * then the semantics string is "isf3". If you want to read 5 of these
+		 * chunks, just put the whole string into paranthesis. "(isf3)5". Nifty, isn't
+		 * it?
+		 */
+		void read( const char *_semantics, void* _buf, size_t& _bytesRead );
+		
+		/**
+		 * The same as the read above, but with the ability to read multiple
+		 * chunks once. Very useful if you don't know how many chunks you're 
+		 * going to read at compile time.
+		 */
+		void read( const char *_semantics, int _chunks, 
+			void* _buf, size_t& _bytesRead );
+		/**
+		 * Writes a chunk of data based on the _semantics string. The string contains
+		 * a description of how the bytes should be laid out in the file. Have a look
+		 * at the description to read().
+		 */
+		void write( const char *_semantics, void* _buf, size_t& _bytesWritten );
+		inline void seekg( int _pos )
+		{
+			fseek( handle(), _pos, SEEK_SET );
+		}
+		/**
+		 * @brief Sets the byteorder of the file. The order affects all subsequent
+		 * calls to write() and read(). It it is not wise to change the order
+		 * in the middle of reading a file. You're totally on your own.
+		 */
+		inline void setByteorder( ByteOrder _order ) 
+		{ byteorder = _order; }
+		
+		/**
+		 * Returns the file's byte-order.
+		 */
+		inline ByteOrder getByteorder() const
+		{ return byteorder; }
+		
+	private:
+		pDataSemantics compileSemantics( const char *_semantics );	
+		ByteOrder 		byteorder;
+};
+
+#endif
Index: branches/terrain/src/lib/util/filesys/file.cc
===================================================================
--- branches/terrain/src/lib/util/filesys/file.cc	(revision 9413)
+++ branches/terrain/src/lib/util/filesys/file.cc	(revision 9414)
@@ -155,14 +155,21 @@
 }
 
-bool File::open(OpenMode mode)
-{
-#warning implement
-  return false;
+bool File::open( OpenMode mode )
+{
+   static const char* openModeStrings[] = {
+			"r", "w", "r+", "a+" };	
+	_mode = mode;
+	_handle = fopen( name().c_str(), openModeStrings[mode] );
+	return ( _handle != NULL );
 }
 
 bool File::close()
 {
-#warning implement
-  return false;
+	if ( _handle != NULL ) {
+		int success = fclose( _handle );
+		_handle = NULL;		
+		return ( success == 0 );
+	}
+	return false;
 }
 
Index: branches/terrain/src/lib/util/filesys/file.h
===================================================================
--- branches/terrain/src/lib/util/filesys/file.h	(revision 9413)
+++ branches/terrain/src/lib/util/filesys/file.h	(revision 9414)
@@ -16,12 +16,10 @@
   public:
   //! How the File should be opened.
-  typedef enum
-  {
-    ReadOnly,      //!< ReadOnly mode
-    WriteOnly,     //!< WriteOnly mode
-    ReadWrite,     //!< Read and Write mode together
-    Append,        //!< Append at the end.
+  typedef enum {
+    ReadOnly 	= 0,     //!< ReadOnly mode
+    WriteOnly 	= 1,     //!< WriteOnly mode
+    ReadWrite	= 2,     //!< Read and Write mode together
+    Append 		= 3      //!< Append at the end.
   } OpenMode;
-
 public:
   File();
@@ -41,6 +39,8 @@
   virtual bool open(OpenMode mode);
   virtual bool close();
-  int handle() const { return this->_handle; };
-
+  FILE* handle() const 
+  { return this->_handle; };
+  inline OpenMode mode() const
+  { return _mode; }
   /** @returns the FileName of this File */
   const std::string& name() const { return this->_name; };
@@ -73,8 +73,8 @@
 
   private:
-    int                 _handle;          //!< The FileHandle (if set).
+    FILE*               _handle;          //!< The FileHandle (if set).
     std::string         _name;            //!< The Name of the File.
     stat*               _status;          //!< The Stat of the File.
-
+	OpenMode			_mode;
     static std::string  _cwd;             //!< The currend Working directory.
 
