Changeset 9421 in orxonox.OLD for branches/terrain/src/lib/graphics/importer
- Timestamp:
- Jul 24, 2006, 1:46:23 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
r9414 r9421 12 12 #endif 13 13 14 bool validateSize( int _s ) { 15 _s-=1; 16 int s = 16; 17 while ( s <= _s ) { 18 if (s == _s ) 19 return true; 20 s*=2; 21 } 22 return false; 14 bool validateSize( int _s ) 15 { 16 _s-=1; 17 int s = 16; 18 while ( s <= _s ) 19 { 20 if (s == _s ) 21 return true; 22 s*=2; 23 } 24 return false; 23 25 } 24 26 void Terrain::build() 25 27 { 26 ResourceManager *MANAGER = ResourceManager::getInstance(); 27 std::string full = MANAGER->getFullName( heightmapSource ); 28 SDL_Surface *tmpData = IMG_Load( full.c_str() ); 29 if ( !tmpData ) { 30 PRINT(0)( "I' sorry, I can't load %s\n", full.c_str() ); 31 return; 32 } 33 if ( !validateSize( tmpData->h ) || !validateSize( tmpData->w ) ) { 34 PRINT(0)( "The size of the elevation map must be 2^n+1x2^m+1. and at least 17x17" ); 35 return; 36 } 37 if ( tmpData->format->BytesPerPixel != 1 ) { 38 PRINT(0)( "The elevetation map must be an 8bit image not %d", 39 tmpData->format->BytesPerPixel*8 ); 40 return; 41 } 42 PRINTF(2)( "Loaded the elevation map\n" ); 43 heightfield.height = tmpData->h; 44 heightfield.width = tmpData->w; 45 heightfield.pitch = tmpData->pitch; 46 int dataSize = heightfield.pitch*heightfield.height; 47 heightfield.data = new Uint8[dataSize]; 48 memcpy( heightfield.data, tmpData->pixels, sizeof(Uint8)*dataSize ); 49 SDL_FreeSurface( tmpData ); 50 pagesX = (heightfield.width/(pageSize-1) ); 51 pagesZ = (heightfield.height/(pageSize-1) ); 52 53 54 pages = new pTerrainPage[pagesX*pagesZ]; 55 for ( int x = 0; x < pagesX; ++x ) 56 for ( int z = 0; z < pagesZ; ++z ) 57 pages[z*pagesX+x] = createPage( x, z ); 58 //Inform each page about its neighbors. 59 for ( int x = 0; x < pagesX; ++x ) 60 for ( int z = 0; z < pagesZ; ++z ) 61 pages[z*pagesX+x]->setNeighbors( 62 x > 0 ? getPage( x-1, z+0 ) : NULL, 63 x < pagesX-1 ? getPage( x+1, z+0 ) : NULL, 64 z < pagesZ-1 ? getPage( x+0, z+1 ) : NULL, 65 z > 0 ? getPage( x+0, z-1 ) : NULL ); 66 67 root = createQuadTree( 0, 0, pagesX, pagesZ ); 68 69 for ( unsigned int i = 0; i < layers.size(); ++i ) { 70 determineLayerVisibility( i ); 71 } 72 activePages = NULL; 28 29 printf("SHOULD GET LOADED :)\n"); 30 31 ResourceManager *MANAGER = ResourceManager::getInstance(); 32 std::string full = MANAGER->getFullName( heightmapSource ); 33 SDL_Surface *tmpData = IMG_Load( full.c_str() ); 34 if ( !tmpData ) 35 { 36 PRINT(0)( "I' sorry, I can't load %s\n", full.c_str() ); 37 return; 38 } 39 if ( !validateSize( tmpData->h ) || !validateSize( tmpData->w ) ) 40 { 41 PRINT(0)( "The size of the elevation map must be 2^n+1x2^m+1. and at least 17x17" ); 42 return; 43 } 44 if ( tmpData->format->BytesPerPixel != 1 ) 45 { 46 PRINT(0)( "The elevetation map must be an 8bit image not %d", 47 tmpData->format->BytesPerPixel*8 ); 48 return; 49 } 50 PRINTF(2)( "Loaded the elevation map\n" ); 51 heightfield.height = tmpData->h; 52 heightfield.width = tmpData->w; 53 heightfield.pitch = tmpData->pitch; 54 int dataSize = heightfield.pitch*heightfield.height; 55 heightfield.data = new Uint8[dataSize]; 56 memcpy( heightfield.data, tmpData->pixels, sizeof(Uint8)*dataSize ); 57 SDL_FreeSurface( tmpData ); 58 pagesX = (heightfield.width/(pageSize-1) ); 59 pagesZ = (heightfield.height/(pageSize-1) ); 60 61 62 pages = new pTerrainPage[pagesX*pagesZ]; 63 for ( int x = 0; x < pagesX; ++x ) 64 for ( int z = 0; z < pagesZ; ++z ) 65 pages[z*pagesX+x] = createPage( x, z ); 66 //Inform each page about its neighbors. 67 for ( int x = 0; x < pagesX; ++x ) 68 for ( int z = 0; z < pagesZ; ++z ) 69 pages[z*pagesX+x]->setNeighbors( 70 x > 0 ? getPage( x-1, z+0 ) : NULL, 71 x < pagesX-1 ? getPage( x+1, z+0 ) : NULL, 72 z < pagesZ-1 ? getPage( x+0, z+1 ) : NULL, 73 z > 0 ? getPage( x+0, z-1 ) : NULL ); 74 75 root = createQuadTree( 0, 0, pagesX, pagesZ ); 76 77 for ( unsigned int i = 0; i < layers.size(); ++i ) 78 { 79 determineLayerVisibility( i ); 80 } 81 activePages = NULL; 73 82 } 74 83 75 84 pTerrainQuad Terrain::createQuadTree( int _x0, int _z0, int _x1, int _z1, int _depth ) 76 85 { 77 int _x01 = (_x1+_x0)/2; int _z01 = (_z1+_z0)/2; 78 pTerrainQuad node; 79 if ( _x1-_x0 == 1 ) { 80 node = getPage( _x0, _z0 ); 81 node->setChildren( NULL, NULL, NULL, NULL ); 82 } 83 else { 84 node = new TerrainQuad( this, _x0, _z0, _x1, _z1 ); 85 node->setChildren( 86 createQuadTree( _x0, _z0, _x01, _z01, _depth+1 ), 87 createQuadTree( _x01, _z0, _x1, _z01, _depth+1 ), 88 createQuadTree( _x0, _z01, _x01, _z1, _depth+1 ), 89 createQuadTree( _x01, _z01, _x1, _z1, _depth+1 ) ); 90 } 91 node->calculateBounds(); 92 return node; 86 int _x01 = (_x1+_x0)/2; int _z01 = (_z1+_z0)/2; 87 pTerrainQuad node; 88 if ( _x1-_x0 == 1 ) 89 { 90 node = getPage( _x0, _z0 ); 91 node->setChildren( NULL, NULL, NULL, NULL ); 92 } 93 else 94 { 95 node = new TerrainQuad( this, _x0, _z0, _x1, _z1 ); 96 node->setChildren( 97 createQuadTree( _x0, _z0, _x01, _z01, _depth+1 ), 98 createQuadTree( _x01, _z0, _x1, _z01, _depth+1 ), 99 createQuadTree( _x0, _z01, _x01, _z1, _depth+1 ), 100 createQuadTree( _x01, _z01, _x1, _z1, _depth+1 ) ); 101 } 102 node->calculateBounds(); 103 return node; 93 104 } 94 105 95 106 pTerrainPage Terrain::createPage( int _xOffset, int _zOffset ) const 96 107 { 97 pTerrainPage newPage = new TerrainPage( const_cast<Terrain*>( this ), _xOffset, _zOffset ); 98 newPage->setScale( scale ); 99 newPage->setPosition( Vector( scale.x*_xOffset, 0.0f, scale.z*_zOffset ) ); 100 newPage->calculateErrors(); 101 return newPage; 102 } 103 104 void Terrain::addLevelFourPage( int _numVertices, Vertex *_vertices, 105 int _numIndices, unsigned short *_indices ) 106 { 107 assert( indices ); assert( vertices ); 108 BufferInfo bi = buffers[current]; 109 if ( ( MAX_VERTICES < _numVertices+bi.numVertices ) || 110 ( MAX_INDICES < _numIndices+bi.numIndices+2 ) ) { 111 //So, we need the next vb and ib. Lets put the old into vram... 112 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 113 glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 114 vertices, GL_DYNAMIC_DRAW_ARB ); 115 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bi.ibIdentifier ); 116 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 117 indices, GL_DYNAMIC_DRAW_ARB ); 118 BufferInfo newInfo; 119 broker->acquire( newInfo.vbIdentifier, newInfo.ibIdentifier ); 120 current++; 121 buffers.push_back( newInfo ); 122 bi = newInfo; 123 } 124 //For the vertex data, a simple copy operation is sufficient... 125 memcpy( &vertices[bi.numVertices], _vertices, 126 _numVertices*sizeof( Vertex ) ); 127 //The indices need to be updated with an offset :( 128 unsigned short *dst= &indices[bi.numIndices]; 129 unsigned short offset = bi.numVertices; 130 unsigned short *src= _indices; 131 unsigned short *end= src+_numIndices; 132 bi.numVertices+=_numVertices; 133 if ( bi.numIndices ) { 134 dst[0] = *(dst-1); 135 dst[1] = *src+offset; 136 dst+=2; bi.numIndices+=2; 137 } 138 while ( src < end ) { 139 *dst= *src+offset; 140 dst++; 141 src++; 142 } 143 bi.numIndices+=_numIndices; 144 buffers[current] = bi; 108 pTerrainPage newPage = new TerrainPage( const_cast<Terrain*>( this ), _xOffset, _zOffset ); 109 newPage->setScale( scale ); 110 newPage->setPosition( Vector( scale.x*_xOffset, 0.0f, scale.z*_zOffset ) ); 111 newPage->calculateErrors(); 112 return newPage; 113 } 114 115 void Terrain::addLevelFourPage( int _numVertices, Vertex *_vertices, 116 int _numIndices, unsigned short *_indices ) 117 { 118 assert( indices ); assert( vertices ); 119 BufferInfo bi = buffers[current]; 120 if ( ( MAX_VERTICES < _numVertices+bi.numVertices ) || 121 ( MAX_INDICES < _numIndices+bi.numIndices+2 ) ) 122 { 123 //So, we need the next vb and ib. Lets put the old into vram... 124 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 125 glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 126 vertices, GL_DYNAMIC_DRAW_ARB ); 127 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bi.ibIdentifier ); 128 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 129 indices, GL_DYNAMIC_DRAW_ARB ); 130 BufferInfo newInfo; 131 broker->acquire( newInfo.vbIdentifier, newInfo.ibIdentifier ); 132 current++; 133 buffers.push_back( newInfo ); 134 bi = newInfo; 135 } 136 //For the vertex data, a simple copy operation is sufficient... 137 memcpy( &vertices[bi.numVertices], _vertices, 138 _numVertices*sizeof( Vertex ) ); 139 //The indices need to be updated with an offset :( 140 unsigned short *dst= &indices[bi.numIndices]; 141 unsigned short offset = bi.numVertices; 142 unsigned short *src= _indices; 143 unsigned short *end= src+_numIndices; 144 bi.numVertices+=_numVertices; 145 if ( bi.numIndices ) 146 { 147 dst[0] = *(dst-1); 148 dst[1] = *src+offset; 149 dst+=2; bi.numIndices+=2; 150 } 151 while ( src < end ) 152 { 153 *dst= *src+offset; 154 dst++; 155 src++; 156 } 157 bi.numIndices+=_numIndices; 158 buffers[current] = bi; 145 159 } 146 160 147 161 void Terrain::determineVisiblePages( pTerrainQuad _node ) 148 162 { 149 switch( _node->cull() ) { 150 case Frustum::INTERSECT: 151 if ( !_node->isChildless() ) { 152 pTerrainQuad *children = _node->getChildren(); 153 for ( int i = 0; i < 4; ++i, ++children ) 154 determineVisiblePages( *children ); 155 } 156 else { 157 showPages( _node->getXOffset(), 158 _node->getZOffset(), 1, 1 ); 159 } 160 break; 161 case Frustum::INSIDE: 162 showPages( _node->getXOffset(), 163 _node->getZOffset(), 164 _node->getWidth() , 165 _node->getHeight() ); 166 break; 167 case Frustum::OUTSIDE: 168 break; 169 } 163 switch( _node->cull() ) 164 { 165 case Frustum::INTERSECT: 166 if ( !_node->isChildless() ) 167 { 168 pTerrainQuad *children = _node->getChildren(); 169 for ( int i = 0; i < 4; ++i, ++children ) 170 determineVisiblePages( *children ); 171 } 172 else 173 { 174 showPages( _node->getXOffset(), 175 _node->getZOffset(), 1, 1 ); 176 } 177 break; 178 case Frustum::INSIDE: 179 showPages( _node->getXOffset(), 180 _node->getZOffset(), 181 _node->getWidth() , 182 _node->getHeight() ); 183 break; 184 case Frustum::OUTSIDE: 185 break; 186 } 170 187 } 171 188 172 189 void Terrain::tick( float _dt ) 173 190 { 174 for ( unsigned int i = 0; i < buffers.size(); ++i ) 175 broker->release( buffers[i].vbIdentifier, buffers[i].ibIdentifier ); 176 buffers.clear(); 177 pTerrainPage page = NULL; 178 //Extract the frustum planes out of the modelview matrix. 179 frustum->extractPlanes(); 180 // Lets see which pages are visible. 181 determineVisiblePages( root ); 182 int wantedLeft, wantedRight, wantedBottom, wantedTop, minLOD; 183 pTerrainPage neighbor = NULL; 184 page = activePages; 185 bool dirty; 186 current = 0; 187 BufferInfo bi; 188 broker->acquire( bi.vbIdentifier, bi.ibIdentifier ); 189 buffers.push_back( bi ); 190 int dirtyRounds = 0; 191 do { 192 dirtyRounds++; 193 dirty = false; 194 page = activePages; 195 while ( page ) { 196 if ( !page->isActive() ) { 197 pTerrainPage tmp = page; 198 page = tmp->getNext(); 199 tmp->setVisibility( false ); 200 continue; 201 } 202 wantedLeft = wantedRight = wantedBottom = wantedTop = page->getWantedLOD(); 203 if ( ( neighbor = page->getLeft() ) && ( neighbor->isActive() ) ) 204 wantedLeft = neighbor->getWantedLOD(); 205 if ( ( neighbor = page->getRight() ) && ( neighbor->isActive() ) ) 206 wantedRight = neighbor->getWantedLOD(); 207 if ( ( neighbor = page->getTop() ) && ( neighbor->isActive() ) ) 208 wantedTop = neighbor->getWantedLOD(); 209 if ( ( neighbor = page->getBottom() ) && ( neighbor->isActive() ) ) 210 wantedBottom = neighbor->getWantedLOD(); 211 212 minLOD = std::min( std::min( wantedBottom, wantedTop ), 213 std::min( wantedLeft, wantedRight ) ); 214 if ( minLOD < page->getWantedLOD()-1 ) { 215 page->setWantedLOD( minLOD+1 ); 216 dirty = true; 217 } 218 page = page->getNext(); 219 } 220 } while ( dirty ); 221 222 page = activePages; 223 while ( page ) { 224 assert( page->isActive() ); 225 page->updateTesselation(); 226 page = page->getNext(); 227 } 228 //If there is some data in the buffer, we need to upload the data 229 //into the vram... 230 if ( buffers[current].numIndices != 0 ) { 231 BufferInfo bi = buffers[current]; 232 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 233 glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 234 vertices, GL_DYNAMIC_DRAW_ARB ); 235 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bi.ibIdentifier ); 236 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 237 indices, GL_DYNAMIC_DRAW_ARB ); 238 } 191 for ( unsigned int i = 0; i < buffers.size(); ++i ) 192 broker->release( buffers[i].vbIdentifier, buffers[i].ibIdentifier ); 193 buffers.clear(); 194 pTerrainPage page = NULL; 195 //Extract the frustum planes out of the modelview matrix. 196 frustum->extractPlanes(); 197 // Lets see which pages are visible. 198 determineVisiblePages( root ); 199 int wantedLeft, wantedRight, wantedBottom, wantedTop, minLOD; 200 pTerrainPage neighbor = NULL; 201 page = activePages; 202 bool dirty; 203 current = 0; 204 BufferInfo bi; 205 broker->acquire( bi.vbIdentifier, bi.ibIdentifier ); 206 buffers.push_back( bi ); 207 int dirtyRounds = 0; 208 do 209 { 210 dirtyRounds++; 211 dirty = false; 212 page = activePages; 213 while ( page ) 214 { 215 if ( !page->isActive() ) 216 { 217 pTerrainPage tmp = page; 218 page = tmp->getNext(); 219 tmp->setVisibility( false ); 220 continue; 221 } 222 wantedLeft = wantedRight = wantedBottom = wantedTop = page->getWantedLOD(); 223 if ( ( neighbor = page->getLeft() ) && ( neighbor->isActive() ) ) 224 wantedLeft = neighbor->getWantedLOD(); 225 if ( ( neighbor = page->getRight() ) && ( neighbor->isActive() ) ) 226 wantedRight = neighbor->getWantedLOD(); 227 if ( ( neighbor = page->getTop() ) && ( neighbor->isActive() ) ) 228 wantedTop = neighbor->getWantedLOD(); 229 if ( ( neighbor = page->getBottom() ) && ( neighbor->isActive() ) ) 230 wantedBottom = neighbor->getWantedLOD(); 231 232 minLOD = std::min( std::min( wantedBottom, wantedTop ), 233 std::min( wantedLeft, wantedRight ) ); 234 if ( minLOD < page->getWantedLOD()-1 ) 235 { 236 page->setWantedLOD( minLOD+1 ); 237 dirty = true; 238 } 239 page = page->getNext(); 240 } 241 } 242 while ( dirty ); 243 244 page = activePages; 245 while ( page ) 246 { 247 assert( page->isActive() ); 248 page->updateTesselation(); 249 page = page->getNext(); 250 } 251 //If there is some data in the buffer, we need to upload the data 252 //into the vram... 253 if ( buffers[current].numIndices != 0 ) 254 { 255 BufferInfo bi = buffers[current]; 256 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 257 glBufferDataARB( GL_ARRAY_BUFFER_ARB, MAX_VERTICES*sizeof( Vertex ), 258 vertices, GL_DYNAMIC_DRAW_ARB ); 259 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bi.ibIdentifier ); 260 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, MAX_INDICES*sizeof( short ), 261 indices, GL_DYNAMIC_DRAW_ARB ); 262 } 239 263 } 240 264 241 265 void Terrain::draw( ) 242 266 { 243 pTerrainPage page = NULL; 244 glGetError(); 245 /*pTerrainPage page = NULL; 246 frustum->extractPlanes();*/ 247 Plane far = frustum->getPlane( Frustum::FAR ); 248 //Due to some reason, the OpenGL implementors chose the plane equation 249 //to an array of doubles. So we will make them happy. 250 double farPlane[] = { far.n.x, far.n.y, far.n.z, far.k }; 251 glEnable( GL_CLIP_PLANE0 ); 252 glClipPlane( GL_CLIP_PLANE0, farPlane ); 253 glPushAttrib( GL_ALL_ATTRIB_BITS ); 254 glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); 255 /* 256 * Enable texture and vertex arrays for the first and the second texture 257 * units and disable the normal arrays. 258 */ 259 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 260 glEnableClientState( GL_VERTEX_ARRAY ); 261 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 262 glDisableClientState( GL_NORMAL_ARRAY ); 263 264 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 265 glEnableClientState( GL_VERTEX_ARRAY ); 266 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 267 glDisableClientState( GL_NORMAL_ARRAY ); 268 glDisable( GL_CULL_FACE ); 269 glDisable( GL_LIGHTING ); 270 glColor3f( 1.0f, 1.0f, 1.0f ); 271 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 272 cullCount = 0; 273 glEnable( GL_BLEND ); 274 glDepthFunc( GL_LEQUAL ); 275 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 276 for ( unsigned int i = 0; i < layers.size(); ++i ) { 277 LayerInfo* layer= layers[i]; 278 page = activePages; 279 280 glActiveTextureARB( GL_TEXTURE1_ARB ); 281 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 282 if ( layer->detail ) { 283 //glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); 284 glEnable( GL_TEXTURE_2D ); 285 glBindTexture( GL_TEXTURE_2D, layer->detail->getTexture() ); 286 glMatrixMode( GL_TEXTURE ); 287 glLoadIdentity(); 288 glScalef( layer->repeatX, layer->repeatZ, 1.0f ); 289 } 290 else { 291 glDisable( GL_TEXTURE_2D ); 292 } 293 glEnable( GL_CULL_FACE ); 294 glCullFace( GL_BACK ); 295 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 296 glActiveTextureARB( GL_TEXTURE0_ARB ); 297 glEnable( GL_TEXTURE_2D ); 298 if ( layer->alpha ) { 299 //glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); 300 glBindTexture( GL_TEXTURE_2D, layer->alpha->getTexture() ); 301 } 302 else { 303 304 glBindTexture( GL_TEXTURE_2D, lightmap->getTexture() ); 305 } 306 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); 307 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); 308 309 for ( unsigned j = 0; j < buffers.size(); ++j ) { 310 BufferInfo bi = buffers[j]; 311 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 312 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 313 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 314 315 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 316 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 317 318 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 319 bi.ibIdentifier ); 320 321 glDrawElements( GL_TRIANGLE_STRIP, bi.numIndices, 322 GL_UNSIGNED_SHORT, NULL ); 323 } 324 while ( page ) { 325 if ( page->hasMaterial( i ) ) 326 page->draw(); 327 page = page->getNext(); 328 } 329 } 330 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 331 glActiveTextureARB( GL_TEXTURE1_ARB ); 332 glDisable( GL_TEXTURE_2D ); 333 glActiveTextureARB( GL_TEXTURE0_ARB ); 334 glEnable( GL_LIGHTING ); 335 glMatrixMode( GL_TEXTURE ); 336 glLoadIdentity(); 337 glPopAttrib(); 338 glPopClientAttrib(); 339 glCullFace( GL_FRONT ); 340 glDisable( GL_CLIP_PLANE0 ); 267 pTerrainPage page = NULL; 268 glGetError(); 269 /*pTerrainPage page = NULL; 270 frustum->extractPlanes();*/ 271 Plane far = frustum->getPlane( Frustum::FAR ); 272 //Due to some reason, the OpenGL implementors chose the plane equation 273 //to an array of doubles. So we will make them happy. 274 double farPlane[] = { far.n.x, far.n.y, far.n.z, far.k }; 275 glEnable( GL_CLIP_PLANE0 ); 276 glClipPlane( GL_CLIP_PLANE0, farPlane ); 277 glPushAttrib( GL_ALL_ATTRIB_BITS ); 278 glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); 279 /* 280 * Enable texture and vertex arrays for the first and the second texture 281 * units and disable the normal arrays. 282 */ 283 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 284 glEnableClientState( GL_VERTEX_ARRAY ); 285 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 286 glDisableClientState( GL_NORMAL_ARRAY ); 287 288 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 289 glEnableClientState( GL_VERTEX_ARRAY ); 290 glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 291 glDisableClientState( GL_NORMAL_ARRAY ); 292 glDisable( GL_CULL_FACE ); 293 glDisable( GL_LIGHTING ); 294 glColor3f( 1.0f, 1.0f, 1.0f ); 295 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 296 cullCount = 0; 297 glEnable( GL_BLEND ); 298 glDepthFunc( GL_LEQUAL ); 299 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 300 for ( unsigned int i = 0; i < layers.size(); ++i ) 301 { 302 LayerInfo* layer= layers[i]; 303 page = activePages; 304 305 glActiveTextureARB( GL_TEXTURE1_ARB ); 306 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 307 if ( layer->detail ) 308 { 309 //glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); 310 glEnable( GL_TEXTURE_2D ); 311 glBindTexture( GL_TEXTURE_2D, layer->detail->getTexture() ); 312 glMatrixMode( GL_TEXTURE ); 313 glLoadIdentity(); 314 glScalef( layer->repeatX, layer->repeatZ, 1.0f ); 315 } 316 else 317 { 318 glDisable( GL_TEXTURE_2D ); 319 } 320 glEnable( GL_CULL_FACE ); 321 glCullFace( GL_BACK ); 322 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 323 glActiveTextureARB( GL_TEXTURE0_ARB ); 324 glEnable( GL_TEXTURE_2D ); 325 if ( layer->alpha ) 326 { 327 //glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); 328 glBindTexture( GL_TEXTURE_2D, layer->alpha->getTexture() ); 329 } 330 else 331 { 332 333 glBindTexture( GL_TEXTURE_2D, lightmap->getTexture() ); 334 } 335 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); 336 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); 337 338 for ( unsigned j = 0; j < buffers.size(); ++j ) 339 { 340 BufferInfo bi = buffers[j]; 341 glBindBufferARB( GL_ARRAY_BUFFER_ARB, bi.vbIdentifier ); 342 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 343 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 344 345 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 346 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 347 348 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 349 bi.ibIdentifier ); 350 351 glDrawElements( GL_TRIANGLE_STRIP, bi.numIndices, 352 GL_UNSIGNED_SHORT, NULL ); 353 } 354 while ( page ) 355 { 356 if ( page->hasMaterial( i ) ) 357 page->draw(); 358 page = page->getNext(); 359 } 360 } 361 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 362 glActiveTextureARB( GL_TEXTURE1_ARB ); 363 glDisable( GL_TEXTURE_2D ); 364 glActiveTextureARB( GL_TEXTURE0_ARB ); 365 glEnable( GL_LIGHTING ); 366 glMatrixMode( GL_TEXTURE ); 367 glLoadIdentity(); 368 glPopAttrib(); 369 glPopClientAttrib(); 370 glCullFace( GL_FRONT ); 371 glDisable( GL_CLIP_PLANE0 ); 341 372 } 342 373 343 374 inline Uint8 getAlpha( const SDL_Surface *_s, int _x, int _y ) 344 375 { 345 int bpp = _s->format->BytesPerPixel; 346 Uint8 *p = (Uint8 *)_s->pixels + _y*_s->pitch + _x * bpp; 347 Uint32 pixel = 0; 348 switch( bpp ) { 376 int bpp = _s->format->BytesPerPixel; 377 Uint8 *p = (Uint8 *)_s->pixels + _y*_s->pitch + _x * bpp; 378 Uint32 pixel = 0; 379 switch( bpp ) 380 { 349 381 case 1: 350 351 382 pixel = *p; 383 break; 352 384 case 2: 353 354 pixel = p[0] << 8 | p[1]; 355 356 357 385 if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) 386 pixel = p[0] << 8 | p[1]; 387 else 388 pixel = *(Uint16 *)p; 389 break; 358 390 case 3: 359 if( SDL_BYTEORDER == SDL_BIG_ENDIAN ) 360 pixel = p[0] << 16 | p[1] << 8 | p[2]; 391 if( SDL_BYTEORDER == SDL_BIG_ENDIAN ) 392 pixel = p[0] << 16 | p[1] << 8 | p[2]; 393 else 394 pixel = p[0] | p[1] << 8 | p[2] << 16; 395 break; 396 case 4: 397 pixel = *(Uint32 *)p; 398 break; 399 default: 400 return 255; /* shouldn't happen, but avoids warnings */ 401 } 402 Uint8 r,g,b,a; 403 SDL_GetRGBA( pixel, _s->format, &r, &g, &b, &a ); 404 return a; 405 } 406 407 void Terrain::determineLayerVisibility( int _layer ) 408 { 409 LayerInfo * layer = layers[_layer]; 410 if ( !layer->alpha ) 411 { 412 int numPages = pagesX*pagesZ; 413 for ( int i = 0; i < numPages; ++i ) 414 pages[i]->setLayerVisibility( _layer, LV_FULL ); 415 416 return; 417 } 418 SDL_Surface *alpha = const_cast<SDL_Surface*>( layer->alpha->getStoredImage() ); 419 SDL_LockSurface( alpha ); 420 float du = ( (float)alpha->w)/pagesX; 421 float dv = ( (float)alpha->h)/pagesZ; 422 float u = 0.0f, v = 0.0f; 423 for ( int pageX = 0; pageX < pagesX; ++pageX ) 424 { 425 v = 0.0f; 426 for ( int pageZ = 0; pageZ < pagesZ; ++pageZ ) 427 { 428 bool full = true; bool has = false; 429 for ( int x = 0; x < (int)PAGE_SIZE; ++x ) 430 { 431 for ( int z = 0; z < (int)PAGE_SIZE; ++z ) 432 { 433 Uint8 a = getAlpha( alpha, (int)u, (int)v ); 434 if ( a ) 435 has = true; 436 if ( a < 255 ) 437 full = false; 438 } 439 } 440 LayerVisibility lv; 441 if ( has ) 442 { 443 if ( full ) 444 lv = LV_FULL; 361 445 else 362 pixel = p[0] | p[1] << 8 | p[2] << 16; 363 break; 364 case 4: 365 pixel = *(Uint32 *)p; 366 break; 367 default: 368 return 255; /* shouldn't happen, but avoids warnings */ 369 } 370 Uint8 r,g,b,a; 371 SDL_GetRGBA( pixel, _s->format, &r, &g, &b, &a ); 372 return a; 373 } 374 375 void Terrain::determineLayerVisibility( int _layer ) 376 { 377 LayerInfo * layer = layers[_layer]; 378 if ( !layer->alpha ) { 379 int numPages = pagesX*pagesZ; 380 for ( int i = 0; i < numPages; ++i ) 381 pages[i]->setLayerVisibility( _layer, LV_FULL ); 382 383 return; 384 } 385 SDL_Surface *alpha = const_cast<SDL_Surface*>( layer->alpha->getStoredImage() ); 386 SDL_LockSurface( alpha ); 387 float du = ( (float)alpha->w)/pagesX; 388 float dv = ( (float)alpha->h)/pagesZ; 389 float u = 0.0f, v = 0.0f; 390 for ( int pageX = 0; pageX < pagesX; ++pageX ) { 391 v = 0.0f; 392 for ( int pageZ = 0; pageZ < pagesZ; ++pageZ ) { 393 bool full = true; bool has = false; 394 for ( int x = 0; x < (int)PAGE_SIZE; ++x ) { 395 for ( int z = 0; z < (int)PAGE_SIZE; ++z ) { 396 Uint8 a = getAlpha( alpha, (int)u, (int)v ); 397 if ( a ) 398 has = true; 399 if ( a < 255 ) 400 full = false; 401 } 402 } 403 LayerVisibility lv; 404 if ( has ) { 405 if ( full ) 406 lv = LV_FULL; 407 else 408 lv = LV_PARTIAL; 409 } 410 else { 411 lv = LV_NO; 412 } 413 getPage( pageX, pageZ )->setLayerVisibility( _layer, lv ); 414 v+= dv; 415 } 416 u+= du; 417 } 418 SDL_UnlockSurface( alpha ); 446 lv = LV_PARTIAL; 447 } 448 else 449 { 450 lv = LV_NO; 451 } 452 getPage( pageX, pageZ )->setLayerVisibility( _layer, lv ); 453 v+= dv; 454 } 455 u+= du; 456 } 457 SDL_UnlockSurface( alpha ); 419 458 } 420 459 421 460 void Terrain::getAltitude( Vector& _alt, Vector& _normal ) 422 461 { 423 float xScaled = _alt.x / scale.x, zScaled = _alt.z / scale.z; 424 //The offset on the map 425 int xOff = (int)xScaled, zOff = (int)zScaled; 426 //The interpolation values. 427 float u = xScaled-xOff, v = zScaled-zOff; 428 429 float dX = scale.x / ( pageSize-1 ); 430 float dZ = scale.z / ( pageSize-1 ); 431 432 //If u is bigger than v, we are on the lower triangle... 433 if ( u > v ) { 434 435 float alt[] = { 436 getAltitude( xOff+0, zOff+0 )*scale.y, 437 getAltitude( xOff+1, zOff+0 )*scale.y, 438 getAltitude( xOff+1, zOff+1 )*scale.y }; 439 _alt.y = (1.0f-u-v)*alt[0]+u*alt[1]+v*alt[2]; 440 441 //Since we know about the directions of some x and z-coordinates, 442 //not the whole cross products needs to be calculated. Grab yourself 443 //pen and paper :) 444 _normal.x = dZ*( alt[0] - alt[1] ); 445 _normal.y = dZ*dX; 446 _normal.z = -dX*( alt[2] - alt[1] ); 447 } 448 else { 449 float alt[] = { 450 getAltitude( xOff+0, zOff+0 )*scale.y, 451 getAltitude( xOff+0, zOff+1 )*scale.y, 452 getAltitude( xOff+1, zOff+1 )*scale.y }; 453 _alt.y = (1.0f-u-v)*alt[0]+v*alt[1]+u*alt[2]; 454 //Since we know about the directions of some x and z-coordinates, 455 //not the whole cross products needs to be calculated. Grab yourself 456 //pen and paper :) 457 _normal.x = -dZ*( alt[2] - alt[1] ); 458 _normal.y = dZ*dX; 459 _normal.z = dX*( alt[0] - alt[1] ); 460 } 462 float xScaled = _alt.x / scale.x, zScaled = _alt.z / scale.z; 463 //The offset on the map 464 int xOff = (int)xScaled, zOff = (int)zScaled; 465 //The interpolation values. 466 float u = xScaled-xOff, v = zScaled-zOff; 467 468 float dX = scale.x / ( pageSize-1 ); 469 float dZ = scale.z / ( pageSize-1 ); 470 471 //If u is bigger than v, we are on the lower triangle... 472 if ( u > v ) 473 { 474 475 float alt[] = { 476 getAltitude( xOff+0, zOff+0 )*scale.y, 477 getAltitude( xOff+1, zOff+0 )*scale.y, 478 getAltitude( xOff+1, zOff+1 )*scale.y }; 479 _alt.y = (1.0f-u-v)*alt[0]+u*alt[1]+v*alt[2]; 480 481 //Since we know about the directions of some x and z-coordinates, 482 //not the whole cross products needs to be calculated. Grab yourself 483 //pen and paper :) 484 _normal.x = dZ*( alt[0] - alt[1] ); 485 _normal.y = dZ*dX; 486 _normal.z = -dX*( alt[2] - alt[1] ); 487 } 488 else 489 { 490 float alt[] = { 491 getAltitude( xOff+0, zOff+0 )*scale.y, 492 getAltitude( xOff+0, zOff+1 )*scale.y, 493 getAltitude( xOff+1, zOff+1 )*scale.y }; 494 _alt.y = (1.0f-u-v)*alt[0]+v*alt[1]+u*alt[2]; 495 //Since we know about the directions of some x and z-coordinates, 496 //not the whole cross products needs to be calculated. Grab yourself 497 //pen and paper :) 498 _normal.x = -dZ*( alt[2] - alt[1] ); 499 _normal.y = dZ*dX; 500 _normal.z = dX*( alt[0] - alt[1] ); 501 } 461 502 } 462 503 463 504 void Terrain::showPages( int _x0, int _z0, int _width, int _height ) 464 505 { 465 for ( int x = 0; x < _width; ++x ) { 466 for ( int z = 0; z < _height; ++z ) { 467 pTerrainPage page = getPage( _x0+x, _z0+z ); 468 page->setVisibility( true ); 469 page->chooseLOD(); 470 471 } 472 } 473 } 506 for ( int x = 0; x < _width; ++x ) 507 { 508 for ( int z = 0; z < _height; ++z ) 509 { 510 pTerrainPage page = getPage( _x0+x, _z0+z ); 511 page->setVisibility( true ); 512 page->chooseLOD(); 513 514 } 515 } 516 }
Note: See TracChangeset
for help on using the changeset viewer.