Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain/src/lib/graphics/importer/terrain/terrain_page.cc @ 9415

Last change on this file since 9415 was 9415, checked in by bensch, 18 years ago

some newlines

File size: 21.0 KB
RevLine 
[8319]1/*
2        orxonox - the future of 3D-vertical-scrollers
[9415]3
[8319]4        Copyright (C) 2006 orx
[9415]5
[8319]6        This program is free software; you can redistribute it and/or modify
7        it under the terms of the GNU General Public License as published by
8        the Free Software Foundation; either version 2, or (at your option)
9        any later version.
[9415]10
[8319]11        ### File Specific:
[8328]12        main-programmer: Marco Biasini
[9415]13
[8319]14 */
15#include "terrain_page.h"
16#include "terrain.h"
17#include "glincl.h"
18#include <stdio.h>
19#include <math.h>
[8569]20#define USE_VBO
[8319]21
[8328]22#define CHECK_GL_ERROR( _d ) do { \
[8319]23        GLenum __err = glGetError(); \
24        if ( __err != GL_NO_ERROR ) \
[8328]25                printf( "check%s: %s\n", _d, (char*)gluErrorString( __err ) );\
[8319]26        }\
27        while ( 0 )
[9415]28
[8775]29TerrainPage::~TerrainPage( )
[9415]30{
[8775]31        SAVE_DELETE_ARRAY( indices );
32        SAVE_DELETE_ARRAY( vertices );
[9415]33        SAVE_DELETE_ARRAY( indexHash );
34        SAVE_DELETE_ARRAY( errors );
[8775]35}
[8319]36
37TerrainPage::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];
[9415]43        vertices = NULL; indices = NULL;
[8770]44        left = top = bottom = right = NULL;
45        for ( int i = 0; i < 8; ++i )
[9415]46                layerVisibility[i] = LV_NO;
47
48        position = Vector( scale.x*_xOffset,
[8770]49                0.0f, scale.z*_zOffset );
[8319]50        isVisible = false;
51        next = NULL;
52        active = false;
[9415]53        previous = NULL;
[8770]54        currentLOD = -1; wantedLOD = -1;
[8745]55        hasfull = false;
[8319]56        forceTesselation = true;
[8641]57        vbIdentifier = 0; ibIdentifier = 0;
[8319]58}
59
[9415]60void TerrainPage::tesselateRow( int _z, int _xStride, int _zStride,
[8741]61        bool _adaptLeft, bool _adaptRight )
[8349]62{
[9415]63
64        int xStart = 0, xEnd = owner->getPageSize();
[8349]65        int halfStride = _zStride >> 1;
[8593]66        assert( _xStride > 0 );         assert( _zStride > 0 );
[8349]67        if ( _z ) {
[8741]68                addAgain();
[8349]69                addIndex( getIndex( 0, _z ) );
70        }
71        if ( _adaptLeft ) {
[9415]72                assert( halfStride > 0 );
[8349]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        }
[9415]81
[8349]82        if ( _adaptRight )
83                xEnd-=_xStride;
[9415]84
[8349]85        for ( int x = xStart; x < xEnd; x+=_xStride ) {
86                addIndex( getIndex( x, _z) );
87                addIndex( getIndex( x, _z+_zStride ) );
88        }
[9415]89
[8349]90        int w = owner->getPageSize()-1;
[9415]91
[8349]92        if ( _adaptRight ) {
[9415]93                assert( halfStride > 0 );
[8741]94                addIndex( getIndex( xEnd-1, _z ) );
[8349]95                addAgain();
96                addIndex( getIndex( w, _z ) );
[8741]97                addIndex( getIndex( xEnd-1, _z+_zStride ) );
[8349]98                addIndex( getIndex( w, _z+halfStride ) );
99                addIndex( getIndex( w, _z+_zStride ) );
100        }
101}
102
103//TODO: Perform benchmark to measure if the isVisible test should be included
104//in this method.
105void TerrainPage::determineBorderAdaption( bool _adapt[] )
106{
107        _adapt[0] = _adapt[1] = _adapt[2] = _adapt[3] = false;
[9415]108
[8741]109        if ( left  && left->isActive() ) {
[8349]110                _adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0;
[9415]111                assert( std::abs( wantedLOD - left->wantedLOD ) < 2 );
112        }
[8741]113        if ( right && right->isActive() ) {
[8349]114                _adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0;
[9415]115                assert( std::abs( wantedLOD - right->wantedLOD ) < 2 );
116        }
117
[8741]118        if ( top && top->isActive() ) {
[9415]119                _adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0;
120                assert( std::abs( wantedLOD - top->wantedLOD ) < 2 );
121        }
[8741]122        if ( bottom && bottom->isActive() ) {
[9415]123                _adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0;
[8741]124                assert( std::abs( wantedLOD - bottom->wantedLOD ) < 2 );
[9415]125        }
[8349]126}
127
[8319]128int TerrainPage::chooseLOD()
129{
130        wantedLOD = -1;
[9147]131        Vector cam( owner->getCameraPosition() );
[9415]132
[8319]133        for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) {
[9147]134                Vector distance( cam.x-errors[i].correct.x,
[8319]135                                                 cam.y-errors[i].correct.y,
136                                                 cam.z-errors[i].correct.z );
[9415]137
[9147]138                float d = distance.len();
[9415]139
[8319]140                float err =  errors[i].diff / d ;
[9415]141
[8319]142                if ( err*scale.y < owner->getDetail() ) {
143                        wantedLOD = i;
144                        break;
[9415]145                }
[8319]146        }
147        if ( wantedLOD < 0 ) {
148                wantedLOD = TerrainPage::MAX_LODS-1;
[9415]149        }
[8319]150        return wantedLOD;
151}
152
153void TerrainPage::activate()
154{
[9415]155
[8319]156        pTerrainPage list = owner->getActiveList();
157        next = list;
158        if ( list )
159                list->previous = this;
160        owner->setActiveList( this );
161}
162
163void TerrainPage::deactivate()
164{
165        pTerrainPage list = owner->getActiveList();
[9415]166
[8319]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;
[9415]177
[8319]178}
179
180void TerrainPage::calculateError( int _lod )
181{
182        float   sumError = 0.0f;
183        int             numErrors = 0;
184        int size = owner->getPageSize();
185        if( _lod!=0 )
186        {
[8349]187                int stride = 1 << _lod, x0, y0, xi, yi;
[9415]188                // Altough these four nested loops look very scary, they're not
189                // that bad and require only about O(n^2).
[8349]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++ )
[8319]194                                        {
195                                                int     x = x0+xi,
196                                                y = y0+yi;
[8349]197                                                float   fx0 = ( float )xi/( float )stride, fx1 = 1.0f-fx0,
198                                                                fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0;
[9415]199
[8319]200                                                float   height00 = getAltitude( x0, y0 ),
[8349]201                                                                height10 = getAltitude( x0+stride,y0 ),
202                                                                height01 = getAltitude( x0,y0+stride ),
203                                                                height11 = getAltitude( x0+stride, y0+stride );
[9415]204
[8319]205                                                float   paintHeight =   fx1*fy1 * height00 +
206                                                        fx0*fy1 * height10 +
207                                                        fx1*fy0 * height01 +
208                                                        fx0*fy0 * height11,
209                                                        correctHeight =  getAltitude( x, y );
[9415]210
[8319]211                                                float   er = ( float )fabs( correctHeight - paintHeight );
[9415]212
[8319]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        }
225}
226
227void TerrainPage::calculateBounds()
228{
229        int size = owner->getPageSize();
230        float alt = 0.0f;
[9415]231
232        Vector  min( xOffset*scale.x ,0.0f, zOffset*scale.z ),
[8319]233                        max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z);
[9415]234
[8319]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 );
[9071]239                        min.y = fmin( min.y, alt-1.0f );
240                        max.y = fmax( max.y, alt+1.0f );
[8319]241                }
242        }
243        bounds.set( min, max );
244}
245
246float TerrainPage::getAltitude( int _x, int _z ) const
247{
248        assert( _x >= 0 && _x < 17 );
249        assert( _z >= 0 && _z < 17 );
[9415]250        return position.y+scale.y*owner->getAltitude(
251                        _x+(owner->getPageSize()-1)*xOffset,
[8319]252                        _z+(owner->getPageSize()-1)*zOffset );
253}
254
[8349]255bool TerrainPage::needsRetesselation()
256{
[9415]257
[8648]258        bool    leftChanged     = ( left && left->isActive() ) &&
259                                ( left->wantedLOD != left->currentLOD ),
[9415]260                        rightChanged    = ( right && right->isActive() ) &&
[8648]261                                ( right->wantedLOD != right->currentLOD ),
[9415]262                        topChanged              = ( top && top->isActive() ) &&
[8648]263                                ( top->wantedLOD != currentLOD ),
[9415]264                        bottomChanged   = ( bottom && bottom->isActive() ) &&
[8648]265                                ( bottom->wantedLOD != bottom->currentLOD ),
[8349]266                        iChanged                =  wantedLOD != currentLOD;
[9415]267
268        return ( leftChanged || rightChanged || topChanged || bottomChanged ||
[8741]269                forceTesselation || iChanged );
[8349]270}
271
[8319]272void TerrainPage::updateTesselation( )
273{
[9071]274        assert( wantedLOD < 5 && wantedLOD >= 0 );
[8349]275        if ( needsRetesselation() ) {
276                tesselate( wantedLOD );
[9415]277        }
[8319]278        currentLOD = wantedLOD;
[9415]279
280        //Check if the page is a level four page. If yes, copy the vertex and index data into
[8741]281        //the shared level four page buffers.
[8641]282        if ( currentLOD == TerrainPage::MAX_LODS-1 ) {
[9415]283                owner->addLevelFourPage( numVertices, vertices,
[8641]284                        numIndices, indices );
285        }
[8319]286        forceTesselation = false;
287}
288
[9415]289void TerrainPage::tesselateTopRow(  int _z, int _stride,
[8741]290        bool _adaptLeft,  bool _adaptRight )
291{
292        int halfStride = _stride/2;
293        int xStart = 0, xEnd= owner->getPageSize()-1;
294        int size = xEnd;
[9415]295        int z = xEnd-_stride ;
[8741]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        }
331
332}
[9415]333void TerrainPage::tesselateBottomRow(  int _z,  int _stride,
[8741]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        }
375}
376
[8641]377void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
[8349]378{
[8641]379        assert( indices ); assert( vertices );
380        numIndices = numVertices = 0;
[8349]381        const int       halfStride = 8, stride = 16;
[9415]382
[8349]383        enum { ADAPT_L = 1, ADAPT_R = 2, ADAPT_B = 4, ADAPT_T = 8,
[9415]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,
[8349]386                ADAPT_RBT = 14, ADAPT_LRBT = 15, ADAPT_NONE = 0 };
[9415]387
388        int                     code =  ( _adapt[TP_LEFT]       ? ADAPT_L : 0 ) |
389                                                ( _adapt[TP_RIGHT]      ? ADAPT_R : 0 ) |
390                                                ( _adapt[TP_BOTTOM] ? ADAPT_B : 0 ) |
[8349]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;
[9415]399
[8349]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 ) );
[8741]406                        addAgain( );
[8349]407                        break;
[9415]408
[8349]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 ) );
[8741]415                        addAgain( );
[8349]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 ) );
[8741]429                        addAgain();
[8349]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 ) );
[8684]450                        addAgain( );
[8349]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 ) );
[8684]464                        addAgain( );
[8349]465                        break;
466
467                case ADAPT_T:
468                        addIndex( getIndex( stride, stride ) );
[8684]469                        addAgain( );
[8349]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 ) );
[8684]481                        addAgain( );
[8349]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 ) );
[8684]504                        addAgain( );
[8349]505                        break;
506
507                case ADAPT_BT:
508                        addIndex( getIndex( 0, 0 ) );
[8684]509                        addAgain( );
[8349]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 ) );
[8684]515                        addAgain( );
[8349]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 ) );
[8684]526                        addAgain( );
[8349]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 ) );
[8684]537                        addAgain( );
[8349]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        }
[8641]551        assert( numIndices % 2 == 0 );
[8349]552}
553
554
[8319]555void TerrainPage::tesselate( int _lod )
556{
[8349]557
[9415]558        memset( indexHash, 0xffff,
[8641]559                        sizeof(unsigned short)*Terrain::MAX_VERTICES );
[9415]560
[8319]561        numVertices = 0; numIndices = 0;
[9415]562
[8319]563        //Calculate the pace, based on the lod.
564        int stride = 1 << _lod;
[9415]565
[8349]566        bool adapt[4];
567        determineBorderAdaption( adapt );
568        assert( isVisible );
[8569]569#ifdef USE_VBO
[8641]570        if ( _lod == TerrainPage::MAX_LODS-1 ) {
571                if ( vbIdentifier && ibIdentifier ) {
572                        owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
573                        vbIdentifier = ibIdentifier = 0;
574                }
[9415]575                if ( !vertices )
576                        vertices =  new Vertex[8];
[8641]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;
[9415]587                        vertices = NULL; indices = NULL;
[8641]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.
[9415]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..
[8641]597
[9415]598                glBufferDataARB( GL_ARRAY_BUFFER_ARB, Terrain::MAX_VERTICES*sizeof( Vertex ),
[8641]599                        NULL, GL_DYNAMIC_DRAW_ARB );
600
[9415]601                vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB,
[8641]602                        GL_WRITE_ONLY_ARB );
603
604                glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
605
[9415]606                glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB,
607                        Terrain::MAX_INDICES*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB );
[8641]608
[9415]609                indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB,
[8641]610                        GL_WRITE_ONLY_ARB );
611
[9415]612        }
[8641]613
[9415]614#endif
[8641]615
616        assert( indices );      assert( vertices );
[8349]617        if ( _lod == TerrainPage::MAX_LODS-1 ) {
[8641]618                tesselateLevelFourPage( adapt );
[8349]619                return;
[8319]620        }
[9415]621
[8349]622        int zStart = 0, zEnd = owner->getPageSize()-stride;
[9415]623
[8648]624        if ( adapt[TP_BOTTOM] ) {
[8741]625                tesselateBottomRow( 0, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
[8349]626                zStart+= stride;
627        }
[9415]628
[8648]629        if ( adapt[TP_TOP] )
[8349]630                zEnd-= stride;
[9415]631
[8349]632        for ( int z = zStart; z < zEnd; z+=stride )
633                tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
634
[9415]635
[8648]636        if ( adapt[TP_TOP] ) {
[9415]637                tesselateTopRow( owner->getPageSize()-stride-1,
[8648]638                        stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
[8569]639        }
[9415]640
[8569]641#ifdef USE_VBO
[8641]642        if ( vbIdentifier && ibIdentifier ) {
643                glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
644                indices = NULL;
645                glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB );
646                vertices = NULL;
[9415]647        }
[8569]648#endif
[8349]649
[8319]650}
651
652
653void TerrainPage::show( )
654{
[9415]655
656#ifdef USE_VBO
[8641]657        //This is done later on...
658        //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
[8569]659        vertices = NULL;
660        indices = NULL;
661#else
[8641]662        vertices = new Vertex[Terrain::MAX_VERTICES];
663        indices = new unsigned short[Terrain::MAX_INDICES];
[9415]664#endif
[8641]665        vbIdentifier = 0; ibIdentifier = 0;
[9415]666        indexHash = new unsigned short[Terrain::MAX_VERTICES];
[8319]667        forceTesselation = true;
668        activate();
669        active = true;
670}
671
672void TerrainPage::hide( )
673{
[8569]674#ifdef USE_VBO
[9415]675        owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
[8641]676#endif
[8775]677        SAVE_DELETE_ARRAY( vertices );
678        numVertices = 0;
679        SAVE_DELETE_ARRAY( indices );
680        numIndices = 0;
[8319]681        deactivate();
682}
683
684void TerrainPage::drawBox()
685{
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 );
[9415]694
[8319]695                glVertex3f( 0.0f, 0.0f, bounds.z );
696                glVertex3f(  bounds.x, 0.0f, bounds.z );
697                glVertex3f( bounds.x, bounds.y, bounds.z );
[9415]698                glVertex3f( 0.0f, bounds.y, bounds.z );
699
[8319]700                glVertex3f( 0.0f, 0.0f, 0.0 );
701                glVertex3f(  0.0, 0.0f, bounds.z );
702                glVertex3f( 0.0f, bounds.y, bounds.z );
[9415]703                glVertex3f( 0.0f, bounds.y, 0.0f );
704
[8319]705                glVertex3f( bounds.x, 0.0f, 0.0 );
706                glVertex3f(  bounds.x, 0.0f, bounds.z );
707                glVertex3f( bounds.x, bounds.y, bounds.z );
[9415]708                glVertex3f( bounds.x, bounds.y, 0.0f );
[8319]709        glEnd();
710        glPopMatrix();
711}
[8641]712//TODO: put all the pages that have a coarses tesselation level than 4 into a
713//              separate list!
[8319]714void TerrainPage::draw( )
715{
716        assert( glIsEnabled( GL_VERTEX_ARRAY ) );
717        assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
[9415]718
[8641]719        if ( currentLOD == TerrainPage::MAX_LODS-1 )
720                return;
[9415]721
[8328]722        assert( isVisible ); assert( numIndices > 0 );
[8319]723        active = false;
[9415]724        CHECK_GL_ERROR( "1" );
[8569]725#ifdef USE_VBO
[9415]726
[8569]727        glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
728        glClientActiveTextureARB( GL_TEXTURE0_ARB );
729        glInterleavedArrays( GL_T2F_V3F, 0, NULL );
[9415]730
[8548]731        glClientActiveTextureARB( GL_TEXTURE1_ARB );
[8569]732        glInterleavedArrays( GL_T2F_V3F, 0, NULL );
[9415]733
734        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
735
736        glDrawElements( GL_TRIANGLE_STRIP, numIndices,
737                                        GL_UNSIGNED_SHORT, NULL );
738#else
[8569]739        glClientActiveTextureARB( GL_TEXTURE0_ARB );
740        glInterleavedArrays( GL_T2F_V3F, 0, vertices );
[9415]741
[8569]742        glClientActiveTextureARB( GL_TEXTURE1_ARB );
743        glInterleavedArrays( GL_T2F_V3F, 0, vertices );
[9415]744
745        glDrawElements( GL_TRIANGLE_STRIP, numIndices,
746                                        GL_UNSIGNED_SHORT, indices );
[8569]747#endif
748
[9415]749
750
[8319]751        if ( owner->debug() )
752                drawBox( );
[9415]753
754        CHECK_GL_ERROR( "2" );
[8319]755}
756
[8641]757unsigned short TerrainPage::getIndex( int _x, int _z )
[8319]758{
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;
[8569]763                getVertex( _x, _z, vertices[numVertices].p );
764                getCoord( _x, _z, vertices[numVertices].t );
[8319]765                numVertices++;
766        }
767        return indexHash[index];
768}
769
[9415]770void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const
[8319]771{
[9415]772        owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ),
[8319]773                                         _z+zOffset*(owner->getPageSize()-1 ), _coord );
774}
775
[9147]776void TerrainPage::getVertex( int _x, int _z, Vector& _vertex ) const
[8319]777{
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 );
782}
[8745]783void TerrainPage::setLayerVisibility( int _layer, LayerVisibility _lv )
784{
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;
[9415]791        }
792        layerVisibility[_layer] = _lv;
[8745]793}
[8319]794
[8745]795bool TerrainPage::hasMaterial( int _layer )
[9415]796{
[8745]797        return ( layerVisibility[_layer] != LV_NO );
798}
[8319]799void TerrainPage::calculateErrors()
800{
801        for ( int i = 0; i < TerrainPage::MAX_LODS; ++i )
802                calculateError( i );
[9415]803}
Note: See TracBrowser for help on using the repository browser.