Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9147 was 9147, checked in by ponder, 18 years ago

To rid of the triple and plane struct in types.h. now using the generic ones

File size: 21.2 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.