Changeset 9428 in orxonox.OLD for branches/terrain/src/lib/graphics
- Timestamp:
- Jul 24, 2006, 3:03:32 PM (18 years ago)
- Location:
- branches/terrain/src/lib/graphics/importer/terrain
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/terrain/src/lib/graphics/importer/terrain/terrain.cc
r9424 r9428 26 26 void Terrain::build() 27 27 { 28 29 printf("SHOULD GET LOADED :)\n");30 31 28 ResourceManager *MANAGER = ResourceManager::getInstance(); 32 29 std::string full = MANAGER->getFullName( heightmapSource ); -
branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc
r9415 r9428 29 29 TerrainPage::~TerrainPage( ) 30 30 { 31 32 33 34 31 SAVE_DELETE_ARRAY( indices ); 32 SAVE_DELETE_ARRAY( vertices ); 33 SAVE_DELETE_ARRAY( indexHash ); 34 SAVE_DELETE_ARRAY( errors ); 35 35 } 36 36 37 37 TerrainPage::TerrainPage( Terrain *_owner, int _xOffset, int _zOffset ) 38 : TerrainQuad( _owner, _xOffset, _zOffset )39 { 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 38 : TerrainQuad( _owner, _xOffset, _zOffset ) 39 { 40 scale = owner->getScale(); 41 numVertices = numIndices = 0; 42 errors = new LODError[TerrainPage::MAX_LODS]; 43 vertices = NULL; indices = NULL; 44 left = top = bottom = right = NULL; 45 for ( int i = 0; i < 8; ++i ) 46 layerVisibility[i] = LV_NO; 47 48 position = Vector( scale.x*_xOffset, 49 0.0f, scale.z*_zOffset ); 50 isVisible = false; 51 next = NULL; 52 active = false; 53 previous = NULL; 54 currentLOD = -1; wantedLOD = -1; 55 hasfull = false; 56 forceTesselation = true; 57 vbIdentifier = 0; ibIdentifier = 0; 58 58 } 59 59 60 60 void TerrainPage::tesselateRow( int _z, int _xStride, int _zStride, 61 bool _adaptLeft, bool _adaptRight ) 62 { 63 64 int xStart = 0, xEnd = owner->getPageSize(); 65 int halfStride = _zStride >> 1; 66 assert( _xStride > 0 ); assert( _zStride > 0 ); 67 if ( _z ) { 68 addAgain(); 69 addIndex( getIndex( 0, _z ) ); 70 } 71 if ( _adaptLeft ) { 72 assert( halfStride > 0 ); 73 addIndex( getIndex( 0, _z ) ); 74 addIndex( getIndex( 0, _z+halfStride ) ); 75 addIndex( getIndex( _xStride, _z ) ); 76 addIndex( getIndex( 0, _z+_zStride ) ); 77 addIndex( getIndex( _xStride, _z+_zStride ) ); 78 addAgain(); 79 xStart = _xStride; 80 } 81 82 if ( _adaptRight ) 83 xEnd-=_xStride; 84 85 for ( int x = xStart; x < xEnd; x+=_xStride ) { 86 addIndex( getIndex( x, _z) ); 87 addIndex( getIndex( x, _z+_zStride ) ); 88 } 89 90 int w = owner->getPageSize()-1; 91 92 if ( _adaptRight ) { 93 assert( halfStride > 0 ); 94 addIndex( getIndex( xEnd-1, _z ) ); 95 addAgain(); 96 addIndex( getIndex( w, _z ) ); 97 addIndex( getIndex( xEnd-1, _z+_zStride ) ); 98 addIndex( getIndex( w, _z+halfStride ) ); 99 addIndex( getIndex( w, _z+_zStride ) ); 100 } 61 bool _adaptLeft, bool _adaptRight ) 62 { 63 64 int xStart = 0, xEnd = owner->getPageSize(); 65 int halfStride = _zStride >> 1; 66 assert( _xStride > 0 ); assert( _zStride > 0 ); 67 if ( _z ) 68 { 69 addAgain(); 70 addIndex( getIndex( 0, _z ) ); 71 } 72 if ( _adaptLeft ) 73 { 74 assert( halfStride > 0 ); 75 addIndex( getIndex( 0, _z ) ); 76 addIndex( getIndex( 0, _z+halfStride ) ); 77 addIndex( getIndex( _xStride, _z ) ); 78 addIndex( getIndex( 0, _z+_zStride ) ); 79 addIndex( getIndex( _xStride, _z+_zStride ) ); 80 addAgain(); 81 xStart = _xStride; 82 } 83 84 if ( _adaptRight ) 85 xEnd-=_xStride; 86 87 for ( int x = xStart; x < xEnd; x+=_xStride ) 88 { 89 addIndex( getIndex( x, _z) ); 90 addIndex( getIndex( x, _z+_zStride ) ); 91 } 92 93 int w = owner->getPageSize()-1; 94 95 if ( _adaptRight ) 96 { 97 assert( halfStride > 0 ); 98 addIndex( getIndex( xEnd-1, _z ) ); 99 addAgain(); 100 addIndex( getIndex( w, _z ) ); 101 addIndex( getIndex( xEnd-1, _z+_zStride ) ); 102 addIndex( getIndex( w, _z+halfStride ) ); 103 addIndex( getIndex( w, _z+_zStride ) ); 104 } 101 105 } 102 106 … … 105 109 void TerrainPage::determineBorderAdaption( bool _adapt[] ) 106 110 { 107 _adapt[0] = _adapt[1] = _adapt[2] = _adapt[3] = false; 108 109 if ( left && left->isActive() ) { 110 _adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0; 111 assert( std::abs( wantedLOD - left->wantedLOD ) < 2 ); 112 } 113 if ( right && right->isActive() ) { 114 _adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0; 115 assert( std::abs( wantedLOD - right->wantedLOD ) < 2 ); 116 } 117 118 if ( top && top->isActive() ) { 119 _adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0; 120 assert( std::abs( wantedLOD - top->wantedLOD ) < 2 ); 121 } 122 if ( bottom && bottom->isActive() ) { 123 _adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0; 124 assert( std::abs( wantedLOD - bottom->wantedLOD ) < 2 ); 125 } 111 _adapt[0] = _adapt[1] = _adapt[2] = _adapt[3] = false; 112 113 if ( left && left->isActive() ) 114 { 115 _adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0; 116 assert( std::abs( wantedLOD - left->wantedLOD ) < 2 ); 117 } 118 if ( right && right->isActive() ) 119 { 120 _adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0; 121 assert( std::abs( wantedLOD - right->wantedLOD ) < 2 ); 122 } 123 124 if ( top && top->isActive() ) 125 { 126 _adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0; 127 assert( std::abs( wantedLOD - top->wantedLOD ) < 2 ); 128 } 129 if ( bottom && bottom->isActive() ) 130 { 131 _adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0; 132 assert( std::abs( wantedLOD - bottom->wantedLOD ) < 2 ); 133 } 126 134 } 127 135 128 136 int TerrainPage::chooseLOD() 129 137 { 130 wantedLOD = -1; 131 Vector cam( owner->getCameraPosition() ); 132 133 for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) { 134 Vector distance( cam.x-errors[i].correct.x, 135 cam.y-errors[i].correct.y, 136 cam.z-errors[i].correct.z ); 137 138 float d = distance.len(); 139 140 float err = errors[i].diff / d ; 141 142 if ( err*scale.y < owner->getDetail() ) { 143 wantedLOD = i; 144 break; 145 } 146 } 147 if ( wantedLOD < 0 ) { 148 wantedLOD = TerrainPage::MAX_LODS-1; 149 } 150 return wantedLOD; 138 wantedLOD = -1; 139 Vector cam( owner->getCameraPosition() ); 140 141 for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) 142 { 143 Vector distance( cam.x-errors[i].correct.x, 144 cam.y-errors[i].correct.y, 145 cam.z-errors[i].correct.z ); 146 147 float d = distance.len(); 148 149 float err = errors[i].diff / d ; 150 151 if ( err*scale.y < owner->getDetail() ) 152 { 153 wantedLOD = i; 154 break; 155 } 156 } 157 if ( wantedLOD < 0 ) 158 { 159 wantedLOD = TerrainPage::MAX_LODS-1; 160 } 161 return wantedLOD; 151 162 } 152 163 … … 154 165 { 155 166 156 157 158 159 160 167 pTerrainPage list = owner->getActiveList(); 168 next = list; 169 if ( list ) 170 list->previous = this; 171 owner->setActiveList( this ); 161 172 } 162 173 163 174 void TerrainPage::deactivate() 164 175 { 165 pTerrainPage list = owner->getActiveList(); 166 167 if ( previous ) { 168 previous->next = next; 169 } 170 if ( next ) { 171 next->previous = previous; 172 } 173 if ( list == this ) 174 owner->setActiveList( next ); 175 next = NULL; 176 previous = NULL; 176 pTerrainPage list = owner->getActiveList(); 177 178 if ( previous ) 179 { 180 previous->next = next; 181 } 182 if ( next ) 183 { 184 next->previous = previous; 185 } 186 if ( list == this ) 187 owner->setActiveList( next ); 188 next = NULL; 189 previous = NULL; 177 190 178 191 } … … 180 193 void TerrainPage::calculateError( int _lod ) 181 194 { 182 float sumError = 0.0f; 183 int numErrors = 0; 184 int size = owner->getPageSize(); 185 if( _lod!=0 ) 186 { 187 int stride = 1 << _lod, x0, y0, xi, yi; 188 // Altough these four nested loops look very scary, they're not 189 // that bad and require only about O(n^2). 190 for( y0 = 0 ; y0 < size-stride; y0 += stride ) { 191 for( x0 = 0; x0 < size-stride; x0 += stride ) { 192 for( yi = 1; yi < stride; yi++ ) { 193 for( xi = 1; xi < stride; xi++ ) 194 { 195 int x = x0+xi, 196 y = y0+yi; 197 float fx0 = ( float )xi/( float )stride, fx1 = 1.0f-fx0, 198 fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0; 199 200 float height00 = getAltitude( x0, y0 ), 201 height10 = getAltitude( x0+stride,y0 ), 202 height01 = getAltitude( x0,y0+stride ), 203 height11 = getAltitude( x0+stride, y0+stride ); 204 205 float paintHeight = fx1*fy1 * height00 + 206 fx0*fy1 * height10 + 207 fx1*fy0 * height01 + 208 fx0*fy0 * height11, 209 correctHeight = getAltitude( x, y ); 210 211 float er = ( float )fabs( correctHeight - paintHeight ); 212 213 numErrors++; 214 sumError += er; 215 } 216 } 217 } 218 } 219 float error = sumError / numErrors; 220 getVertex(size/2, size/2, errors[_lod].correct); 221 errors[_lod].real = errors[_lod].correct; 222 errors[_lod].real.y += error; 223 errors[_lod].diff = error; 224 } 195 float sumError = 0.0f; 196 int numErrors = 0; 197 int size = owner->getPageSize(); 198 if( _lod!=0 ) 199 { 200 int stride = 1 << _lod, x0, y0, xi, yi; 201 // Altough these four nested loops look very scary, they're not 202 // that bad and require only about O(n^2). 203 for( y0 = 0 ; y0 < size-stride; y0 += stride ) 204 { 205 for( x0 = 0; x0 < size-stride; x0 += stride ) 206 { 207 for( yi = 1; yi < stride; yi++ ) 208 { 209 for( xi = 1; xi < stride; xi++ ) 210 { 211 int x = x0+xi, 212 y = y0+yi; 213 float fx0 = ( float )xi/( float )stride, fx1 = 1.0f-fx0, 214 fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0; 215 216 float height00 = getAltitude( x0, y0 ), 217 height10 = getAltitude( x0+stride,y0 ), 218 height01 = getAltitude( x0,y0+stride ), 219 height11 = getAltitude( x0+stride, y0+stride ); 220 221 float paintHeight = fx1*fy1 * height00 + 222 fx0*fy1 * height10 + 223 fx1*fy0 * height01 + 224 fx0*fy0 * height11, 225 correctHeight = getAltitude( x, y ); 226 227 float er = ( float )fabs( correctHeight - paintHeight ); 228 229 numErrors++; 230 sumError += er; 231 } 232 } 233 } 234 } 235 float error = sumError / numErrors; 236 getVertex(size/2, size/2, errors[_lod].correct); 237 errors[_lod].real = errors[_lod].correct; 238 errors[_lod].real.y += error; 239 errors[_lod].diff = error; 240 } 225 241 } 226 242 227 243 void TerrainPage::calculateBounds() 228 244 { 229 int size = owner->getPageSize(); 230 float alt = 0.0f; 231 232 Vector min( xOffset*scale.x ,0.0f, zOffset*scale.z ), 233 max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z); 234 235 min.y = max.y = getAltitude( 0, 0 ); 236 for ( int x = 0; x < size; ++x ) { 237 for ( int z = 0; z < size; ++z ) { 238 alt = getAltitude( x, z ); 239 min.y = fmin( min.y, alt-1.0f ); 240 max.y = fmax( max.y, alt+1.0f ); 241 } 242 } 243 bounds.set( min, max ); 245 int size = owner->getPageSize(); 246 float alt = 0.0f; 247 248 Vector min( xOffset*scale.x ,0.0f, zOffset*scale.z ), 249 max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z); 250 251 min.y = max.y = getAltitude( 0, 0 ); 252 for ( int x = 0; x < size; ++x ) 253 { 254 for ( int z = 0; z < size; ++z ) 255 { 256 alt = getAltitude( x, z ); 257 min.y = fmin( min.y, alt-1.0f ); 258 max.y = fmax( max.y, alt+1.0f ); 259 } 260 } 261 bounds.set( min, max ); 244 262 } 245 263 246 264 float TerrainPage::getAltitude( int _x, int _z ) const 247 265 { 248 249 250 251 252 266 assert( _x >= 0 && _x < 17 ); 267 assert( _z >= 0 && _z < 17 ); 268 return position.y+scale.y*owner->getAltitude( 269 _x+(owner->getPageSize()-1)*xOffset, 270 _z+(owner->getPageSize()-1)*zOffset ); 253 271 } 254 272 … … 256 274 { 257 275 258 259 260 261 262 263 264 265 266 267 268 269 276 bool leftChanged = ( left && left->isActive() ) && 277 ( left->wantedLOD != left->currentLOD ), 278 rightChanged = ( right && right->isActive() ) && 279 ( right->wantedLOD != right->currentLOD ), 280 topChanged = ( top && top->isActive() ) && 281 ( top->wantedLOD != currentLOD ), 282 bottomChanged = ( bottom && bottom->isActive() ) && 283 ( bottom->wantedLOD != bottom->currentLOD ), 284 iChanged = wantedLOD != currentLOD; 285 286 return ( leftChanged || rightChanged || topChanged || bottomChanged || 287 forceTesselation || iChanged ); 270 288 } 271 289 272 290 void TerrainPage::updateTesselation( ) 273 291 { 274 assert( wantedLOD < 5 && wantedLOD >= 0 ); 275 if ( needsRetesselation() ) { 276 tesselate( wantedLOD ); 277 } 278 currentLOD = wantedLOD; 279 280 //Check if the page is a level four page. If yes, copy the vertex and index data into 281 //the shared level four page buffers. 282 if ( currentLOD == TerrainPage::MAX_LODS-1 ) { 283 owner->addLevelFourPage( numVertices, vertices, 284 numIndices, indices ); 285 } 286 forceTesselation = false; 292 assert( wantedLOD < 5 && wantedLOD >= 0 ); 293 if ( needsRetesselation() ) 294 { 295 tesselate( wantedLOD ); 296 } 297 currentLOD = wantedLOD; 298 299 //Check if the page is a level four page. If yes, copy the vertex and index data into 300 //the shared level four page buffers. 301 if ( currentLOD == TerrainPage::MAX_LODS-1 ) 302 { 303 owner->addLevelFourPage( numVertices, vertices, 304 numIndices, indices ); 305 } 306 forceTesselation = false; 287 307 } 288 308 289 309 void TerrainPage::tesselateTopRow( int _z, int _stride, 290 bool _adaptLeft, bool _adaptRight ) 291 { 292 int halfStride = _stride/2; 293 int xStart = 0, xEnd= owner->getPageSize()-1; 294 int size = xEnd; 295 int z = xEnd-_stride ; 296 addAgain(); 297 addIndex( getIndex( 0, z ) ); 298 assert(halfStride>=1); 299 300 if( _adaptLeft ) { 301 addIndex( getIndex( 0, z ) ); 302 addIndex( getIndex( 0, z+halfStride ) ); 303 addIndex( getIndex( _stride, z ) ); 304 addIndex( getIndex( 0, size ) ); 305 addIndex( getIndex( halfStride, size ) ); 306 addAgain(); 307 addIndex( getIndex( _stride, z ) ); 308 addIndex( getIndex( _stride, size ) ); 309 xStart = _stride; 310 } 311 312 if ( _adaptRight ) 313 xEnd -= _stride; 314 for ( int x = xStart; x < xEnd; x+=_stride ) { 315 addIndex( getIndex( x, z ) ); 316 addIndex( getIndex( x, size ) ); 317 addIndex( getIndex( x+_stride, z ) ); 318 addIndex( getIndex( x+halfStride, size ) ); 319 addIndex( getIndex( x+_stride, size ) ); 320 addAgain(); 321 } 322 323 if ( _adaptRight ) { 324 addIndex( getIndex( xEnd, z ) ); 325 addIndex( getIndex( xEnd, size ) ); 326 addIndex( getIndex( size, z ) ); 327 addIndex( getIndex( xEnd+halfStride, size ) ); 328 addIndex( getIndex( size, size-halfStride ) ); 329 addIndex( getIndex( size, size ) ); 330 } 310 bool _adaptLeft, bool _adaptRight ) 311 { 312 int halfStride = _stride/2; 313 int xStart = 0, xEnd= owner->getPageSize()-1; 314 int size = xEnd; 315 int z = xEnd-_stride ; 316 addAgain(); 317 addIndex( getIndex( 0, z ) ); 318 assert(halfStride>=1); 319 320 if( _adaptLeft ) 321 { 322 addIndex( getIndex( 0, z ) ); 323 addIndex( getIndex( 0, z+halfStride ) ); 324 addIndex( getIndex( _stride, z ) ); 325 addIndex( getIndex( 0, size ) ); 326 addIndex( getIndex( halfStride, size ) ); 327 addAgain(); 328 addIndex( getIndex( _stride, z ) ); 329 addIndex( getIndex( _stride, size ) ); 330 xStart = _stride; 331 } 332 333 if ( _adaptRight ) 334 xEnd -= _stride; 335 for ( int x = xStart; x < xEnd; x+=_stride ) 336 { 337 addIndex( getIndex( x, z ) ); 338 addIndex( getIndex( x, size ) ); 339 addIndex( getIndex( x+_stride, z ) ); 340 addIndex( getIndex( x+halfStride, size ) ); 341 addIndex( getIndex( x+_stride, size ) ); 342 addAgain(); 343 } 344 345 if ( _adaptRight ) 346 { 347 addIndex( getIndex( xEnd, z ) ); 348 addIndex( getIndex( xEnd, size ) ); 349 addIndex( getIndex( size, z ) ); 350 addIndex( getIndex( xEnd+halfStride, size ) ); 351 addIndex( getIndex( size, size-halfStride ) ); 352 addIndex( getIndex( size, size ) ); 353 } 331 354 332 355 } 333 356 void TerrainPage::tesselateBottomRow( int _z, int _stride, 334 bool _adaptLeft, bool _adaptRight ) 335 { 336 int halfStride = _stride/2; 337 int xStart=0, xEnd=owner->getPageSize()-1; 338 int size = xEnd; 339 assert( halfStride>=1 ); 340 341 if ( _adaptLeft ) { 342 addIndex( getIndex( 0, 0 ) ); 343 addIndex( getIndex( 0, halfStride ) ); 344 addIndex( getIndex( halfStride, 0 ) ); 345 addIndex( getIndex( 0, _stride ) ); 346 addIndex( getIndex( _stride, 0 ) ); 347 addIndex( getIndex( _stride, _stride ) ); 348 xStart = _stride; 349 } 350 351 352 if ( _adaptRight ) 353 xEnd -= _stride; 354 355 for ( int x = xStart; x < xEnd; x+=_stride ) { 356 addIndex( getIndex( x, 0 ) ); 357 addAgain(); 358 addIndex( getIndex( x+halfStride, 0 ) ); 359 addIndex( getIndex( x, _stride ) ); 360 addIndex( getIndex( x+_stride ,0 ) ); 361 addIndex( getIndex( x+_stride, _stride ) ); 362 } 363 364 365 if( _adaptRight ) { 366 addIndex( getIndex( xEnd,0 ) ); 367 addIndex( getIndex( xEnd,_stride ) ); 368 addIndex( getIndex( xEnd+halfStride, 0 ) ); 369 addIndex( getIndex( size ,0 ) ); 370 addAgain(); 371 addIndex( getIndex( xEnd, _stride ) ); 372 addIndex( getIndex( size, halfStride ) ); 373 addIndex( getIndex( size, _stride ) ); 374 } 357 bool _adaptLeft, bool _adaptRight ) 358 { 359 int halfStride = _stride/2; 360 int xStart=0, xEnd=owner->getPageSize()-1; 361 int size = xEnd; 362 assert( halfStride>=1 ); 363 364 if ( _adaptLeft ) 365 { 366 addIndex( getIndex( 0, 0 ) ); 367 addIndex( getIndex( 0, halfStride ) ); 368 addIndex( getIndex( halfStride, 0 ) ); 369 addIndex( getIndex( 0, _stride ) ); 370 addIndex( getIndex( _stride, 0 ) ); 371 addIndex( getIndex( _stride, _stride ) ); 372 xStart = _stride; 373 } 374 375 376 if ( _adaptRight ) 377 xEnd -= _stride; 378 379 for ( int x = xStart; x < xEnd; x+=_stride ) 380 { 381 addIndex( getIndex( x, 0 ) ); 382 addAgain(); 383 addIndex( getIndex( x+halfStride, 0 ) ); 384 addIndex( getIndex( x, _stride ) ); 385 addIndex( getIndex( x+_stride ,0 ) ); 386 addIndex( getIndex( x+_stride, _stride ) ); 387 } 388 389 390 if( _adaptRight ) 391 { 392 addIndex( getIndex( xEnd,0 ) ); 393 addIndex( getIndex( xEnd,_stride ) ); 394 addIndex( getIndex( xEnd+halfStride, 0 ) ); 395 addIndex( getIndex( size ,0 ) ); 396 addAgain(); 397 addIndex( getIndex( xEnd, _stride ) ); 398 addIndex( getIndex( size, halfStride ) ); 399 addIndex( getIndex( size, _stride ) ); 400 } 375 401 } 376 402 377 403 void TerrainPage::tesselateLevelFourPage( bool _adapt[] ) 378 404 { 379 assert( indices ); assert( vertices ); 380 numIndices = numVertices = 0; 381 const int halfStride = 8, stride = 16; 382 383 enum { ADAPT_L = 1, ADAPT_R = 2, ADAPT_B = 4, ADAPT_T = 8, 384 ADAPT_LR = 3, ADAPT_LB = 5, ADAPT_LT = 9, ADAPT_RB = 6, 385 ADAPT_RT = 10, ADAPT_BT = 12, ADAPT_LRB = 7, ADAPT_LBT = 13, ADAPT_LRT = 11, 386 ADAPT_RBT = 14, ADAPT_LRBT = 15, ADAPT_NONE = 0 }; 387 388 int code = ( _adapt[TP_LEFT] ? ADAPT_L : 0 ) | 389 ( _adapt[TP_RIGHT] ? ADAPT_R : 0 ) | 390 ( _adapt[TP_BOTTOM] ? ADAPT_B : 0 ) | 391 ( _adapt[TP_TOP] ? ADAPT_T : 0 ); 392 switch( code ) { 393 case ADAPT_NONE: 394 addIndex( getIndex( 0, 0 ) ); 395 addIndex( getIndex( 0, stride ) ); 396 addIndex( getIndex( stride, 0 ) ); 397 addIndex( getIndex( stride, stride ) ); 398 break; 399 400 case ADAPT_L: 401 addIndex( getIndex( 0, 0 ) ); 402 addIndex( getIndex( 0, halfStride ) ); 403 addIndex( getIndex( stride, 0 ) ); 404 addIndex( getIndex( 0, stride ) ); 405 addIndex( getIndex( stride, stride ) ); 406 addAgain( ); 407 break; 408 409 case ADAPT_R: 410 addIndex( getIndex( stride, stride ) ); 411 addIndex( getIndex( stride, halfStride ) ); 412 addIndex( getIndex( 0, stride ) ); 413 addIndex( getIndex( stride, 0 ) ); 414 addIndex( getIndex( 0, 0 ) ); 415 addAgain( ); 416 break; 417 418 case ADAPT_LR: 419 addIndex( getIndex( 0, 0 ) ); 420 addIndex( getIndex( 0, halfStride ) ); 421 addIndex( getIndex( stride, 0 ) ); 422 addIndex( getIndex( 0, stride ) ); 423 addIndex( getIndex( stride, halfStride ) ); 424 addIndex( getIndex( stride, stride ) ); 425 break; 426 427 case ADAPT_B: 428 addIndex( getIndex( 0, 0 ) ); 429 addAgain(); 430 addIndex( getIndex( halfStride, 0 ) ); 431 addIndex( getIndex( 0, stride ) ); 432 addIndex( getIndex( stride, 0 ) ); 433 addIndex( getIndex( stride, stride ) ); 434 break; 435 436 case ADAPT_LB: 437 addIndex( getIndex( 0, 0 ) ); 438 addIndex( getIndex( 0, halfStride ) ); 439 addIndex( getIndex( halfStride, 0 ) ); 440 addIndex( getIndex( 0, stride ) ); 441 addIndex( getIndex( stride, 0 ) ); 442 addIndex( getIndex( stride, stride ) ); 443 break; 444 445 case ADAPT_RB: 446 addIndex( getIndex( 0, 0 ) ); 447 addIndex( getIndex( 0, stride ) ); 448 addIndex( getIndex( halfStride, 0 ) ); 449 addIndex( getIndex( stride, 0 ) ); 450 addAgain( ); 451 addIndex( getIndex( 0, stride ) ); 452 addIndex( getIndex( stride, halfStride ) ); 453 addIndex( getIndex( stride, stride ) ); 454 break; 455 456 case ADAPT_LRB: 457 addIndex( getIndex( stride, stride ) ); 458 addIndex( getIndex( stride, halfStride ) ); 459 addIndex( getIndex( 0, stride ) ); 460 addIndex( getIndex( stride, 0 ) ); 461 addIndex( getIndex( 0, halfStride ) ); 462 addIndex( getIndex( halfStride, 0 ) ); 463 addIndex( getIndex( 0, 0 ) ); 464 addAgain( ); 465 break; 466 467 case ADAPT_T: 468 addIndex( getIndex( stride, stride ) ); 469 addAgain( ); 470 addIndex( getIndex( halfStride, stride ) ); 471 addIndex( getIndex( stride, 0 ) ); 472 addIndex( getIndex( 0, stride ) ); 473 addIndex( getIndex( 0, 0 ) ); 474 break; 475 476 case ADAPT_LT: 477 addIndex( getIndex( stride, stride ) ); 478 addIndex( getIndex( stride, 0 ) ); 479 addIndex( getIndex( halfStride, stride ) ); 480 addIndex( getIndex( 0, stride ) ); 481 addAgain( ); 482 addIndex( getIndex( stride, 0 ) ); 483 addIndex( getIndex( 0, halfStride ) ); 484 addIndex( getIndex( 0, 0 ) ); 485 break; 486 487 case ADAPT_RT: 488 addIndex( getIndex( stride, stride ) ); 489 addIndex( getIndex( stride, halfStride ) ); 490 addIndex( getIndex( halfStride, stride ) ); 491 addIndex( getIndex( stride, 0 ) ); 492 addIndex( getIndex( 0, stride ) ); 493 addIndex( getIndex( 0, 0 ) ); 494 break; 495 496 case ADAPT_LRT: 497 addIndex( getIndex( 0, 0 ) ); 498 addIndex( getIndex( 0, halfStride ) ); 499 addIndex( getIndex( stride, 0 ) ); 500 addIndex( getIndex( 0, stride ) ); 501 addIndex( getIndex( stride, halfStride ) ); 502 addIndex( getIndex( halfStride, stride ) ); 503 addIndex( getIndex( stride, stride ) ); 504 addAgain( ); 505 break; 506 507 case ADAPT_BT: 508 addIndex( getIndex( 0, 0 ) ); 509 addAgain( ); 510 addIndex( getIndex( halfStride, 0 ) ); 511 addIndex( getIndex( 0, stride ) ); 512 addIndex( getIndex( stride, 0 ) ); 513 addIndex( getIndex( halfStride, stride ) ); 514 addIndex( getIndex( stride, stride ) ); 515 addAgain( ); 516 break; 517 518 case ADAPT_LBT: 519 addIndex( getIndex( 0, 0 ) ); 520 addIndex( getIndex( 0, halfStride ) ); 521 addIndex( getIndex( halfStride, 0 ) ); 522 addIndex( getIndex( 0, stride ) ); 523 addIndex( getIndex( stride, 0 ) ); 524 addIndex( getIndex( halfStride, stride ) ); 525 addIndex( getIndex( stride, stride ) ); 526 addAgain( ); 527 break; 528 529 case ADAPT_RBT: 530 addIndex( getIndex( stride, stride ) ); 531 addIndex( getIndex( stride, halfStride ) ); 532 addIndex( getIndex( halfStride, stride ) ); 533 addIndex( getIndex( stride, 0 ) ); 534 addIndex( getIndex( 0, stride ) ); 535 addIndex( getIndex( halfStride, 0 ) ); 536 addIndex( getIndex( 0, 0 ) ); 537 addAgain( ); 538 break; 539 540 case ADAPT_LRBT: 541 addIndex( getIndex( 0, 0 ) ); 542 addIndex( getIndex( 0, halfStride ) ); 543 addIndex( getIndex( halfStride, 0 ) ); 544 addIndex( getIndex( 0, stride ) ); 545 addIndex( getIndex( stride, 0 ) ); 546 addIndex( getIndex( halfStride, stride ) ); 547 addIndex( getIndex( stride, halfStride ) ); 548 addIndex( getIndex( stride, stride ) ); 549 break; 550 } 551 assert( numIndices % 2 == 0 ); 405 assert( indices ); assert( vertices ); 406 numIndices = numVertices = 0; 407 const int halfStride = 8, stride = 16; 408 409 enum { ADAPT_L = 1, ADAPT_R = 2, ADAPT_B = 4, ADAPT_T = 8, 410 ADAPT_LR = 3, ADAPT_LB = 5, ADAPT_LT = 9, ADAPT_RB = 6, 411 ADAPT_RT = 10, ADAPT_BT = 12, ADAPT_LRB = 7, ADAPT_LBT = 13, ADAPT_LRT = 11, 412 ADAPT_RBT = 14, ADAPT_LRBT = 15, ADAPT_NONE = 0 }; 413 414 int code = ( _adapt[TP_LEFT] ? ADAPT_L : 0 ) | 415 ( _adapt[TP_RIGHT] ? ADAPT_R : 0 ) | 416 ( _adapt[TP_BOTTOM] ? ADAPT_B : 0 ) | 417 ( _adapt[TP_TOP] ? ADAPT_T : 0 ); 418 switch( code ) 419 { 420 case ADAPT_NONE: 421 addIndex( getIndex( 0, 0 ) ); 422 addIndex( getIndex( 0, stride ) ); 423 addIndex( getIndex( stride, 0 ) ); 424 addIndex( getIndex( stride, stride ) ); 425 break; 426 427 case ADAPT_L: 428 addIndex( getIndex( 0, 0 ) ); 429 addIndex( getIndex( 0, halfStride ) ); 430 addIndex( getIndex( stride, 0 ) ); 431 addIndex( getIndex( 0, stride ) ); 432 addIndex( getIndex( stride, stride ) ); 433 addAgain( ); 434 break; 435 436 case ADAPT_R: 437 addIndex( getIndex( stride, stride ) ); 438 addIndex( getIndex( stride, halfStride ) ); 439 addIndex( getIndex( 0, stride ) ); 440 addIndex( getIndex( stride, 0 ) ); 441 addIndex( getIndex( 0, 0 ) ); 442 addAgain( ); 443 break; 444 445 case ADAPT_LR: 446 addIndex( getIndex( 0, 0 ) ); 447 addIndex( getIndex( 0, halfStride ) ); 448 addIndex( getIndex( stride, 0 ) ); 449 addIndex( getIndex( 0, stride ) ); 450 addIndex( getIndex( stride, halfStride ) ); 451 addIndex( getIndex( stride, stride ) ); 452 break; 453 454 case ADAPT_B: 455 addIndex( getIndex( 0, 0 ) ); 456 addAgain(); 457 addIndex( getIndex( halfStride, 0 ) ); 458 addIndex( getIndex( 0, stride ) ); 459 addIndex( getIndex( stride, 0 ) ); 460 addIndex( getIndex( stride, stride ) ); 461 break; 462 463 case ADAPT_LB: 464 addIndex( getIndex( 0, 0 ) ); 465 addIndex( getIndex( 0, halfStride ) ); 466 addIndex( getIndex( halfStride, 0 ) ); 467 addIndex( getIndex( 0, stride ) ); 468 addIndex( getIndex( stride, 0 ) ); 469 addIndex( getIndex( stride, stride ) ); 470 break; 471 472 case ADAPT_RB: 473 addIndex( getIndex( 0, 0 ) ); 474 addIndex( getIndex( 0, stride ) ); 475 addIndex( getIndex( halfStride, 0 ) ); 476 addIndex( getIndex( stride, 0 ) ); 477 addAgain( ); 478 addIndex( getIndex( 0, stride ) ); 479 addIndex( getIndex( stride, halfStride ) ); 480 addIndex( getIndex( stride, stride ) ); 481 break; 482 483 case ADAPT_LRB: 484 addIndex( getIndex( stride, stride ) ); 485 addIndex( getIndex( stride, halfStride ) ); 486 addIndex( getIndex( 0, stride ) ); 487 addIndex( getIndex( stride, 0 ) ); 488 addIndex( getIndex( 0, halfStride ) ); 489 addIndex( getIndex( halfStride, 0 ) ); 490 addIndex( getIndex( 0, 0 ) ); 491 addAgain( ); 492 break; 493 494 case ADAPT_T: 495 addIndex( getIndex( stride, stride ) ); 496 addAgain( ); 497 addIndex( getIndex( halfStride, stride ) ); 498 addIndex( getIndex( stride, 0 ) ); 499 addIndex( getIndex( 0, stride ) ); 500 addIndex( getIndex( 0, 0 ) ); 501 break; 502 503 case ADAPT_LT: 504 addIndex( getIndex( stride, stride ) ); 505 addIndex( getIndex( stride, 0 ) ); 506 addIndex( getIndex( halfStride, stride ) ); 507 addIndex( getIndex( 0, stride ) ); 508 addAgain( ); 509 addIndex( getIndex( stride, 0 ) ); 510 addIndex( getIndex( 0, halfStride ) ); 511 addIndex( getIndex( 0, 0 ) ); 512 break; 513 514 case ADAPT_RT: 515 addIndex( getIndex( stride, stride ) ); 516 addIndex( getIndex( stride, halfStride ) ); 517 addIndex( getIndex( halfStride, stride ) ); 518 addIndex( getIndex( stride, 0 ) ); 519 addIndex( getIndex( 0, stride ) ); 520 addIndex( getIndex( 0, 0 ) ); 521 break; 522 523 case ADAPT_LRT: 524 addIndex( getIndex( 0, 0 ) ); 525 addIndex( getIndex( 0, halfStride ) ); 526 addIndex( getIndex( stride, 0 ) ); 527 addIndex( getIndex( 0, stride ) ); 528 addIndex( getIndex( stride, halfStride ) ); 529 addIndex( getIndex( halfStride, stride ) ); 530 addIndex( getIndex( stride, stride ) ); 531 addAgain( ); 532 break; 533 534 case ADAPT_BT: 535 addIndex( getIndex( 0, 0 ) ); 536 addAgain( ); 537 addIndex( getIndex( halfStride, 0 ) ); 538 addIndex( getIndex( 0, stride ) ); 539 addIndex( getIndex( stride, 0 ) ); 540 addIndex( getIndex( halfStride, stride ) ); 541 addIndex( getIndex( stride, stride ) ); 542 addAgain( ); 543 break; 544 545 case ADAPT_LBT: 546 addIndex( getIndex( 0, 0 ) ); 547 addIndex( getIndex( 0, halfStride ) ); 548 addIndex( getIndex( halfStride, 0 ) ); 549 addIndex( getIndex( 0, stride ) ); 550 addIndex( getIndex( stride, 0 ) ); 551 addIndex( getIndex( halfStride, stride ) ); 552 addIndex( getIndex( stride, stride ) ); 553 addAgain( ); 554 break; 555 556 case ADAPT_RBT: 557 addIndex( getIndex( stride, stride ) ); 558 addIndex( getIndex( stride, halfStride ) ); 559 addIndex( getIndex( halfStride, stride ) ); 560 addIndex( getIndex( stride, 0 ) ); 561 addIndex( getIndex( 0, stride ) ); 562 addIndex( getIndex( halfStride, 0 ) ); 563 addIndex( getIndex( 0, 0 ) ); 564 addAgain( ); 565 break; 566 567 case ADAPT_LRBT: 568 addIndex( getIndex( 0, 0 ) ); 569 addIndex( getIndex( 0, halfStride ) ); 570 addIndex( getIndex( halfStride, 0 ) ); 571 addIndex( getIndex( 0, stride ) ); 572 addIndex( getIndex( stride, 0 ) ); 573 addIndex( getIndex( halfStride, stride ) ); 574 addIndex( getIndex( stride, halfStride ) ); 575 addIndex( getIndex( stride, stride ) ); 576 break; 577 } 578 assert( numIndices % 2 == 0 ); 552 579 } 553 580 … … 556 583 { 557 584 558 559 560 561 562 563 564 565 566 567 568 585 memset( indexHash, 0xffff, 586 sizeof(unsigned short)*Terrain::MAX_VERTICES ); 587 588 numVertices = 0; numIndices = 0; 589 590 //Calculate the pace, based on the lod. 591 int stride = 1 << _lod; 592 593 bool adapt[4]; 594 determineBorderAdaption( adapt ); 595 assert( isVisible ); 569 596 #ifdef USE_VBO 570 if ( _lod == TerrainPage::MAX_LODS-1 ) { 571 if ( vbIdentifier && ibIdentifier ) { 572 owner->getBufferBroker()->release( vbIdentifier, ibIdentifier ); 573 vbIdentifier = ibIdentifier = 0; 574 } 575 if ( !vertices ) 576 vertices = new Vertex[8]; 577 if ( !indices ) 578 indices = new unsigned short[8]; 579 } 580 else { 581 if ( !vbIdentifier && !ibIdentifier ) { 582 owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier ); 583 if ( vertices ) 584 delete[] vertices; 585 if ( indices ) 586 delete[] indices; 587 vertices = NULL; indices = NULL; 588 } 589 assert( vbIdentifier ); assert( ibIdentifier ); 590 glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier ); 591 592 // The call to glBufferDataARB with a null argument for data is to make things faster. 593 // Then calling call glMapBuffer() tells the driver that the previous 594 // data aren’t valid. As a consequence, if the GPU is still working on them, there won’t 595 // be a conflict because we invalidated these data. The function glMapBuffer() returns a 596 // new pointer that we can use while the GPU is working on the previous set of data.. 597 598 glBufferDataARB( GL_ARRAY_BUFFER_ARB, Terrain::MAX_VERTICES*sizeof( Vertex ), 599 NULL, GL_DYNAMIC_DRAW_ARB ); 600 601 vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB, 602 GL_WRITE_ONLY_ARB ); 603 604 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier ); 605 606 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 607 Terrain::MAX_INDICES*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB ); 608 609 indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 610 GL_WRITE_ONLY_ARB ); 611 612 } 597 if ( _lod == TerrainPage::MAX_LODS-1 ) 598 { 599 if ( vbIdentifier && ibIdentifier ) 600 { 601 owner->getBufferBroker()->release( vbIdentifier, ibIdentifier ); 602 vbIdentifier = ibIdentifier = 0; 603 } 604 if ( !vertices ) 605 vertices = new Vertex[8]; 606 if ( !indices ) 607 indices = new unsigned short[8]; 608 } 609 else 610 { 611 if ( !vbIdentifier && !ibIdentifier ) 612 { 613 owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier ); 614 if ( vertices ) 615 delete[] vertices; 616 if ( indices ) 617 delete[] indices; 618 vertices = NULL; indices = NULL; 619 } 620 assert( vbIdentifier ); assert( ibIdentifier ); 621 glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier ); 622 623 // The call to glBufferDataARB with a null argument for data is to make things faster. 624 // Then calling call glMapBuffer() tells the driver that the previous 625 // data aren’t valid. As a consequence, if the GPU is still working on them, there won’t 626 // be a conflict because we invalidated these data. The function glMapBuffer() returns a 627 // new pointer that we can use while the GPU is working on the previous set of data.. 628 629 glBufferDataARB( GL_ARRAY_BUFFER_ARB, Terrain::MAX_VERTICES*sizeof( Vertex ), 630 NULL, GL_DYNAMIC_DRAW_ARB ); 631 632 vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB, 633 GL_WRITE_ONLY_ARB ); 634 635 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier ); 636 637 glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 638 Terrain::MAX_INDICES*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB ); 639 640 indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 641 GL_WRITE_ONLY_ARB ); 642 643 } 613 644 614 645 #endif 615 646 616 assert( indices ); assert( vertices ); 617 if ( _lod == TerrainPage::MAX_LODS-1 ) { 618 tesselateLevelFourPage( adapt ); 619 return; 620 } 621 622 int zStart = 0, zEnd = owner->getPageSize()-stride; 623 624 if ( adapt[TP_BOTTOM] ) { 625 tesselateBottomRow( 0, stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 626 zStart+= stride; 627 } 628 629 if ( adapt[TP_TOP] ) 630 zEnd-= stride; 631 632 for ( int z = zStart; z < zEnd; z+=stride ) 633 tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 634 635 636 if ( adapt[TP_TOP] ) { 637 tesselateTopRow( owner->getPageSize()-stride-1, 638 stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 639 } 647 assert( indices ); assert( vertices ); 648 if ( _lod == TerrainPage::MAX_LODS-1 ) 649 { 650 tesselateLevelFourPage( adapt ); 651 return; 652 } 653 654 int zStart = 0, zEnd = owner->getPageSize()-stride; 655 656 if ( adapt[TP_BOTTOM] ) 657 { 658 tesselateBottomRow( 0, stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 659 zStart+= stride; 660 } 661 662 if ( adapt[TP_TOP] ) 663 zEnd-= stride; 664 665 for ( int z = zStart; z < zEnd; z+=stride ) 666 tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 667 668 669 if ( adapt[TP_TOP] ) 670 { 671 tesselateTopRow( owner->getPageSize()-stride-1, 672 stride, adapt[TP_LEFT], adapt[TP_RIGHT] ); 673 } 640 674 641 675 #ifdef USE_VBO 642 if ( vbIdentifier && ibIdentifier ) { 643 glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ); 644 indices = NULL; 645 glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB ); 646 vertices = NULL; 647 } 676 if ( vbIdentifier && ibIdentifier ) 677 { 678 glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ); 679 indices = NULL; 680 glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB ); 681 vertices = NULL; 682 } 648 683 #endif 649 684 … … 655 690 656 691 #ifdef USE_VBO 657 658 659 660 692 //This is done later on... 693 //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier ); 694 vertices = NULL; 695 indices = NULL; 661 696 #else 662 663 697 vertices = new Vertex[Terrain::MAX_VERTICES]; 698 indices = new unsigned short[Terrain::MAX_INDICES]; 664 699 #endif 665 666 667 668 669 700 vbIdentifier = 0; ibIdentifier = 0; 701 indexHash = new unsigned short[Terrain::MAX_VERTICES]; 702 forceTesselation = true; 703 activate(); 704 active = true; 670 705 } 671 706 … … 673 708 { 674 709 #ifdef USE_VBO 675 710 owner->getBufferBroker()->release( vbIdentifier, ibIdentifier ); 676 711 #endif 677 678 679 680 681 712 SAVE_DELETE_ARRAY( vertices ); 713 numVertices = 0; 714 SAVE_DELETE_ARRAY( indices ); 715 numIndices = 0; 716 deactivate(); 682 717 } 683 718 684 719 void TerrainPage::drawBox() 685 720 { 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 721 glMatrixMode( GL_MODELVIEW ); 722 glPushMatrix(); 723 glTranslatef( bounds.corner.x, bounds.corner.y, bounds.corner.z ); 724 glBegin( GL_QUADS ); 725 glVertex3f( 0.0f, 0.0f, 0.0f ); 726 glVertex3f( bounds.x, 0.0f, 0.0f ); 727 glVertex3f( bounds.x, bounds.y, 0.0f ); 728 glVertex3f( 0.0f, bounds.y, 0.0f ); 729 730 glVertex3f( 0.0f, 0.0f, bounds.z ); 731 glVertex3f( bounds.x, 0.0f, bounds.z ); 732 glVertex3f( bounds.x, bounds.y, bounds.z ); 733 glVertex3f( 0.0f, bounds.y, bounds.z ); 734 735 glVertex3f( 0.0f, 0.0f, 0.0 ); 736 glVertex3f( 0.0, 0.0f, bounds.z ); 737 glVertex3f( 0.0f, bounds.y, bounds.z ); 738 glVertex3f( 0.0f, bounds.y, 0.0f ); 739 740 glVertex3f( bounds.x, 0.0f, 0.0 ); 741 glVertex3f( bounds.x, 0.0f, bounds.z ); 742 glVertex3f( bounds.x, bounds.y, bounds.z ); 743 glVertex3f( bounds.x, bounds.y, 0.0f ); 744 glEnd(); 745 glPopMatrix(); 711 746 } 712 747 //TODO: put all the pages that have a coarses tesselation level than 4 into a … … 714 749 void TerrainPage::draw( ) 715 750 { 716 717 718 719 720 721 722 723 724 751 assert( glIsEnabled( GL_VERTEX_ARRAY ) ); 752 assert( !glIsEnabled( GL_NORMAL_ARRAY ) ); 753 754 if ( currentLOD == TerrainPage::MAX_LODS-1 ) 755 return; 756 757 assert( isVisible ); assert( numIndices > 0 ); 758 active = false; 759 CHECK_GL_ERROR( "1" ); 725 760 #ifdef USE_VBO 726 761 727 728 729 730 731 732 733 734 735 736 737 762 glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier ); 763 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 764 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 765 766 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 767 glInterleavedArrays( GL_T2F_V3F, 0, NULL ); 768 769 glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier ); 770 771 glDrawElements( GL_TRIANGLE_STRIP, numIndices, 772 GL_UNSIGNED_SHORT, NULL ); 738 773 #else 739 740 741 742 743 744 745 746 774 glClientActiveTextureARB( GL_TEXTURE0_ARB ); 775 glInterleavedArrays( GL_T2F_V3F, 0, vertices ); 776 777 glClientActiveTextureARB( GL_TEXTURE1_ARB ); 778 glInterleavedArrays( GL_T2F_V3F, 0, vertices ); 779 780 glDrawElements( GL_TRIANGLE_STRIP, numIndices, 781 GL_UNSIGNED_SHORT, indices ); 747 782 #endif 748 783 749 784 750 785 751 752 753 754 786 if ( owner->debug() ) 787 drawBox( ); 788 789 CHECK_GL_ERROR( "2" ); 755 790 } 756 791 757 792 unsigned short TerrainPage::getIndex( int _x, int _z ) 758 793 { 759 unsigned short index = _z*owner->getPageSize()+_x; 760 if ( indexHash[index] == 0xffff ) { 761 //The vertex didn't exists before, lets create it. 762 indexHash[index] = numVertices; 763 getVertex( _x, _z, vertices[numVertices].p ); 764 getCoord( _x, _z, vertices[numVertices].t ); 765 numVertices++; 766 } 767 return indexHash[index]; 794 unsigned short index = _z*owner->getPageSize()+_x; 795 if ( indexHash[index] == 0xffff ) 796 { 797 //The vertex didn't exists before, lets create it. 798 indexHash[index] = numVertices; 799 getVertex( _x, _z, vertices[numVertices].p ); 800 getCoord( _x, _z, vertices[numVertices].t ); 801 numVertices++; 802 } 803 return indexHash[index]; 768 804 } 769 805 770 806 void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const 771 807 { 772 773 808 owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ), 809 _z+zOffset*(owner->getPageSize()-1 ), _coord ); 774 810 } 775 811 776 812 void TerrainPage::getVertex( int _x, int _z, Vector& _vertex ) const 777 813 { 778 779 780 781 814 _vertex.x = position.x+scale.x*_x/ 815 ( owner->getPageSize()-1 ); 816 _vertex.y = getAltitude( _x, _z ); 817 _vertex.z = position.z+scale.z*_z/( owner->getPageSize()-1 ); 782 818 } 783 819 void TerrainPage::setLayerVisibility( int _layer, LayerVisibility _lv ) 784 820 { 785 if ( hasfull ) return; 786 if ( _lv == LV_FULL ) { 787 for ( int i = 0; i < 8; ++i ) 788 layerVisibility[i] = LV_NO; 789 if ( _layer ) 790 hasfull = true; 791 } 792 layerVisibility[_layer] = _lv; 821 if ( hasfull ) return; 822 if ( _lv == LV_FULL ) 823 { 824 for ( int i = 0; i < 8; ++i ) 825 layerVisibility[i] = LV_NO; 826 if ( _layer ) 827 hasfull = true; 828 } 829 layerVisibility[_layer] = _lv; 793 830 } 794 831 795 832 bool TerrainPage::hasMaterial( int _layer ) 796 833 { 797 834 return ( layerVisibility[_layer] != LV_NO ); 798 835 } 799 836 void TerrainPage::calculateErrors() 800 837 { 801 802 803 } 838 for ( int i = 0; i < TerrainPage::MAX_LODS; ++i ) 839 calculateError( i ); 840 } -
branches/terrain/src/lib/graphics/importer/terrain/terrain_page.h
r9418 r9428 26 26 typedef TerrainPage *pTerrainPage; 27 27 28 struct Vertex { 29 TexCoord t; 30 Vector p; 28 struct Vertex 29 { 30 TexCoord t; 31 Vector p; 31 32 }; 32 33 33 34 typedef Vertex *pVertex; 34 35 35 typedef struct { 36 Vector correct; 37 Vector real; 38 float diff; 39 } LODError, *pLODError; 40 41 class TerrainPage : public TerrainQuad { 42 public: 43 enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 }; 44 const static int MAX_LODS = 5; 45 46 /** 47 * Creates a new terrain page with its lower left corner set 48 * to C = ( _xOffset, _zOffset ), where the two values specify 49 * the offset in the height-map. 50 * The size of the page, as well as the scaling factors are read 51 * from the _owner terrain page. 52 */ 53 TerrainPage( Terrain *_owner, int _xOffset, int _zOffset ); 54 55 /** 56 * This is used only internally for communication between the TerrainPage and 57 * the Terrain class itself. 58 */ 59 inline bool isActive() { return active; } 60 61 virtual ~TerrainPage(); 62 /** 63 * @brief Makes the terrain look as if it were created with the given level of 64 * detail. 65 */ 66 void mimick( int _level ) {} 67 68 /** 69 * @brief Draws a box around the TerrainPage. For debugging purposes. 70 */ 71 void drawBox(); 72 73 /** 74 * @brief Calculates the smallest fitting axis aligned bounding box for this TerrainPage. 75 */ 76 virtual void calculateBounds(); 77 78 79 /** 80 * @brief Sets the visibility to _flag. If the visibility changed, the vertex and 81 * index arrays are allocated or freed, respectively. 82 */ 83 inline void setVisibility( bool _flag ); 84 85 /** 86 * @brief Prepares the page for rendering. 87 */ 88 void show( ); 89 90 /** 91 * @brief Frees most of the memory for economomical reasons. 92 */ 93 void hide( ); 94 95 /** 96 * @brief Updates the tesselation if necessary. 97 */ 98 void updateTesselation( ); 99 100 /** 101 * @return The current tesselation level. 102 */ 103 int getLOD() { return currentLOD; } 104 105 /** 106 * @return The curren tween factor. This is a floating point value between 0.0f 107 * and 1.0f 108 */ 109 float getTween() { return 0.0f; } 110 111 /** 112 * @brief Determines the new LOD which should be used by this terrain page based on 113 * the distance from the camera. 114 * 115 * No geometry is updated in this method. You need to call 116 * updateTesselation() in order to see a change in geometry. This method is 117 * just a recommondation for the LOD. It might be invalid due to outer 118 * constraints. 119 */ 120 int chooseLOD(); 121 122 /** 123 * If the terrain pages tesselation level changed between the last and the 124 * current frame, this function returns true, else you'll get false as the 125 * return value. 126 * @return True if the page needs an update and false if not. 127 */ 128 bool isDirty() { return forceTesselation; } 129 130 /** 131 * @brief Calculates the maximal errors for every LOD. 132 */ 133 void calculateErrors(); 134 135 /** 136 * @brief Calculates the error for the given LOD. We just need to know the "worst" 137 * vertex for choosing an appropriate LOD. 138 */ 139 void calculateError( int _lod ); 140 141 142 /** 143 * Tests if the terrain page would cull against the viewing frustum. 144 */ 145 bool cull( ); 146 147 bool needsRetesselation(); 148 /** 149 * Sets the neighbors of this terrain page. pass null if a neighbor if this 150 * pages is at the border. 151 */ 152 inline void setNeighbors( pTerrainPage _left, pTerrainPage _right, 153 pTerrainPage _top, pTerrainPage _bottom ) 154 { 155 left = _left; right = _right; top = _top; bottom = _bottom; 156 } 157 158 /** 159 * Sets the position of the TerrainPage. Is this needed? 160 */ 161 inline void setPosition( const Vector& _pos ) 162 { 163 position.x = _pos.x; 164 position.y = _pos.y; 165 position.z = _pos.z; 166 } 167 168 pTerrainPage getLeft() { return left; } 169 pTerrainPage getRight() { return right; } 170 pTerrainPage getBottom() { return bottom; } 171 pTerrainPage getTop() { return top; } 172 173 /** 174 * Does what exactly what the name says and nothing more. 175 */ 176 void draw( ); 177 178 /** 179 * @return the next active page 180 */ 181 inline pTerrainPage getNext() { return next; } 182 void setLayerVisibility( int _layer, LayerVisibility _lv ); 183 bool hasMaterial( int _layer ); 184 /** 185 * Returns the previous active page 186 */ 187 inline pTerrainPage getPrevious() { return previous; } 188 inline int getCurrentLOD() { return currentLOD; } 189 /** 190 * @return Returns the wanted LOD. Make sure you call this method after a call to 191 * chooseLOD() or you will get screwed values. 192 */ 193 inline int getWantedLOD() { return wantedLOD; } 194 195 /** 196 * @brief Removes the page from the active page list. 197 */ 198 void deactivate(); 199 200 /** 201 * @brief Inserts the page into the active page list. 202 */ 203 void activate(); 204 205 inline void setWantedLOD( int _lod ) 206 { 207 if ( _lod >= TerrainPage::MAX_LODS ) 208 wantedLOD = TerrainPage::MAX_LODS-1; 209 else if ( _lod < 0 ) 210 wantedLOD = 0; 211 else 212 wantedLOD = _lod; 213 } 214 215 protected: 216 217 /** 218 * @brief Tesselates one row of the terrain page. 219 * @param _z The z-offset of the row 220 * @param _xStride Defines the step-size horizontally 221 * @param _zStride Defines the step-size vertically. 222 * @param _adaptLeft True if the left neighbor has a coarser 223 * tesselation level. 224 * @param _adaptRight True if the right neighbor has a coarser 225 * tesselation level. 226 */ 227 void tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight ); 228 void tesselateTopRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); 229 void tesselateBottomRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); 230 /** 231 * @brief Returns four boolean values in the oder 232 */ 233 void determineBorderAdaption( bool _adapt[] ); 234 235 /** 236 * @brief Adds the given index to the index-array 237 */ 238 inline void addIndex( unsigned short _index ); 239 240 /** 241 * @brief We programmers are very lazy :) This method just adds the last added index 242 * again. 243 */ 244 inline void addAgain(); 245 246 247 void getCoord( int _x, int _z, TexCoord& _coord) const; 248 249 /** 250 * Fills _vertex with the vertex information at index. 251 */ 252 void getVertex( int _x, int _z, Vector& _vertex ) const; 253 254 /** 255 * Use this method to safely get a vertex at location ( _x, _z ). If it wasn't 256 * created before, this method does that for you. 257 */ 258 unsigned short getIndex( int _x, int _z ); 259 void tesselateLevelFourPage( bool _adapt[] ); 260 /** 261 * Generates the tesselation for the given level of detail. 262 */ 263 void tesselate( int _lod ); 264 265 float getAltitude( int _x, int _z ) const; 266 267 int currentLOD, 268 wantedLOD; 269 pTerrainPage left, 270 right, 271 top, 272 bottom; 273 bool forceTesselation; 274 bool active; 275 pVertex vertices; 276 unsigned short *indices; 277 unsigned short *indexHash; 278 int numIndices; 279 int numVertices; 280 LayerVisibility layerVisibility[8]; 281 bool hasfull; 36 typedef struct 37 { 38 Vector correct; 39 Vector real; 40 float diff; 41 } 42 LODError, *pLODError; 43 44 class TerrainPage : public TerrainQuad 45 { 46 public: 47 enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 }; 48 const static int MAX_LODS = 5; 49 50 /** 51 * Creates a new terrain page with its lower left corner set 52 * to C = ( _xOffset, _zOffset ), where the two values specify 53 * the offset in the height-map. 54 * The size of the page, as well as the scaling factors are read 55 * from the _owner terrain page. 56 */ 57 TerrainPage( Terrain *_owner, int _xOffset, int _zOffset ); 58 59 /** 60 * This is used only internally for communication between the TerrainPage and 61 * the Terrain class itself. 62 */ 63 inline bool isActive() { return active; } 64 65 virtual ~TerrainPage(); 66 /** 67 * @brief Makes the terrain look as if it were created with the given level of 68 * detail. 69 */ 70 void mimick( int _level ) {} 71 72 /** 73 * @brief Draws a box around the TerrainPage. For debugging purposes. 74 */ 75 void drawBox(); 76 77 /** 78 * @brief Calculates the smallest fitting axis aligned bounding box for this TerrainPage. 79 */ 80 virtual void calculateBounds(); 81 82 83 /** 84 * @brief Sets the visibility to _flag. If the visibility changed, the vertex and 85 * index arrays are allocated or freed, respectively. 86 */ 87 inline void setVisibility( bool _flag ); 88 89 /** 90 * @brief Prepares the page for rendering. 91 */ 92 void show( ); 93 94 /** 95 * @brief Frees most of the memory for economomical reasons. 96 */ 97 void hide( ); 98 99 /** 100 * @brief Updates the tesselation if necessary. 101 */ 102 void updateTesselation( ); 103 104 /** 105 * @return The current tesselation level. 106 */ 107 int getLOD() { return currentLOD; } 108 109 /** 110 * @return The curren tween factor. This is a floating point value between 0.0f 111 * and 1.0f 112 */ 113 float getTween() { return 0.0f; } 114 115 /** 116 * @brief Determines the new LOD which should be used by this terrain page based on 117 * the distance from the camera. 118 * 119 * No geometry is updated in this method. You need to call 120 * updateTesselation() in order to see a change in geometry. This method is 121 * just a recommondation for the LOD. It might be invalid due to outer 122 * constraints. 123 */ 124 int chooseLOD(); 125 126 /** 127 * If the terrain pages tesselation level changed between the last and the 128 * current frame, this function returns true, else you'll get false as the 129 * return value. 130 * @return True if the page needs an update and false if not. 131 */ 132 bool isDirty() { return forceTesselation; } 133 134 /** 135 * @brief Calculates the maximal errors for every LOD. 136 */ 137 void calculateErrors(); 138 139 /** 140 * @brief Calculates the error for the given LOD. We just need to know the "worst" 141 * vertex for choosing an appropriate LOD. 142 */ 143 void calculateError( int _lod ); 144 145 146 /** 147 * Tests if the terrain page would cull against the viewing frustum. 148 */ 149 bool cull( ); 150 151 bool needsRetesselation(); 152 /** 153 * Sets the neighbors of this terrain page. pass null if a neighbor if this 154 * pages is at the border. 155 */ 156 inline void setNeighbors( pTerrainPage _left, pTerrainPage _right, 157 pTerrainPage _top, pTerrainPage _bottom ) 158 { 159 left = _left; right = _right; top = _top; bottom = _bottom; 160 } 161 162 /** 163 * Sets the position of the TerrainPage. Is this needed? 164 */ 165 inline void setPosition( const Vector& _pos ) 166 { 167 position.x = _pos.x; 168 position.y = _pos.y; 169 position.z = _pos.z; 170 } 171 172 pTerrainPage getLeft() { return left; } 173 pTerrainPage getRight() { return right; } 174 pTerrainPage getBottom() { return bottom; } 175 pTerrainPage getTop() { return top; } 176 177 /** 178 * Does what exactly what the name says and nothing more. 179 */ 180 void draw( ); 181 182 /** 183 * @return the next active page 184 */ 185 inline pTerrainPage getNext() { return next; } 186 void setLayerVisibility( int _layer, LayerVisibility _lv ); 187 bool hasMaterial( int _layer ); 188 /** 189 * Returns the previous active page 190 */ 191 inline pTerrainPage getPrevious() { return previous; } 192 inline int getCurrentLOD() { return currentLOD; } 193 /** 194 * @return Returns the wanted LOD. Make sure you call this method after a call to 195 * chooseLOD() or you will get screwed values. 196 */ 197 inline int getWantedLOD() { return wantedLOD; } 198 199 /** 200 * @brief Removes the page from the active page list. 201 */ 202 void deactivate(); 203 204 /** 205 * @brief Inserts the page into the active page list. 206 */ 207 void activate(); 208 209 inline void setWantedLOD( int _lod ) 210 { 211 if ( _lod >= TerrainPage::MAX_LODS ) 212 wantedLOD = TerrainPage::MAX_LODS-1; 213 else if ( _lod < 0 ) 214 wantedLOD = 0; 215 else 216 wantedLOD = _lod; 217 } 218 219 protected: 220 221 /** 222 * @brief Tesselates one row of the terrain page. 223 * @param _z The z-offset of the row 224 * @param _xStride Defines the step-size horizontally 225 * @param _zStride Defines the step-size vertically. 226 * @param _adaptLeft True if the left neighbor has a coarser 227 * tesselation level. 228 * @param _adaptRight True if the right neighbor has a coarser 229 * tesselation level. 230 */ 231 void tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight ); 232 void tesselateTopRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); 233 void tesselateBottomRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); 234 /** 235 * @brief Returns four boolean values in the oder 236 */ 237 void determineBorderAdaption( bool _adapt[] ); 238 239 /** 240 * @brief Adds the given index to the index-array 241 */ 242 inline void addIndex( unsigned short _index ); 243 244 /** 245 * @brief We programmers are very lazy :) This method just adds the last added index 246 * again. 247 */ 248 inline void addAgain(); 249 250 251 void getCoord( int _x, int _z, TexCoord& _coord) const; 252 253 /** 254 * Fills _vertex with the vertex information at index. 255 */ 256 void getVertex( int _x, int _z, Vector& _vertex ) const; 257 258 /** 259 * Use this method to safely get a vertex at location ( _x, _z ). If it wasn't 260 * created before, this method does that for you. 261 */ 262 unsigned short getIndex( int _x, int _z ); 263 void tesselateLevelFourPage( bool _adapt[] ); 264 /** 265 * Generates the tesselation for the given level of detail. 266 */ 267 void tesselate( int _lod ); 268 269 float getAltitude( int _x, int _z ) const; 270 271 int currentLOD, 272 wantedLOD; 273 pTerrainPage left, 274 right, 275 top, 276 bottom; 277 bool forceTesselation; 278 bool active; 279 pVertex vertices; 280 unsigned short *indices; 281 unsigned short *indexHash; 282 int numIndices; 283 int numVertices; 284 LayerVisibility layerVisibility[8]; 285 bool hasfull; 282 286 #ifdef USE_VBO 283 284 287 GLuint ibIdentifier, 288 vbIdentifier; 285 289 #endif 286 287 288 289 290 290 bool isVisible; 291 pTerrainPage next; 292 pTerrainPage previous; 293 LODError *errors; 294 Vector position; 291 295 }; 292 296 293 297 inline void TerrainPage::setVisibility( bool _flag ) 294 298 { 295 if ( _flag ) { 296 if ( !isVisible ) { 297 isVisible = true; 298 show( ); 299 } 300 active = true; 301 } 302 else { 303 if ( isVisible ) { 304 isVisible = false; 305 hide( ); 306 } 307 } 299 if ( _flag ) 300 { 301 if ( !isVisible ) 302 { 303 isVisible = true; 304 show( ); 305 } 306 active = true; 307 } 308 else 309 { 310 if ( isVisible ) 311 { 312 isVisible = false; 313 hide( ); 314 } 315 } 308 316 } 309 317 310 318 inline void TerrainPage::addIndex( unsigned short _index ) 311 319 { 312 320 indices[numIndices] = _index; numIndices++; 313 321 } 314 322 315 323 inline void TerrainPage::addAgain() 316 324 { 317 325 indices[numIndices] = indices[numIndices-1]; numIndices++; 318 326 } 319 327
Note: See TracChangeset
for help on using the changeset viewer.