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
Line 
1/*
2        orxonox - the future of 3D-vertical-scrollers
3
4        Copyright (C) 2006 orx
5
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.
10
11        ### File Specific:
12        main-programmer: Marco Biasini
13
14 */
15#include "terrain_page.h"
16#include "terrain.h"
17#include "glincl.h"
18#include <stdio.h>
19#include <math.h>
20#define USE_VBO
21
22#define CHECK_GL_ERROR( _d ) do { \
23        GLenum __err = glGetError(); \
24        if ( __err != GL_NO_ERROR ) \
25                printf( "check%s: %s\n", _d, (char*)gluErrorString( __err ) );\
26        }\
27        while ( 0 )
28
29TerrainPage::~TerrainPage( )
30{
31        SAVE_DELETE_ARRAY( indices );
32        SAVE_DELETE_ARRAY( vertices );
33        SAVE_DELETE_ARRAY( indexHash );
34        SAVE_DELETE_ARRAY( errors );
35}
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];
43        vertices = NULL; indices = NULL;
44        left = top = bottom = right = NULL;
45        for ( int i = 0; i < 8; ++i )
46                layerVisibility[i] = LV_NO;
47
48        position = Vector( scale.x*_xOffset,
49                0.0f, scale.z*_zOffset );
50        isVisible = false;
51        next = NULL;
52        active = false;
53        previous = NULL;
54        currentLOD = -1; wantedLOD = -1;
55        hasfull = false;
56        forceTesselation = true;
57        vbIdentifier = 0; ibIdentifier = 0;
58}
59
60void 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        }
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;
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        }
126}
127
128int TerrainPage::chooseLOD()
129{
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;
151}
152
153void TerrainPage::activate()
154{
155
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();
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;
177
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        {
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        }
225}
226
227void TerrainPage::calculateBounds()
228{
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 );
244}
245
246float TerrainPage::getAltitude( int _x, int _z ) const
247{
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 );
253}
254
255bool TerrainPage::needsRetesselation()
256{
257
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 );
270}
271
272void TerrainPage::updateTesselation( )
273{
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;
287}
288
289void 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        }
331
332}
333void 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        }
375}
376
377void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
378{
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 );
552}
553
554
555void TerrainPage::tesselate( int _lod )
556{
557
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 );
569#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        }
613
614#endif
615
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        }
640
641#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        }
648#endif
649
650}
651
652
653void TerrainPage::show( )
654{
655
656#ifdef USE_VBO
657        //This is done later on...
658        //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
659        vertices = NULL;
660        indices = NULL;
661#else
662        vertices = new Vertex[Terrain::MAX_VERTICES];
663        indices = new unsigned short[Terrain::MAX_INDICES];
664#endif
665        vbIdentifier = 0; ibIdentifier = 0;
666        indexHash = new unsigned short[Terrain::MAX_VERTICES];
667        forceTesselation = true;
668        activate();
669        active = true;
670}
671
672void TerrainPage::hide( )
673{
674#ifdef USE_VBO
675        owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
676#endif
677        SAVE_DELETE_ARRAY( vertices );
678        numVertices = 0;
679        SAVE_DELETE_ARRAY( indices );
680        numIndices = 0;
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 );
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();
711}
712//TODO: put all the pages that have a coarses tesselation level than 4 into a
713//              separate list!
714void TerrainPage::draw( )
715{
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" );
725#ifdef USE_VBO
726
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 );
738#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 );
747#endif
748
749
750
751        if ( owner->debug() )
752                drawBox( );
753
754        CHECK_GL_ERROR( "2" );
755}
756
757unsigned short TerrainPage::getIndex( int _x, int _z )
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;
763                getVertex( _x, _z, vertices[numVertices].p );
764                getCoord( _x, _z, vertices[numVertices].t );
765                numVertices++;
766        }
767        return indexHash[index];
768}
769
770void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const
771{
772        owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ),
773                                         _z+zOffset*(owner->getPageSize()-1 ), _coord );
774}
775
776void TerrainPage::getVertex( int _x, int _z, Vector& _vertex ) const
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}
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;
791        }
792        layerVisibility[_layer] = _lv;
793}
794
795bool TerrainPage::hasMaterial( int _layer )
796{
797        return ( layerVisibility[_layer] != LV_NO );
798}
799void TerrainPage::calculateErrors()
800{
801        for ( int i = 0; i < TerrainPage::MAX_LODS; ++i )
802                calculateError( i );
803}
Note: See TracBrowser for help on using the repository browser.