Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 9428 in orxonox.OLD for branches/terrain/src/lib/graphics


Ignore:
Timestamp:
Jul 24, 2006, 3:03:32 PM (18 years ago)
Author:
bensch
Message:

minor change

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  
    2626void Terrain::build()
    2727{
    28 
    29   printf("SHOULD GET LOADED :)\n");
    30 
    3128  ResourceManager *MANAGER = ResourceManager::getInstance();
    3229  std::string full = MANAGER->getFullName( heightmapSource );
  • branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc

    r9415 r9428  
    2929TerrainPage::~TerrainPage( )
    3030{
    31         SAVE_DELETE_ARRAY( indices );
    32         SAVE_DELETE_ARRAY( vertices );
    33         SAVE_DELETE_ARRAY( indexHash );
    34         SAVE_DELETE_ARRAY( errors );
     31  SAVE_DELETE_ARRAY( indices );
     32  SAVE_DELETE_ARRAY( vertices );
     33  SAVE_DELETE_ARRAY( indexHash );
     34  SAVE_DELETE_ARRAY( errors );
    3535}
    3636
    3737TerrainPage::TerrainPage( Terrain *_owner, int _xOffset, int _zOffset )
    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;
     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;
    5858}
    5959
    6060void 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  }
    101105}
    102106
     
    105109void TerrainPage::determineBorderAdaption( bool _adapt[] )
    106110{
    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  }
    126134}
    127135
    128136int TerrainPage::chooseLOD()
    129137{
    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;
    151162}
    152163
     
    154165{
    155166
    156         pTerrainPage list = owner->getActiveList();
    157         next = list;
    158         if ( list )
    159                 list->previous = this;
    160         owner->setActiveList( this );
     167  pTerrainPage list = owner->getActiveList();
     168  next = list;
     169  if ( list )
     170    list->previous = this;
     171  owner->setActiveList( this );
    161172}
    162173
    163174void TerrainPage::deactivate()
    164175{
    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;
    177190
    178191}
     
    180193void TerrainPage::calculateError( int _lod )
    181194{
    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  }
    225241}
    226242
    227243void TerrainPage::calculateBounds()
    228244{
    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 );
    244262}
    245263
    246264float TerrainPage::getAltitude( int _x, int _z ) const
    247265{
    248         assert( _x >= 0 && _x < 17 );
    249         assert( _z >= 0 && _z < 17 );
    250         return position.y+scale.y*owner->getAltitude(
    251                         _x+(owner->getPageSize()-1)*xOffset,
    252                         _z+(owner->getPageSize()-1)*zOffset );
     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 );
    253271}
    254272
     
    256274{
    257275
    258         bool    leftChanged     = ( left && left->isActive() ) &&
    259                                 ( left->wantedLOD != left->currentLOD ),
    260                         rightChanged    = ( right && right->isActive() ) &&
    261                                 ( right->wantedLOD != right->currentLOD ),
    262                         topChanged              = ( top && top->isActive() ) &&
    263                                 ( top->wantedLOD != currentLOD ),
    264                         bottomChanged   = ( bottom && bottom->isActive() ) &&
    265                                 ( bottom->wantedLOD != bottom->currentLOD ),
    266                         iChanged                =  wantedLOD != currentLOD;
    267 
    268         return ( leftChanged || rightChanged || topChanged || bottomChanged ||
    269                 forceTesselation || iChanged );
     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 );
    270288}
    271289
    272290void TerrainPage::updateTesselation( )
    273291{
    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;
    287307}
    288308
    289309void 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  }
    331354
    332355}
    333356void 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  }
    375401}
    376402
    377403void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
    378404{
    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 );
    552579}
    553580
     
    556583{
    557584
    558         memset( indexHash, 0xffff,
    559                         sizeof(unsigned short)*Terrain::MAX_VERTICES );
    560 
    561         numVertices = 0; numIndices = 0;
    562 
    563         //Calculate the pace, based on the lod.
    564         int stride = 1 << _lod;
    565 
    566         bool adapt[4];
    567         determineBorderAdaption( adapt );
    568         assert( isVisible );
     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 );
    569596#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  }
    613644
    614645#endif
    615646
    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  }
    640674
    641675#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  }
    648683#endif
    649684
     
    655690
    656691#ifdef USE_VBO
    657         //This is done later on...
    658         //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
    659         vertices = NULL;
    660         indices = NULL;
     692  //This is done later on...
     693  //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
     694  vertices = NULL;
     695  indices = NULL;
    661696#else
    662         vertices = new Vertex[Terrain::MAX_VERTICES];
    663         indices = new unsigned short[Terrain::MAX_INDICES];
     697  vertices = new Vertex[Terrain::MAX_VERTICES];
     698  indices = new unsigned short[Terrain::MAX_INDICES];
    664699#endif
    665         vbIdentifier = 0; ibIdentifier = 0;
    666         indexHash = new unsigned short[Terrain::MAX_VERTICES];
    667         forceTesselation = true;
    668         activate();
    669         active = true;
     700  vbIdentifier = 0; ibIdentifier = 0;
     701  indexHash = new unsigned short[Terrain::MAX_VERTICES];
     702  forceTesselation = true;
     703  activate();
     704  active = true;
    670705}
    671706
     
    673708{
    674709#ifdef USE_VBO
    675         owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
     710  owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
    676711#endif
    677         SAVE_DELETE_ARRAY( vertices );
    678         numVertices = 0;
    679         SAVE_DELETE_ARRAY( indices );
    680         numIndices = 0;
    681         deactivate();
     712  SAVE_DELETE_ARRAY( vertices );
     713  numVertices = 0;
     714  SAVE_DELETE_ARRAY( indices );
     715  numIndices = 0;
     716  deactivate();
    682717}
    683718
    684719void TerrainPage::drawBox()
    685720{
    686         glMatrixMode( GL_MODELVIEW );
    687         glPushMatrix();
    688         glTranslatef( bounds.corner.x, bounds.corner.y, bounds.corner.z );
    689         glBegin( GL_QUADS );
    690                 glVertex3f( 0.0f, 0.0f, 0.0f );
    691                 glVertex3f(  bounds.x, 0.0f, 0.0f );
    692                 glVertex3f( bounds.x, bounds.y, 0.0f );
    693                 glVertex3f( 0.0f, bounds.y, 0.0f );
    694 
    695                 glVertex3f( 0.0f, 0.0f, bounds.z );
    696                 glVertex3f(  bounds.x, 0.0f, bounds.z );
    697                 glVertex3f( bounds.x, bounds.y, bounds.z );
    698                 glVertex3f( 0.0f, bounds.y, bounds.z );
    699 
    700                 glVertex3f( 0.0f, 0.0f, 0.0 );
    701                 glVertex3f(  0.0, 0.0f, bounds.z );
    702                 glVertex3f( 0.0f, bounds.y, bounds.z );
    703                 glVertex3f( 0.0f, bounds.y, 0.0f );
    704 
    705                 glVertex3f( bounds.x, 0.0f, 0.0 );
    706                 glVertex3f(  bounds.x, 0.0f, bounds.z );
    707                 glVertex3f( bounds.x, bounds.y, bounds.z );
    708                 glVertex3f( bounds.x, bounds.y, 0.0f );
    709         glEnd();
    710         glPopMatrix();
     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();
    711746}
    712747//TODO: put all the pages that have a coarses tesselation level than 4 into a
     
    714749void TerrainPage::draw( )
    715750{
    716         assert( glIsEnabled( GL_VERTEX_ARRAY ) );
    717         assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
    718 
    719         if ( currentLOD == TerrainPage::MAX_LODS-1 )
    720                 return;
    721 
    722         assert( isVisible ); assert( numIndices > 0 );
    723         active = false;
    724         CHECK_GL_ERROR( "1" );
     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" );
    725760#ifdef USE_VBO
    726761
    727         glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
    728         glClientActiveTextureARB( GL_TEXTURE0_ARB );
    729         glInterleavedArrays( GL_T2F_V3F, 0, NULL );
    730 
    731         glClientActiveTextureARB( GL_TEXTURE1_ARB );
    732         glInterleavedArrays( GL_T2F_V3F, 0, NULL );
    733 
    734         glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
    735 
    736         glDrawElements( GL_TRIANGLE_STRIP, numIndices,
    737                                         GL_UNSIGNED_SHORT, NULL );
     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 );
    738773#else
    739         glClientActiveTextureARB( GL_TEXTURE0_ARB );
    740         glInterleavedArrays( GL_T2F_V3F, 0, vertices );
    741 
    742         glClientActiveTextureARB( GL_TEXTURE1_ARB );
    743         glInterleavedArrays( GL_T2F_V3F, 0, vertices );
    744 
    745         glDrawElements( GL_TRIANGLE_STRIP, numIndices,
    746                                         GL_UNSIGNED_SHORT, indices );
     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 );
    747782#endif
    748783
    749784
    750785
    751         if ( owner->debug() )
    752                 drawBox( );
    753 
    754         CHECK_GL_ERROR( "2" );
     786  if ( owner->debug() )
     787    drawBox( );
     788
     789  CHECK_GL_ERROR( "2" );
    755790}
    756791
    757792unsigned short TerrainPage::getIndex( int _x, int _z )
    758793{
    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];
    768804}
    769805
    770806void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const
    771807{
    772         owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ),
    773                                         _z+zOffset*(owner->getPageSize()-1 ), _coord );
     808  owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ),
     809                  _z+zOffset*(owner->getPageSize()-1 ), _coord );
    774810}
    775811
    776812void TerrainPage::getVertex( int _x, int _z, Vector& _vertex ) const
    777813{
    778         _vertex.x = position.x+scale.x*_x/
    779                 ( owner->getPageSize()-1 );
    780         _vertex.y = getAltitude( _x, _z );
    781         _vertex.z = position.z+scale.z*_z/( owner->getPageSize()-1 );
     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 );
    782818}
    783819void TerrainPage::setLayerVisibility( int _layer, LayerVisibility _lv )
    784820{
    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;
    793830}
    794831
    795832bool TerrainPage::hasMaterial( int _layer )
    796833{
    797         return ( layerVisibility[_layer] != LV_NO );
     834  return ( layerVisibility[_layer] != LV_NO );
    798835}
    799836void TerrainPage::calculateErrors()
    800837{
    801         for ( int i = 0; i < TerrainPage::MAX_LODS; ++i )
    802                 calculateError( i );
    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  
    2626typedef TerrainPage *pTerrainPage;
    2727
    28 struct Vertex {
    29         TexCoord        t;
    30         Vector          p;
     28struct Vertex
     29{
     30  TexCoord      t;
     31  Vector                p;
    3132};
    3233
    3334typedef Vertex *pVertex;
    3435
    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;
     36typedef struct
     37{
     38  Vector        correct;
     39  Vector        real;
     40  float diff;
     41}
     42LODError, *pLODError;
     43
     44class 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;
    282286#ifdef  USE_VBO
    283                 GLuint                                          ibIdentifier,
    284                                                                         vbIdentifier;
     287    GLuint                                              ibIdentifier,
     288    vbIdentifier;
    285289#endif
    286                 bool                                            isVisible;
    287                 pTerrainPage                            next;
    288                 pTerrainPage                            previous;
    289                 LODError                                        *errors;
    290                 Vector                                          position;
     290    bool                                                isVisible;
     291    pTerrainPage                                next;
     292    pTerrainPage                                previous;
     293    LODError                                    *errors;
     294    Vector                                              position;
    291295};
    292296
    293297inline void TerrainPage::setVisibility( bool _flag )
    294298{
    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  }
    308316}
    309317
    310318inline void TerrainPage::addIndex( unsigned short _index )
    311319{
    312         indices[numIndices] = _index; numIndices++;
     320  indices[numIndices] = _index; numIndices++;
    313321}
    314322
    315323inline void TerrainPage::addAgain()
    316324{
    317         indices[numIndices] = indices[numIndices-1]; numIndices++;
     325  indices[numIndices] = indices[numIndices-1]; numIndices++;
    318326}
    319327
Note: See TracChangeset for help on using the changeset viewer.