Index: /branches/terrain/src/defs/debug.h
===================================================================
--- /branches/terrain/src/defs/debug.h	(revision 9139)
+++ /branches/terrain/src/defs/debug.h	(revision 9140)
@@ -111,4 +111,10 @@
 #define PRINTFORX_VDEBUG  PRINTF5
 
+#ifndef ORX_DATADIR
+#define ORX_DATADIR "/usr/share"
+#endif
+#ifndef DEBUG_LEVEL
+#define DEBUG_LEVEL 2
+#endif
 #if DEBUG_LEVEL <= 3
 #define PRINTF(x)        PRINT(x)
Index: /branches/terrain/src/defs/glincl.h
===================================================================
--- /branches/terrain/src/defs/glincl.h	(revision 9139)
+++ /branches/terrain/src/defs/glincl.h	(revision 9140)
@@ -17,4 +17,5 @@
 #include <OpenGL/gl.h>
 #include <OpenGL/glu.h>
+#include <OpenGL/glext.h>
 #endif
 
Index: /branches/terrain/src/lib/collision_detection/cd_engine.cc
===================================================================
--- /branches/terrain/src/lib/collision_detection/cd_engine.cc	(revision 9139)
+++ /branches/terrain/src/lib/collision_detection/cd_engine.cc	(revision 9140)
@@ -24,5 +24,5 @@
 #include "model.h"
 #include "world_entity.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 // #include "player.h"
 
@@ -45,5 +45,5 @@
 
   this->bAbordOnFirstCollision = false;
-  
+
   this->terrain = NULL;
 }
@@ -106,15 +106,40 @@
   std::list<WorldEntity*>::iterator entityIterator;
   const std::list<BaseObject*>* bspList = ClassList::getList(CL_BSP_ENTITY);
-  if( bspList == NULL)
-    return;
+  if( bspList != NULL)
+  {
 
-  // for all bsp managers check all entities
-  for( bspIterator = bspList->begin(); bspIterator != bspList->end(); bspIterator++) {
+    // for all bsp managers check all entities
+    for( bspIterator = bspList->begin(); bspIterator != bspList->end(); bspIterator++)
+    {
       for(entityIterator = list1.begin(); entityIterator != list1.end(); entityIterator++)
       {
-//         PRINTF(0)("Checking: %s a %s\n", (*entityIterator)->getName(), (*entityIterator)->getClassName());
+        //               PRINTF(0)("Checking: %s a %s\n", (*entityIterator)->getName(), (*entityIterator)->getClassName());
         (dynamic_cast<BspEntity*>(*bspIterator)->getBspManager())->checkCollision(*entityIterator);
       }
+    }
   }
+
+  /// COLLISION OF THE Modular-TERRAIN
+/*  const std::list<BaseObject*>* tl = ClassList::getList( CL_TERRAIN );
+  std::list<BaseObject*>::const_iterator ti;
+  if ( tl == NULL )
+    return;
+  float offset = 8.0f;
+  for ( ti = tl->begin(); ti != tl->end(); ++ti )
+  {
+    TerrainEntity* terrain = dynamic_cast<TerrainEntity*>( *ti );
+    for( entityIterator = list1.begin(); entityIterator != list1.end(); entityIterator++ )
+    {
+      Vector pos( (*entityIterator)->getAbsCoor() );
+      Vector normal;
+      float height = pos.y;
+      terrain->getAltitude( pos, normal );
+      if ( height-offset < pos.y )
+      {
+        ( *entityIterator )->registerCollision(
+          *entityIterator, terrain, pos, normal );
+      }
+    }
+  }*/
 }
 
@@ -138,6 +163,6 @@
 void CDEngine::debugSpawnTree(int depth, sVec3D* vertices, int numVertices)
 {
-//   if ( this->rootTree == NULL)
-//     this->rootTree = new OBBTree(depth, vertices, numVertices);
+  //   if ( this->rootTree == NULL)
+  //     this->rootTree = new OBBTree(depth, vertices, numVertices);
 }
 
@@ -156,5 +181,5 @@
 void CDEngine::debugDraw(int depth, int drawMode)
 {
-//   if(this-> rootTree != NULL)
-//     this->rootTree->drawBV(depth, drawMode);
+  //   if(this-> rootTree != NULL)
+  //     this->rootTree->drawBV(depth, drawMode);
 }
Index: /branches/terrain/src/lib/collision_detection/cd_engine.h
===================================================================
--- /branches/terrain/src/lib/collision_detection/cd_engine.h	(revision 9139)
+++ /branches/terrain/src/lib/collision_detection/cd_engine.h	(revision 9140)
@@ -16,5 +16,5 @@
 class WorldEntity;
 class OBBTree;
-class Terrain;
+class TerrainEntity;
 class BspManager;
 //class Player;
@@ -50,5 +50,5 @@
   inline void disable(const int options) { int temp = this->state & options; this->state ^= temp; }
 
-  inline void setTerrain(Terrain* terrain) { this->terrain = terrain; }
+  inline void setTerrain( TerrainEntity* terrain) { this->terrain = terrain; }
   inline void setBSPModel(BspManager* bspManager) { this->bspManager = bspManager; }
 
@@ -83,5 +83,5 @@
   OBBTree*                rootTree;                         //!< for testing purposes a root tree
 
-  Terrain*                terrain;                          //!< this it a ref to the terrain, serving as a ground for all WE
+  TerrainEntity*                terrain;                          //!< this it a ref to the terrain, serving as a ground for all WE
   BspManager*             bspManager;
 };
Index: /branches/terrain/src/lib/graphics/effects/volfog_effect.cc
===================================================================
--- /branches/terrain/src/lib/graphics/effects/volfog_effect.cc	(revision 9139)
+++ /branches/terrain/src/lib/graphics/effects/volfog_effect.cc	(revision 9140)
@@ -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
 
 using namespace std;
Index: /branches/terrain/src/lib/graphics/graphics_engine.cc
===================================================================
--- /branches/terrain/src/lib/graphics/graphics_engine.cc	(revision 9139)
+++ /branches/terrain/src/lib/graphics/graphics_engine.cc	(revision 9140)
@@ -236,5 +236,6 @@
   // Enable default GL stuff
   glEnable(GL_DEPTH_TEST);
-
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_FRONT);
   Render2D::getInstance();
 
@@ -297,6 +298,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 9139)
+++ /branches/terrain/src/lib/graphics/importer/Makefile.am	(revision 9140)
@@ -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/material.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/material.h	(revision 9139)
+++ /branches/terrain/src/lib/graphics/importer/material.h	(revision 9140)
@@ -61,5 +61,4 @@
   void setSpecularMap(const std::string& sMap, GLenum target = GL_TEXTURE_2D);
   void setBump(const std::string& bump);
-
   GLuint diffuseTextureID(unsigned int i = 0) const { return (this->textures.size() > i)? this->textures[i].getTexture() : 0; };
 
Index: /branches/terrain/src/lib/graphics/importer/md2/md2Model.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/md2/md2Model.cc	(revision 9139)
+++ /branches/terrain/src/lib/graphics/importer/md2/md2Model.cc	(revision 9140)
@@ -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"
@@ -66,5 +73,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
 
 /********************************************************************************
@@ -467,6 +490,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());
@@ -474,5 +498,5 @@
     }
 
-  this->fileName =fileName;
+  this->fileName = fileName;
   /* got the data: map it to locals */
   this->numFrames = this->header->numFrames;
@@ -493,18 +517,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_data.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/md3/md3_data.h	(revision 9139)
+++ /branches/terrain/src/lib/graphics/importer/md3/md3_data.h	(revision 9140)
@@ -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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/buffer_broker.h	(revision 9140)
@@ -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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/frustum.cc	(revision 9140)
@@ -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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/frustum.h	(revision 9140)
@@ -0,0 +1,129 @@
+/*
+	orxonox - the future of 3D-vertical-scrollers
+ 
+	Copyright (C) 2006 orx
+ 
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2, or (at your option)
+	any later version.
+ 
+	### File Specific:
+	main programmer: Marco Biasini
+ 
+ */
+#ifndef _FRUSTUM_H
+#define _FRUSTUM_H
+#include "types.h"
+#include "glincl.h"
+#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].distance( _box.vertexP( planes[i].n ) ) < 0 )
+					return OUTSIDE;
+				// is the negative vertex outside?	
+				else if ( planes[i].distance( _box.vertexN( planes[i].n ) ) < 0 )
+					result = INTERSECT;
+			}
+			return result;
+		}
+		
+		inline int pointInFrustum( const Triple& _point)
+		{
+			int result = INSIDE;
+			for(int i=0; i < 6; i++) {
+				if (planes[i].distance( _point ) < 0)
+					return OUTSIDE;
+			}
+			return result;		
+		}
+		
+		inline Plane getPlane( int _plane ) { return planes[_plane]; }
+		inline void setFrustum( float *_m )
+		{
+			planes[NEAR].setCoefficients( m(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].setCoefficients( -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].setCoefficients( 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].setCoefficients(  -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].setCoefficients(  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].setCoefficients(-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].d +planes[FAR].d  > MAX_CLIP_DISTANCE ) {
+				planes[FAR].d = -planes[NEAR].d+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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain.cc	(revision 9140)
@@ -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( Triple( 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.d };
+	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( Triple& _alt, Triple& _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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain.h	(revision 9140)
@@ -0,0 +1,231 @@
+/*
+	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 "types.h"
+#include "terrain_page.h"
+#include "terrain_quad.h"
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include "texture.h"
+#include "frustum.h"
+
+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 Triple& _cameraPosition ) 
+		{ 
+			cameraPosition = _cameraPosition; 
+		}
+		
+		inline const Triple& getCameraPosition() const
+		{
+			return cameraPosition;
+		}
+	
+		void getAltitude( Triple& _alt, Triple& _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  = Triple( 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 Triple& _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 Triple getScale() const { return scale; }
+		
+		inline int getPageSize() const 
+		{
+			return pageSize;
+		}
+		
+		inline void getCoord( int _x, int _z, TexCoord& _coord) const
+		{
+			_coord.u = ( ( float )_x )/( heightfield.width-1 );
+			_coord.v = ( ( float )_z )/( heightfield.height-1 );			
+		}
+		
+		inline void setScale( const Triple& _scale )
+		{ scale = _scale; }
+#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;
+		Triple						scale;
+		int 						pagesX, 
+									pagesZ;
+		int							pageSize;	
+		int							cullCount;
+		
+		int							activatedCount, 
+									deactivatedCount; // For debugging and statistics
+								
+		//The next five members are for the level 4 pages.						
+		Vertex						*vertices;						
+		unsigned short				*indices;
+		int							current;
+									
+		std::vector<BufferInfo>		buffers;			
+			
+		Triple						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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc	(revision 9140)
@@ -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 = Triple( 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;
+	Triple cam( owner->getCameraPosition() );
+	
+	for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) {
+		Triple distance( cam.x-errors[i].correct.x,
+						 cam.y-errors[i].correct.y,
+						 cam.z-errors[i].correct.z );
+		
+		float d = distance.length();
+		
+		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;
+	
+	Triple	min( xOffset*scale.x ,0.0f, zOffset*scale.z ), 
+			max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z);
+	
+	min.y = max.y = getAltitude( 0, 0 );
+	for ( int x = 0; x < size; ++x ) {
+		for ( int z = 0; z < size; ++z ) {
+			alt = getAltitude( x, z );
+			min.y = fmin( min.y, alt-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, Triple& _vertex ) const
+{
+	_vertex.x = position.x+scale.x*_x/
+		( owner->getPageSize()-1 );
+	_vertex.y = getAltitude( _x, _z );
+	_vertex.z = position.z+scale.z*_z/( owner->getPageSize()-1 );
+}
+void TerrainPage::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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h	(revision 9140)
@@ -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;	
+	Triple 		p;
+};
+
+typedef Vertex *pVertex;
+
+typedef struct {
+	Triple	correct;
+	Triple	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 Triple& _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, Triple& _vertex ) const;
+		
+	 	/**
+		 * Use this method to safely get a vertex at location ( _x, _z ). If it wasn't
+		 * created before, this method does that for you. 
+		 */			
+		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;
+		Triple						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 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.cc	(revision 9140)
@@ -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 );
+	}	
+	Triple min = Triple( children[BL_CHILD]->getBounds().min() );
+	Triple max = Triple( children[TR_CHILD]->getBounds().max() );
+	for ( int i = 1; i < 4; ++i ) {
+		pTerrainQuad child = children[i];
+		min.y = fmin( child->bounds.min().y, min.y );
+		max.y = fmax( child->bounds.max().y, max.y );		
+	}
+	bounds.set( min, max );
+}
Index: /branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h	(revision 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/terrain_quad.h	(revision 9140)
@@ -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( Triple _scale )
+		{
+			scale = _scale;
+		}
+		inline const ABox getBounds() { return bounds; }
+		inline void setChildren( pTerrainQuad _bl, pTerrainQuad _br, pTerrainQuad _tl,
+			pTerrainQuad _tr )
+		{
+			children[TL_CHILD] = _tl;
+			children[TR_CHILD] = _tr;
+			children[BR_CHILD] = _br;
+			children[BL_CHILD] = _bl;
+		}
+		/**
+		 * Calculates the mininum and maximum value of this box based on the size
+		 * and position of its children.
+		 */
+		virtual void calculateBounds( );
+		inline int getXOffset() { return xOffset; }
+		inline int getZOffset() { return zOffset; }
+		inline int getWidth() { return width; }
+		inline int getHeight() { return height; }
+		
+	protected:
+		TerrainQuad( ) {}
+		Terrain			*owner;
+		int				xOffset, zOffset;
+		int				width,	height;
+		Triple			scale;
+		pTerrainQuad 	children[4];
+		ABox			bounds;
+};
+
+#endif
Index: /branches/terrain/src/lib/graphics/importer/terrain/types.h
===================================================================
--- /branches/terrain/src/lib/graphics/importer/terrain/types.h	(revision 9140)
+++ /branches/terrain/src/lib/graphics/importer/terrain/types.h	(revision 9140)
@@ -0,0 +1,194 @@
+/*
+        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 Triple
+{
+  Triple( float _x, float _y, float _z )
+  {
+    x = _x; y = _y; z = _z;
+  }
+  Triple() { x = y = z = 0.0f; }
+  inline float length() const
+    { return sqrt( x*x+y*y+z*z ); }
+  float x, y, z;
+};
+
+struct TexCoord
+{
+  TexCoord( float _u, float _v )
+  {
+    u = _u; v = _v;
+  }
+  TexCoord() { u = v = 0.0f; }
+  float u, v;
+};
+
+/**
+ * Defines an axis aligned box.
+ */
+struct ABox
+{
+
+  ABox( Triple _min, Triple _max)
+  {
+    corner = _min;
+    x = _max.x-_min.x;
+    y = _max.y-_min.y;
+    z = _max.z-_min.z;
+  }
+
+  ABox()
+  {
+    corner = Triple( 0.0f, 0.0f, 0.0f );
+    x = y = z = 0.0f;
+  }
+  inline void set( const Triple& _min, const Triple& _max )
+  {
+    setMin( _min ); setMax( _max );
+  }
+  inline void setMax( const Triple& _max )
+  {
+    x = _max.x-corner.x;
+    y = _max.y-corner.y;
+    z = _max.z-corner.z;
+  }
+  inline void setMin( const Triple& _min )
+  {
+    corner = _min;
+  }
+  inline Triple vertexP( const Triple& _normal ) const
+  {
+    Triple res = corner;
+    if ( _normal.x > 0 )
+      res.x+= x;
+    if ( _normal.y > 0 )
+      res.y+= y;
+    if ( _normal.z > 0 )
+      res.z+= z;
+
+    return res;
+  }
+  inline Triple vertexN( const Triple& _normal ) const
+  {
+    Triple res = corner;
+    if ( _normal.x < 0 )
+      res.x+= x;
+    if ( _normal.y < 0 )
+      res.y+= y;
+    if ( _normal.z < 0 )
+      res.z+= z;
+
+    return res;
+
+  }
+inline Triple min() const { return Triple(corner); }
+  inline Triple max() const { return Triple( corner.x+x, corner.y+y, corner.z+z ); }
+  Triple corner;
+  float x, y, z;
+
+};
+
+// struct Plane
+// {
+//   Plane() { n = Triple( 0.0f, 1.0f, 0.0f ); d = 0.0f; }
+//   inline void setCoefficients( float _nx, float _ny, float _nz, float _d )
+//   {
+//     n = Triple( _nx, _ny, _nz );
+//     float l = n.length();
+//     n.x /= l; n.y/=l; n.z/=l;
+//     d = _d/l;
+//   }
+//   inline float distance( const Triple& _point ) const
+//   {
+//     return _point.x*n.x+_point.y*n.y+_point.z*n.z+d;
+//   }
+//   Triple n;
+//   float d;
+// };
+
+/**
+ * TODO: Replace this method with the actual matrix multiplication code!
+ */
+inline void multMat(float *res,float *a, float *b)
+{
+
+
+  for (int i=0;i<4;i++)
+  {
+    for (int j = 0;j < 4;j++)
+    {
+      res[i*4+j] = 0.0;
+      for (int k = 0; k < 4; k++)
+      {
+        res[i*4+j] += a[i*4+k] * b[k*4+j];
+      }
+    }
+  }
+}
+typedef unsigned char UByte;
+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/graphics/importer/texture.cc
===================================================================
--- /branches/terrain/src/lib/graphics/importer/texture.cc	(revision 9139)
+++ /branches/terrain/src/lib/graphics/importer/texture.cc	(revision 9140)
@@ -332,5 +332,5 @@
   else
   {
-    assert(surface->format->BitsPerPixel == 24);
+    //assert(surface->format->BitsPerPixel == 24);
   }
 
Index: /branches/terrain/src/lib/sound/ogg_player.cc
===================================================================
--- /branches/terrain/src/lib/sound/ogg_player.cc	(revision 9139)
+++ /branches/terrain/src/lib/sound/ogg_player.cc	(revision 9140)
@@ -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/threading.h
===================================================================
--- /branches/terrain/src/lib/util/threading.h	(revision 9139)
+++ /branches/terrain/src/lib/util/threading.h	(revision 9140)
@@ -14,5 +14,5 @@
  #include <SDL/SDL_thread.h>
 #endif
-
+#include <string>
 namespace OrxThread
 {
@@ -31,6 +31,4 @@
     void start();
     void terminate();
-
-
   private:
     SDL_Thread* thread;
Index: /branches/terrain/src/orxonox.cc
===================================================================
--- /branches/terrain/src/orxonox.cc	(revision 9139)
+++ /branches/terrain/src/orxonox.cc	(revision 9140)
@@ -27,5 +27,4 @@
 #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ORXONOX
 #include "orxonox.h"
-
 #include "globals.h"
 
@@ -519,9 +518,5 @@
   // checking for existence of the configuration-files, or if the lock file is still used
   if (showGui || (!File("./orxonox.conf").isFile() &&
-                  !File(DEFAULT_CONFIG_FILE).isFile())
-#if DEBUG_LEVEL <= 3 // developers do not need to see the GUI, when orxonox fails
-      || ResourceManager::isFile(DEFAULT_LOCK_FILE)
-#endif
-     )
+                  !File(DEFAULT_CONFIG_FILE).isFile() ) )
   {
     File lockFile(DEFAULT_LOCK_FILE);
Index: /branches/terrain/src/story_entities/game_world.cc
===================================================================
--- /branches/terrain/src/story_entities/game_world.cc	(revision 9139)
+++ /branches/terrain/src/story_entities/game_world.cc	(revision 9140)
@@ -30,7 +30,6 @@
 #include "camera.h"
 #include "environment.h"
-#include "terrain.h"
 #include "test_entity.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 #include "playable.h"
 #include "environments/mapped_water.h"
Index: /branches/terrain/src/story_entities/game_world_data.cc
===================================================================
--- /branches/terrain/src/story_entities/game_world_data.cc	(revision 9139)
+++ /branches/terrain/src/story_entities/game_world_data.cc	(revision 9140)
@@ -31,5 +31,5 @@
 #include "player.h"
 #include "camera.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 #include "skybox.h"
 #include "md2/md2Model.h"
@@ -209,5 +209,5 @@
       BaseObject* created = Factory::fabricate(element);
       if( created != NULL )
-        PRINTF(4)("Created a %s: %s\n", created->getClassName(), created->getName());
+        PRINTF(2)("Created a %s: %s\n", created->getClassName(), created->getName());
 
       //todo do this more elegant
@@ -217,7 +217,8 @@
         State::setSkyBox(dynamic_cast<SkyBox*>(this->sky));
       }
-      if( element->Value() == "Terrain" && created->isA(CL_TERRAIN))
+		
+      if( element->Value() == "TerrainEntity" && created->isA(CL_TERRAIN))
       {
-        this->terrain = dynamic_cast<Terrain*>(created);
+        this->terrain = dynamic_cast<TerrainEntity*>(created);
         CDEngine::getInstance()->setTerrain(terrain);
       }
Index: /branches/terrain/src/story_entities/game_world_data.h
===================================================================
--- /branches/terrain/src/story_entities/game_world_data.h	(revision 9139)
+++ /branches/terrain/src/story_entities/game_world_data.h	(revision 9140)
@@ -14,5 +14,5 @@
 class Camera;
 class Player;
-class Terrain;
+class TerrainEntity;
 class WorldEntity;
 
@@ -57,5 +57,5 @@
     Player*                       localPlayer;    //!< The player, you fly through the level.
     WorldEntity*                  sky;            //!< The environmental sky of orxonox
-    Terrain*                      terrain;        //!< The terrain - ground
+    TerrainEntity*                terrain;        //!< The terrain - ground
 
     OrxSound::OggPlayer*          music;          //!< Reference to the SoundEngine's music player (OggPlayer)
Index: /branches/terrain/src/story_entities/multi_player_world_data.cc
===================================================================
--- /branches/terrain/src/story_entities/multi_player_world_data.cc	(revision 9139)
+++ /branches/terrain/src/story_entities/multi_player_world_data.cc	(revision 9140)
@@ -31,7 +31,6 @@
 #include "camera.h"
 #include "environment.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 #include "test_entity.h"
-#include "terrain.h"
 #include "md2/md2Model.h"
 #include "world_entities/projectiles/projectile.h"
@@ -157,5 +156,5 @@
         if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
         {
-          this->terrain = dynamic_cast<Terrain*>(created);
+          this->terrain = dynamic_cast<TerrainEntity*>(created);
           CDEngine::getInstance()->setTerrain(terrain);
         }
@@ -188,5 +187,5 @@
           if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
           {
-            this->terrain = dynamic_cast<Terrain*>(created);
+            this->terrain = dynamic_cast<TerrainEntity*>(created);
             CDEngine::getInstance()->setTerrain(terrain);
           }
Index: /branches/terrain/src/story_entities/simple_game_menu.cc
===================================================================
--- /branches/terrain/src/story_entities/simple_game_menu.cc	(revision 9139)
+++ /branches/terrain/src/story_entities/simple_game_menu.cc	(revision 9140)
@@ -31,5 +31,5 @@
 #include "world_entity.h"
 #include "elements/image_entity.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 #include "camera.h"
 
Index: /branches/terrain/src/util/multiplayer_team_deathmatch.cc
===================================================================
--- /branches/terrain/src/util/multiplayer_team_deathmatch.cc	(revision 9139)
+++ /branches/terrain/src/util/multiplayer_team_deathmatch.cc	(revision 9140)
@@ -32,5 +32,5 @@
 
 #include "shared_network_data.h"
-#include "terrain.h"
+#include "terrain_entity.h"
 #include "class_list.h"
 #include "space_ships/space_ship.h"
Index: /branches/terrain/src/world_entities/WorldEntities.am
===================================================================
--- /branches/terrain/src/world_entities/WorldEntities.am	(revision 9139)
+++ /branches/terrain/src/world_entities/WorldEntities.am	(revision 9140)
@@ -12,5 +12,5 @@
                 world_entities/skybox.cc \
                 world_entities/skydome.cc \
-                world_entities/terrain.cc \
+                world_entities/terrain_entity.cc \
                 world_entities/satellite.cc \
                 world_entities/movie_entity.cc \
@@ -77,5 +77,5 @@
                 skybox.h \
                 skydome.h \
-                terrain.h \
+                terrain_entity.h \
                 satellite.h \
                 movie_entity.h \
Index: /branches/terrain/src/world_entities/camera.cc
===================================================================
--- /branches/terrain/src/world_entities/camera.cc	(revision 9139)
+++ /branches/terrain/src/world_entities/camera.cc	(revision 9140)
@@ -34,7 +34,7 @@
   this->subscribeEvent(ES_GAME, KeyMapper::PEV_VIEW5);
 
-  this->setFovy(90);
+  this->setFovy(90.0);
   this->setAspectRatio(1.2f);
-  this->setClipRegion(.1, 2000);
+  this->setClipRegion( .1, 40.0f );
 
   this->setViewMode(Camera::ViewNormal);
Index: /branches/terrain/src/world_entities/playable.cc
===================================================================
--- /branches/terrain/src/world_entities/playable.cc	(revision 9139)
+++ /branches/terrain/src/world_entities/playable.cc	(revision 9140)
@@ -69,5 +69,5 @@
   //subscribe to collision reaction
   this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_BSP_ENTITY);
-
+	this->subscribeReaction(CREngine::CR_PHYSICS_GROUND_WALK, CL_TERRAIN );
   registerVar( new SynchronizeableInt( &score, &score, "score" ) );
   registerVar( new SynchronizeableBool( &bFire, &bFire, "bFire", PERMISSION_OWNER));
Index: /branches/terrain/src/world_entities/skybox.cc
===================================================================
--- /branches/terrain/src/world_entities/skybox.cc	(revision 9139)
+++ /branches/terrain/src/world_entities/skybox.cc	(revision 9140)
@@ -230,5 +230,5 @@
 //   glPushAttrib(GL_LIGHTING_BIT);
   glDisable(GL_LIGHTING);
-
+  glDisable( GL_DEPTH_TEST );	
   glDisable(GL_FOG);
 
Index: anches/terrain/src/world_entities/terrain.cc
===================================================================
--- /branches/terrain/src/world_entities/terrain.cc	(revision 9139)
+++ 	(revision )
@@ -1,431 +1,0 @@
-/*
-   orxonox - the future of 3D-vertical-scrollers
-
-   Copyright (C) 2004 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: Benjamin Grauer
-   co-programmer: ...
-*/
-#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
-
-
-#include "terrain.h"
-
-#include "util/loading/load_param.h"
-#include "util/loading/factory.h"
-#include "spatial_separation.h"
-
-#include "util/loading/resource_manager.h"
-#include "model.h"
-#include "network_game_manager.h"
-
-#include "height_map.h"
-#include "material.h"
-
-#include "glincl.h"
-
-#include "state.h"
-
-using namespace std;
-
-CREATE_FACTORY(Terrain, CL_TERRAIN);
-
-/**
- *  standard constructor
- */
-Terrain::Terrain (const TiXmlElement* root)
-{
-  this->init();
-
-
-  if( root != NULL)
-    this->loadParams(root);
-
-  //  if (this->model != NULL)
-  //this->ssp = new SpatialSeparation((Model*)this->model, 10.0f);
-}
-
-
-/**
- *  Constructor for loading a Terrain out of a file
- * @param fileName The file to load data from.
-
-   this either loads out of an OBJ-file, or loads a heightmap if no .obj-extension is found.
-*/
-Terrain::Terrain(const std::string& fileName)
-{
-  this->init();
-
-  if (fileName.rfind(".obj" ) != std::string::npos || fileName.rfind(".OBJ") != std::string::npos )
-  {
-    this->loadModel(fileName);
-  }
-  else
-  {
-    // load the hightMap here.
-  }
-}
-
-/**
- *  a Constructor for the Debug-Worlds
- */
-Terrain::Terrain(DebugTerrain debugTerrain)
-{
-  this->init();
-  this->buildDebugTerrain(debugTerrain);
-}
-
-/**
- *  standard deconstructor
-
-*/
-Terrain::~Terrain ()
-{
-  if (objectList)
-    glDeleteLists(this->objectList, 1);
-  if( this->ssp)
-    delete ssp;
-  if (this->vegetation)
-  {
-    ResourceManager::getInstance()->unload(this->vegetation);
-  }
-
-  if(this->heightMap)
-    delete heightMap;
-}
-
-
-void Terrain::init()
-{
-  this->setClassID(CL_TERRAIN, "Terrain");
-  this->toList(OM_ENVIRON_NOTICK);
-  this->toReflectionList();
-
-  this->objectList = 0;
-  this->ssp = NULL;
-  this->vegetation = NULL;
-
-  this->heightMap = NULL;
-
-  this->heightMapMaterial = new Material();
-}
-
-
-void Terrain::loadParams(const TiXmlElement* root)
-{
-  WorldEntity::loadParams(root);
-
-  LoadParam(root, "scale", this, Terrain, setScale)
-  .describe("The scale in x,y,z direction");
-
-  LoadParam(root, "texture", this, Terrain, loadTexture)
-  .describe("The name of the Texture for this heightMap");
-
-  LoadParam(root, "vegetation", this, Terrain, loadVegetation)
-  .describe("the fileName of the vegetation, that should be loaded onto this terrain. (must be relative to the data-dir)") ;
-
-  LoadParam(root, "height-map", this, Terrain, loadHeightMap)
-  .describe("The HeightMap, splitted into two strings seperated by ','. 1: HeighMap, 2: ColorMap");
-
-}
-
-void Terrain::setScale(float x, float y, float z)
-{
-  this->terrainScale = Vector(x, y, z);
-}
-
-void Terrain::loadHeightMap(const std::string& heightMapFile, const std::string& colorMap)
-{
-  if (this->heightMap != NULL)
-    delete this->heightMap;
-  this->heightMap = NULL;
-
-  std::string hmName = ResourceManager::getFullName(heightMapFile);
-  std::string hmColorName = ResourceManager::getFullName(colorMap);
-
-
-  this->heightMap = new HeightMap(hmName, hmColorName);
-  //   heightMap->scale(Vector(43.0f,4.7f,43.0f));
-  heightMap->scale(this->terrainScale);
-  heightMap->setAbsCoor(this->getAbsCoor());
-  heightMap->load();
-}
-
-
-void Terrain::loadTexture(const std::string& textureName)
-{
-  PRINTF(4)("Load texture: %s\n", textureName.c_str());
-
-  heightMapMaterial->setDiffuse(1.0,1.0,1.0);
-  heightMapMaterial->setAmbient(1.0,1.0,1.0 );
-  heightMapMaterial->setSpecular(1.0,1.0,1.0);
-  heightMapMaterial->setShininess(.5);
-  heightMapMaterial->setTransparency(1.0);
-
-  heightMapMaterial->setDiffuseMap(textureName);
-  //   heightMapMaterial->setAmbientMap(textureName);
-  //   heightMapMaterial->setSpecularMap(textureName);
-}
-
-
-
-void Terrain::loadVegetation(const std::string& vegetationFile)
-{
-  PRINTF(4)("loadVegetation: %s\n", vegetationFile.c_str());
-  if (this->vegetation)
-    ResourceManager::getInstance()->unload(this->vegetation, RP_LEVEL);
-  if (!vegetationFile.empty())
-  {
-    PRINTF(4)("fetching %s\n", vegetationFile.c_str());
-    this->vegetation = dynamic_cast<Model*>(ResourceManager::getInstance()->load(vegetationFile, OBJ, RP_CAMPAIGN));
-  }
-  else
-    this->vegetation = NULL;
-}
-
-
-
-
-
-void Terrain::draw () const
-{
-  glPushMatrix();
-
-  /* translate */
-  glTranslatef (this->getAbsCoor ().x,
-                this->getAbsCoor ().y,
-                this->getAbsCoor ().z);
-  /* rotate */
-  // Vector tmpRot = this->getAbsDir().getSpacialAxis();
-  //glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
-
-  if (this->objectList)
-    glCallList(this->objectList);
-  else if (this->getModel())
-    this->getModel()->draw();
-
-  if (this->vegetation)
-    this->vegetation->draw();
-
-  if( this->heightMap)
-  {
-    this->heightMapMaterial->select();
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    this->heightMap->draw();
-  }
-  glPopMatrix();
-
-
-  /*
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glLoadIdentity();
-    Vector camera =   State::getCameraNode()->getAbsCoor(); // Go on here ..........!!!
-
-    float height =    heightMap->getHeight(camera.x, camera.z);
-
-    glEnable (GL_COLOR_MATERIAL) ;
-    glBegin(GL_QUADS);            // Draw The Cube Using quads
-    glColor3f(0.0f,1.0f,0.0f);  // Color Blue
-    glVertex3f(camera.x + 63.0f,Terrain->getHeight(camera.x+63.0f, camera.z-10.0f)+13.0f,camera.z-10.0f);      // Top Right Of The Quad (Top)
-    glVertex3f(camera.x-63.0f, getHeight(camera.x+63.0f, camera.z-10.0f)+13.0f,camera.z-10.0f);      // Top Left Of The Quad (Top)
-    glVertex3f(camera.x-63.0f, getHeight(camera.x+63.0f, camera.z+10.0f)+13.0f, camera.z+10.0f);      // Bottom Left Of The Quad (Top)
-    glVertex3f(camera.x+ 63.0f, getHeight(camera.x+63.0f, camera.z+10.0f)+13.0f, camera.z+10.0f);      // Bottom Right Of The Quad (Top)
-    glEnd();                      // End Drawing The Plan
-
-    glPopMatrix();*/
-
-
-  /* THIS IS ONLY FOR DEBUGGING INFORMATION */
-  if (this->ssp != NULL)
-    this->ssp->drawQuadtree();
-}
-
-
-void Terrain::buildDebugTerrain(DebugTerrain debugTerrain)
-{
-  // if the terrain is the Terrain of Dave
-  if (debugTerrain == TERRAIN_DAVE)
-  {
-    objectList = glGenLists(1);
-    glNewList (objectList, GL_COMPILE);
-
-    glColor3f(1.0,0,0);
-
-    int sizeX = 100;
-    int sizeZ = 80;
-    float length = 1000;
-    float width = 200;
-    float widthX = float (length /sizeX);
-    float widthZ = float (width /sizeZ);
-
-    float height [sizeX][sizeZ];
-    Vector normal_vectors[sizeX][sizeZ];
-
-
-    for ( int i = 0; i<sizeX-1; i+=1)
-      for (int j = 0; j<sizeZ-1;j+=1)
-        //height[i][j] = rand()/20046 + (j-25)*(j-25)/30;
-#ifdef __WIN32__
-        height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
-#else
-        height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
-#endif
-
-    //Die Huegel ein wenig glaetten
-    for (int h=1; h<2;h++)
-      for (int i=1;i<sizeX-2 ;i+=1 )
-        for(int j=1;j<sizeZ-2;j+=1)
-          height[i][j]=(height[i+1][j]+height[i][j+1]+height[i-1][j]+height[i][j-1])/4;
-
-    //Berechnung von normalen Vektoren
-    for(int i=1;i<sizeX-2;i+=1)
-      for(int j=1;j<sizeZ-2 ;j+=1)
-      {
-        Vector v1 = Vector (widthX*(1),      height[i][j],      widthZ*(j) );
-        Vector v2 = Vector (widthX*(i-1),    height[i-1][j],    widthZ*(j));
-        Vector v3 = Vector (widthX*(i),      height[i][j+1],    widthZ*(j+1));
-        Vector v4 = Vector (widthX*(i+1),    height[i+1][j],    widthZ*(j));
-        Vector v5 = Vector (widthX*(i),      height[i][j-1],    widthZ*(j-1));
-
-        Vector c1 = v2 - v1;
-        Vector c2 = v3 - v1;
-        Vector c3=  v4 - v1;
-        Vector c4 = v5 - v1;
-        Vector zero = Vector (0,0,0);
-        normal_vectors[i][j]=c1.cross(v3-v5)+c2.cross(v4-v2)+c3.cross(v5-v3)+c4.cross(v2-v4);
-        normal_vectors[i][j].normalize();
-      }
-
-    glBegin(GL_QUADS);
-    int snowheight=3;
-    for ( int i = 0; i<sizeX; i+=1)
-      for (int j = 0; j<sizeZ;j+=1)
-      {
-        Vector v1 = Vector (widthX*(i),      height[i][j]-20,       widthZ*(j)  -width/2);
-        Vector v2 = Vector (widthX*(i+1),    height[i+1][j]-20,     widthZ*(j)  -width/2);
-        Vector v3 = Vector (widthX*(i+1),    height[i+1][j+1]-20,   widthZ*(j+1)-width/2);
-        Vector v4 = Vector (widthX*(i),      height[i][j+1]-20,     widthZ*(j+1)-width/2);
-        float a[3];
-        if(height[i][j]<snowheight)
-        {
-          a[0]=0;
-          a[1]=1.0-height[i][j]/10-.3;
-          a[2]=0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-        }
-        else
-        {
-          a[0]=1.0;
-          a[1]=1.0;
-          a[2]=1.0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-
-        }
-        glNormal3f(normal_vectors[i][j].x, normal_vectors[i][j].y, normal_vectors[i][j].z);
-        glVertex3f(v1.x, v1.y, v1.z);
-        if(height[i+1][j]<snowheight)
-        {
-          a[0]=0;
-          a[1] =1.0-height[i+1][j]/10-.3;
-          a[2]=0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-        }
-        else
-        {
-          a[0]=1.0;
-          a[1]=1.0;
-          a[2]=1.0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-
-        }
-        glNormal3f(normal_vectors[i+1][j].x, normal_vectors[i+1][j].y, normal_vectors[i+1][j].z);
-        glVertex3f(v2.x, v2.y, v2.z);
-        if(height[i+1][j+1]<snowheight)
-        {
-          a[0]=0;
-          a[1] =1.0-height[i+1][j+1]/10-.3;
-          a[2]=0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-        }
-        else
-        {
-          a[0]=1.0;
-          a[1]=1.0;
-          a[2]=1.0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-
-
-        }
-        glNormal3f(normal_vectors[i+1][j+1].x, normal_vectors[i+1][j+1].y, normal_vectors[i+1][j+1].z);
-        glVertex3f(v3.x, v3.y, v3.z);
-        if(height[i][j+1]<snowheight)
-        {
-          a[0]=0;
-          a[1] =1.0-height[i+1][j+1]/10-.3;
-          a[2]=0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-        }
-        else
-        {
-          a[0]=1.0;
-          a[1]=1.0;
-          a[2]=1.0;
-          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
-        }
-        glNormal3f(normal_vectors[i][j+1].x, normal_vectors[i][j+1].y, normal_vectors[i][j+1].z);
-        glVertex3f(v4.x, v4.y, v4.z);
-
-      }
-    glEnd();
-    glEndList();
-  }
-
-  if (debugTerrain == TERRAIN_BENSCH)
-  {
-    /*
-      this->model = (OBJModel*) new Model();
-    this->model->setName("CUBE");
-    this->model->addVertex (-0.5, -0.5, 0.5);
-    this->model->addVertex (0.5, -0.5, 0.5);
-    this->model->addVertex (-0.5, 0.5, 0.5);
-    this->model->addVertex (0.5, 0.5, 0.5);
-    this->model->addVertex (-0.5, 0.5, -0.5);
-    this->model->addVertex (0.5, 0.5, -0.5);
-    this->model->addVertex (-0.5, -0.5, -0.5);
-    this->model->addVertex (0.5, -0.5, -0.5);
-
-    this->model->addVertexTexture (0.0, 0.0);
-    this->model->addVertexTexture (1.0, 0.0);
-    this->model->addVertexTexture (0.0, 1.0);
-    this->model->addVertexTexture (1.0, 1.0);
-    this->model->addVertexTexture (0.0, 2.0);
-    this->model->addVertexTexture (1.0, 2.0);
-    this->model->addVertexTexture (0.0, 3.0);
-    this->model->addVertexTexture (1.0, 3.0);
-    this->model->addVertexTexture (0.0, 4.0);
-    this->model->addVertexTexture (1.0, 4.0);
-    this->model->addVertexTexture (2.0, 0.0);
-    this->model->addVertexTexture (2.0, 1.0);
-    this->model->addVertexTexture (-1.0, 0.0);
-    this->model->addVertexTexture (-1.0, 1.0);
-
-    this->model->finalize();
-    */
-  }
-}
-
-float Terrain::getHeight(float x, float y)
-{
-  if(this->heightMap != NULL)
-    return (this->heightMap->getHeight(x, y));
-  return 0;
-}
Index: anches/terrain/src/world_entities/terrain.h
===================================================================
--- /branches/terrain/src/world_entities/terrain.h	(revision 9139)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*!
- * @file terrain.h
-  *  Defines and handles the terrain of the World
-
-    @todo implement it
-
-    The terrain should either be build from a Model a OBJModel or from a HeightMap.
-*/
-
-#ifndef _TERRAIN_H
-#define _TERRAIN_H
-
-#include "world_entity.h"
-#include "vector.h"
-
-// FORWARD DECLARATION
-class SpatialSeparation;
-class HeightMap;
-class Material;
-
-//! A simple method to call a desired debug world.
-enum DebugTerrain {TERRAIN_DAVE, TERRAIN_BENSCH};
-
-
-//! A Class to handle Terrain of orxonox
-class Terrain : public WorldEntity
-{
-
- public:
-  Terrain(const TiXmlElement* root = NULL);
-  Terrain(const std::string& fileName);
-  Terrain(DebugTerrain debugTerrain);
-  virtual ~Terrain();
-
-  void init();
-  virtual void loadParams(const TiXmlElement* root);
-
-  void loadVegetation(const std::string& vegetationFile);
-
-  void loadHeightMap(const std::string& heightMapFile, const std::string& colorMap);
-  void loadTexture(const std::string& textureName);
-  void setScale(float x, float y, float z);
-
-  void buildDebugTerrain(DebugTerrain debugTerrain);
-
-  float getHeight(float x, float y);
-  virtual void draw() const;
-
-  public:
-    SpatialSeparation* ssp;
-
- private:
-   Model*              vegetation;
-   int                 objectList;
-
-   HeightMap*          heightMap;
-   Material*           heightMapMaterial;
-   Vector              terrainScale;
-};
-
-#endif /* _TERRAIN_H */
Index: /branches/terrain/src/world_entities/terrain_entity.cc
===================================================================
--- /branches/terrain/src/world_entities/terrain_entity.cc	(revision 9140)
+++ /branches/terrain/src/world_entities/terrain_entity.cc	(revision 9140)
@@ -0,0 +1,424 @@
+/*
+   orxonox - the future of 3D-vertical-scrollers
+
+   Copyright (C) 2004 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: Benjamin Grauer
+   co-programmer: ...
+*/
+#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
+
+
+#include "terrain_entity.h"
+#include "terrain/terrain.h"
+#include "util/loading/load_param.h"
+#include "util/loading/factory.h"
+#include "spatial_separation.h"
+
+#include "util/loading/resource_manager.h"
+#include "model.h"
+#include "network_game_manager.h"
+
+#include "material.h"
+
+#include "glincl.h"
+
+#include "state.h"
+
+using namespace std;
+
+CREATE_FACTORY( TerrainEntity, CL_TERRAIN );
+
+/**
+ *  standard constructor
+ */
+TerrainEntity::TerrainEntity (const TiXmlElement* root)
+{
+	this->init();
+
+
+	if( root != NULL)
+		this->loadParams(root);
+	terrain->build( );
+}
+
+
+/**
+ *  Constructor for loading a TerrainEntity out of a file
+ * @param fileName The file to load data from.
+
+   this either loads out of an OBJ-file, or loads a heightmap if no .obj-extension is found.
+*/
+TerrainEntity::TerrainEntity(const std::string& fileName )
+{
+  this->init();
+
+  if (fileName.rfind(".obj" ) != -1 || fileName.rfind(".OBJ") != -1 )
+  {
+    this->loadModel(fileName);
+  }
+  else
+  {
+    // load the hightMap here.
+  }
+}
+
+/**
+ *  a Constructor for the Debug-Worlds
+ */
+TerrainEntity::TerrainEntity(DebugTerrainEntity debugTerrainEntity)
+{
+  this->init();
+  this->buildDebugTerrainEntity(debugTerrainEntity);
+}
+
+/**
+ *  standard deconstructor
+
+*/
+TerrainEntity::~TerrainEntity ()
+{
+  if (objectList)
+    glDeleteLists(this->objectList, 1);
+
+  if (this->vegetation)
+  {
+    ResourceManager::getInstance()->unload( this->vegetation );
+  }
+
+  if( this->terrain )
+    delete terrain;
+}
+
+
+void TerrainEntity::init()
+{
+  this->setClassID( CL_TERRAIN, "TerrainEntity");
+  this->toList(OM_ENVIRON);
+  this->toReflectionList();
+
+  this->objectList = 0;
+  this->vegetation = NULL;
+
+  this->terrain = new Terrain();
+
+  //this->heightMapMaterial = new Material();
+}
+
+
+void TerrainEntity::loadParams(const TiXmlElement* root)
+{
+	WorldEntity::loadParams( root );
+
+	LoadParam(root, "scale", this, TerrainEntity, setScale)
+		.describe("The scale in x,y,z direction");
+	
+	LoadParam( root, "light_map", this, TerrainEntity, loadLightmap )
+		.describe("The name of the lightmap.");
+		
+	LoadParam( root, "elevation_map", this, TerrainEntity, loadElevationmap )
+		.describe( "The name of the elevation map. Must be an 8bit image" );
+	ResourceManager *manager = ResourceManager::getInstance();
+	TiXmlElement * layer = (TiXmlElement*)root->FirstChild( "material_layer" );		
+	while ( layer ) {
+		LayerInfo *info = new LayerInfo();
+		TiXmlElement *detail = (TiXmlElement*)layer->FirstChild( "detail_map" );
+		if ( detail ) {
+			string detailmap( detail->Attribute( "file" ) );
+			info->detail = (Texture*)manager->load( detailmap, 
+				IMAGE, RP_GAME, (int)GL_TEXTURE_2D );			
+			if ( !info->detail ) {
+				PRINTF(0)( "%s not found\n", detailmap.c_str() );
+			}	
+			else
+				PRINTF(0)( "loaded %s\n", detailmap.c_str() );
+			TiXmlElement *repeat = (TiXmlElement*)detail->FirstChild( "repeat" );
+			if ( repeat ) {
+				repeat->QueryFloatAttribute( "x", &info->repeatX );
+				repeat->QueryFloatAttribute( "z", &info->repeatZ );				
+			}
+		}
+		else {
+			PRINTF(0)( "Please specify a detail-map" );
+		}
+		TiXmlElement *alpha = (TiXmlElement*)layer->FirstChild( "alpha" );
+		if ( alpha ) {
+				if ( !alpha->Attribute( "full" ) ) {
+					string alphamap( alpha->Attribute( "file" ) );
+					info->alpha = (Texture*)manager->load( alphamap, 
+						IMAGE, RP_GAME, (int)GL_TEXTURE_2D );
+					if ( !info->alpha )	
+						PRINTF(0)( "%s not found\n", alphamap.c_str() );
+					else
+						PRINTF(0)( "loaded %s\n", alphamap.c_str() );
+				}
+		}	
+		terrain->addMaterialLayer( info );
+		layer = (TiXmlElement*)layer->NextSibling( "material_layer" );
+	}
+}
+
+void TerrainEntity::setScale(float x, float y, float z)
+{
+ 	terrain->setScale( Triple( x, y, z ) );
+}
+
+void TerrainEntity::loadElevationmap( const std::string& _eleFile )
+{
+	terrain->setHeightmap( _eleFile );
+}
+
+void TerrainEntity::loadLightmap( const std::string& _lightFile )
+{
+	ResourceManager *manager = ResourceManager::getInstance();
+	Texture *lightmap = (Texture*)manager->load( _lightFile, 
+		IMAGE, RP_GAME, (int)GL_TEXTURE_2D );	
+	if ( lightmap )	
+		terrain->setLightmap( lightmap );
+	else {
+		PRINTF(0)("no lightmap %s\n", _lightFile.c_str() );
+		
+	}	
+}
+
+
+
+void TerrainEntity::loadVegetation(const std::string& vegetationFile)
+{
+  PRINTF(4)("loadVegetation: %s\n", vegetationFile.c_str());
+  if (this->vegetation)
+    ResourceManager::getInstance()->unload(this->vegetation, RP_LEVEL);
+  if (!vegetationFile.empty())
+  {
+    PRINTF(4)("fetching %s\n", vegetationFile.c_str());
+    this->vegetation = dynamic_cast<Model*>(ResourceManager::getInstance()->load(vegetationFile, OBJ, RP_CAMPAIGN));
+  }
+  else
+    this->vegetation = NULL;
+}
+
+
+
+void TerrainEntity::tick( float _dt ) { if ( terrain ) terrain->tick( _dt ); }
+
+void TerrainEntity::draw () const
+{
+	glMatrixMode( GL_MODELVIEW );
+  	glPushMatrix();
+
+   glTranslatef( this->getAbsCoor().x,
+                 this->getAbsCoor().y,
+                 this->getAbsCoor().z );
+
+	Vector cam = State::getCameraNode()->getAbsCoor();
+	
+  	if ( this->terrain ) {
+		terrain->setCameraPosition( Triple( cam.x, cam.y, cam.z ) ); 
+		terrain->draw( );
+  	}
+  	glPopMatrix();
+
+
+}
+
+
+void TerrainEntity::buildDebugTerrainEntity(DebugTerrainEntity debugTerrainEntity)
+{
+	terrain->build( );
+  /*
+  // if the TerrainEntity is the TerrainEntity of Dave
+  if (debugTerrainEntity == TERRAINENTITY_DAVE)
+  {
+    objectList = glGenLists(1);
+    glNewList (objectList, GL_COMPILE);
+
+    glColor3f(1.0,0,0);
+
+    int sizeX = 100;
+    int sizeZ = 80;
+    float length = 1000;
+    float width = 200;
+    float widthX = float (length /sizeX);
+    float widthZ = float (width /sizeZ);
+
+    float height [sizeX][sizeZ];
+    Vector normal_vectors[sizeX][sizeZ];
+
+
+    for ( int i = 0; i<sizeX-1; i+=1)
+      for (int j = 0; j<sizeZ-1;j+=1)
+        //height[i][j] = rand()/20046 + (j-25)*(j-25)/30;
+#ifdef __WIN32__
+        height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
+#else
+        height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
+#endif
+
+    //Die Huegel ein wenig glaetten
+    for (int h=1; h<2;h++)
+      for (int i=1;i<sizeX-2 ;i+=1 )
+        for(int j=1;j<sizeZ-2;j+=1)
+          height[i][j]=(height[i+1][j]+height[i][j+1]+height[i-1][j]+height[i][j-1])/4;
+
+    //Berechnung von normalen Vektoren
+    for(int i=1;i<sizeX-2;i+=1)
+      for(int j=1;j<sizeZ-2 ;j+=1)
+      {
+        Vector v1 = Vector (widthX*(1),      height[i][j],      widthZ*(j) );
+        Vector v2 = Vector (widthX*(i-1),    height[i-1][j],    widthZ*(j));
+        Vector v3 = Vector (widthX*(i),      height[i][j+1],    widthZ*(j+1));
+        Vector v4 = Vector (widthX*(i+1),    height[i+1][j],    widthZ*(j));
+        Vector v5 = Vector (widthX*(i),      height[i][j-1],    widthZ*(j-1));
+
+        Vector c1 = v2 - v1;
+        Vector c2 = v3 - v1;
+        Vector c3=  v4 - v1;
+        Vector c4 = v5 - v1;
+        Vector zero = Vector (0,0,0);
+        normal_vectors[i][j]=c1.cross(v3-v5)+c2.cross(v4-v2)+c3.cross(v5-v3)+c4.cross(v2-v4);
+        normal_vectors[i][j].normalize();
+      }
+
+    glBegin(GL_QUADS);
+    int snowheight=3;
+    for ( int i = 0; i<sizeX; i+=1)
+      for (int j = 0; j<sizeZ;j+=1)
+      {
+        Vector v1 = Vector (widthX*(i),      height[i][j]-20,       widthZ*(j)  -width/2);
+        Vector v2 = Vector (widthX*(i+1),    height[i+1][j]-20,     widthZ*(j)  -width/2);
+        Vector v3 = Vector (widthX*(i+1),    height[i+1][j+1]-20,   widthZ*(j+1)-width/2);
+        Vector v4 = Vector (widthX*(i),      height[i][j+1]-20,     widthZ*(j+1)-width/2);
+        float a[3];
+        if(height[i][j]<snowheight)
+        {
+          a[0]=0;
+          a[1]=1.0-height[i][j]/10-.3;
+          a[2]=0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+        }
+        else
+        {
+          a[0]=1.0;
+          a[1]=1.0;
+          a[2]=1.0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+
+        }
+        glNormal3f(normal_vectors[i][j].x, normal_vectors[i][j].y, normal_vectors[i][j].z);
+        glVertex3f(v1.x, v1.y, v1.z);
+        if(height[i+1][j]<snowheight)
+        {
+          a[0]=0;
+          a[1] =1.0-height[i+1][j]/10-.3;
+          a[2]=0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+        }
+        else
+        {
+          a[0]=1.0;
+          a[1]=1.0;
+          a[2]=1.0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+
+        }
+        glNormal3f(normal_vectors[i+1][j].x, normal_vectors[i+1][j].y, normal_vectors[i+1][j].z);
+        glVertex3f(v2.x, v2.y, v2.z);
+        if(height[i+1][j+1]<snowheight)
+        {
+          a[0]=0;
+          a[1] =1.0-height[i+1][j+1]/10-.3;
+          a[2]=0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+        }
+        else
+        {
+          a[0]=1.0;
+          a[1]=1.0;
+          a[2]=1.0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+
+
+        }
+        glNormal3f(normal_vectors[i+1][j+1].x, normal_vectors[i+1][j+1].y, normal_vectors[i+1][j+1].z);
+        glVertex3f(v3.x, v3.y, v3.z);
+        if(height[i][j+1]<snowheight)
+        {
+          a[0]=0;
+          a[1] =1.0-height[i+1][j+1]/10-.3;
+          a[2]=0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+        }
+        else
+        {
+          a[0]=1.0;
+          a[1]=1.0;
+          a[2]=1.0;
+          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
+        }
+        glNormal3f(normal_vectors[i][j+1].x, normal_vectors[i][j+1].y, normal_vectors[i][j+1].z);
+        glVertex3f(v4.x, v4.y, v4.z);
+
+      }
+    glEnd();
+    glEndList();
+  }
+	*/
+  if (debugTerrainEntity == TERRAINENTITY_BENSCH)
+  {
+    /*
+      this->model = (OBJModel*) new Model();
+    this->model->setName("CUBE");
+    this->model->addVertex (-0.5, -0.5, 0.5);
+    this->model->addVertex (0.5, -0.5, 0.5);
+    this->model->addVertex (-0.5, 0.5, 0.5);
+    this->model->addVertex (0.5, 0.5, 0.5);
+    this->model->addVertex (-0.5, 0.5, -0.5);
+    this->model->addVertex (0.5, 0.5, -0.5);
+    this->model->addVertex (-0.5, -0.5, -0.5);
+    this->model->addVertex (0.5, -0.5, -0.5);
+
+    this->model->addVertexTexture (0.0, 0.0);
+    this->model->addVertexTexture (1.0, 0.0);
+    this->model->addVertexTexture (0.0, 1.0);
+    this->model->addVertexTexture (1.0, 1.0);
+    this->model->addVertexTexture (0.0, 2.0);
+    this->model->addVertexTexture (1.0, 2.0);
+    this->model->addVertexTexture (0.0, 3.0);
+    this->model->addVertexTexture (1.0, 3.0);
+    this->model->addVertexTexture (0.0, 4.0);
+    this->model->addVertexTexture (1.0, 4.0);
+    this->model->addVertexTexture (2.0, 0.0);
+    this->model->addVertexTexture (2.0, 1.0);
+    this->model->addVertexTexture (-1.0, 0.0);
+    this->model->addVertexTexture (-1.0, 1.0);
+
+    this->model->finalize();
+    */
+  }
+}
+void TerrainEntity::getAltitude( Vector& _position, Vector& _normal )
+{
+	Triple 	altitude( _position.x-getAbsCoor().x, 0.0f, _position.z-getAbsCoor().z ), 
+			normal( 0.0f, 0.0f, 0.0f );
+	if ( terrain ) 
+			terrain->getAltitude( altitude, normal );
+			
+	_position.y = altitude.y+getAbsCoor().y;
+	_normal.z = normal.z; _normal.y = normal.y; _normal.z = normal.z;	
+}
+
+float TerrainEntity::getHeight( float x, float z )
+{
+	Triple 	altitude( x-getAbsCoor().x, 0.0f, z-getAbsCoor().z ), 
+			normal( 0.0f, 0.0f, 0.0f );
+	if ( terrain )
+		terrain->getAltitude( altitude, normal );
+		
+  return altitude.y+getAbsCoor().y;
+}
Index: /branches/terrain/src/world_entities/terrain_entity.h
===================================================================
--- /branches/terrain/src/world_entities/terrain_entity.h	(revision 9140)
+++ /branches/terrain/src/world_entities/terrain_entity.h	(revision 9140)
@@ -0,0 +1,59 @@
+/*!
+ * @file TerrainEntity.h
+
+  *  Defines and handles the TerrainEntity of the World
+
+    @todo implement it
+
+    The TerrainEntity should either be build from a Model a OBJModel or from a HeightMap.
+*/
+
+#ifndef _TERRAINENTITY_H
+#define _TERRAINENTITY_H
+
+#include "world_entity.h"
+#include "vector.h"
+
+// FORWARD DECLARATION
+class Material;
+class Terrain;
+
+//! A simple method to call a desired debug world.
+enum DebugTerrainEntity {TERRAINENTITY_DAVE, TERRAINENTITY_BENSCH};
+
+
+//! A Class to handle TerrainEntity of orxonox
+class TerrainEntity : public WorldEntity
+{
+
+	public:
+		TerrainEntity(const TiXmlElement* root = NULL);
+		TerrainEntity(const std::string& fileName);
+		TerrainEntity(DebugTerrainEntity debugTerrainEntity);
+		virtual ~TerrainEntity();
+
+		void init();
+		virtual void loadParams(const TiXmlElement* root);
+
+		void loadVegetation(const std::string& vegetationFile);
+
+		void loadElevationmap( const std::string& _eleFile );
+		void loadLightmap(const std::string& _lightFile );
+		void setScale( float x, float y, float z );
+
+		void buildDebugTerrainEntity(DebugTerrainEntity debugTerrainEntity);
+
+		float getHeight(float x, float y);
+		void getAltitude( Vector& _position, Vector& _normal );
+		virtual void draw() const;
+		virtual void tick( float _dt );
+	public:
+	
+	private:
+		 Model*              	vegetation;
+		 int                 	objectList;
+		 Terrain*				terrain;
+		 Vector              	TerrainEntityScale;
+};
+
+#endif /* _TerrainEntity_H */
Index: /branches/terrain/src/world_entities/world_entity.cc
===================================================================
--- /branches/terrain/src/world_entities/world_entity.cc	(revision 9139)
+++ /branches/terrain/src/world_entities/world_entity.cc	(revision 9140)
@@ -442,4 +442,5 @@
     return false;
 
+
   // get a collision event
   CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
