Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8697 was 8697, checked in by patrick, 18 years ago

merged the terrain with the new trunk (MARK TERRAIN)

File size: 18.1 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( Terrain *_owner, int _xOffset, int _zOffset )
30: TerrainQuad( _owner, _xOffset, _zOffset )
31{
32        scale = owner->getScale();
33        numVertices = numIndices = 0;
34        errors = new LODError[TerrainPage::MAX_LODS];
35        vertices = NULL; indices = NULL; 
36        position = Triple( scale.x*_xOffset, 0.0f, scale.z*_zOffset );
37        isVisible = false;
38        next = NULL;
39        active = false;
40        previous = NULL;
41        currentLOD = -1;
42        forceTesselation = true;
43        vbIdentifier = 0; ibIdentifier = 0;
44}
45
46void TerrainPage::tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight )
47{
48       
49        int xStart = 0, xEnd = owner->getPageSize();   
50        int halfStride = _zStride >> 1;
51        assert( _xStride > 0 );         assert( _zStride > 0 );
52        if ( _z ) {
53                addAgain( );
54                addIndex( getIndex( 0, _z ) );
55        }
56        if ( _adaptLeft ) {
57                assert( halfStride > 0 );               
58                addIndex( getIndex( 0, _z ) );
59                addIndex( getIndex( 0, _z+halfStride ) );
60                addIndex( getIndex( _xStride, _z ) );
61                addIndex( getIndex( 0, _z+_zStride ) );
62                addIndex( getIndex( _xStride, _z+_zStride ) );
63                addAgain();
64                xStart = _xStride;
65        }
66       
67        if ( _adaptRight )
68                xEnd-=_xStride;
69               
70        for ( int x = xStart; x < xEnd; x+=_xStride ) {
71                addIndex( getIndex( x, _z) );
72                addIndex( getIndex( x, _z+_zStride ) );
73        }
74       
75        int w = owner->getPageSize()-1;
76       
77        if ( _adaptRight ) {
78                assert( halfStride > 0 );               
79                addIndex( getIndex( w-_xStride, _z ) );
80                addAgain();
81                addIndex( getIndex( w, _z ) );
82                addIndex( getIndex( w-_xStride, _z+_zStride ) );
83                addIndex( getIndex( w, _z+halfStride ) );
84                addIndex( getIndex( w, _z+_zStride ) );
85        }
86}
87
88//TODO: Perform benchmark to measure if the isVisible test should be included
89//in this method.
90void TerrainPage::determineBorderAdaption( bool _adapt[] )
91{
92        _adapt[0] = _adapt[1] = _adapt[2] = _adapt[3] = false;
93       
94        if ( left  && left->isVisible ) 
95                _adapt[TP_LEFT] = ( wantedLOD - left->getWantedLOD() ) > 0;
96               
97        if ( right && right->isVisible ) 
98                _adapt[TP_RIGHT] = ( wantedLOD - right->getWantedLOD() ) > 0;
99               
100        if ( top && top->isVisible ) 
101                _adapt[TP_TOP] = ( wantedLOD - top->getWantedLOD() ) > 0;                               
102               
103        if ( bottom && bottom->isVisible ) 
104                _adapt[TP_BOTTOM] = ( wantedLOD - bottom->getWantedLOD() ) > 0;         
105}
106
107int TerrainPage::chooseLOD()
108{
109        wantedLOD = -1;
110        Triple cam( owner->getCameraPosition() );
111       
112        for ( int i = TerrainPage::MAX_LODS-1; i >= 0; --i ) {
113                Triple distance( cam.x-errors[i].correct.x,
114                                                 cam.y-errors[i].correct.y,
115                                                 cam.z-errors[i].correct.z );
116               
117                float d = distance.length();
118               
119                assert( d > 0.000001f );
120                float err =  errors[i].diff / d ;
121               
122                if ( err*scale.y < owner->getDetail() ) {
123                        wantedLOD = i;
124                        break;
125                }       
126        }
127        if ( wantedLOD < 0 ) {
128                wantedLOD = TerrainPage::MAX_LODS-1;
129        }       
130        return wantedLOD;
131}
132
133void TerrainPage::activate()
134{
135       
136        pTerrainPage list = owner->getActiveList();
137        next = list;
138        if ( list )
139                list->previous = this;
140        owner->setActiveList( this );
141}
142
143void TerrainPage::deactivate()
144{
145        pTerrainPage list = owner->getActiveList();
146       
147        if ( previous ) {
148                previous->next = next;
149        }
150        if ( next ) {
151                next->previous = previous;
152        }
153        if ( list == this )
154                owner->setActiveList( next );
155        next = NULL;
156        previous = NULL;
157       
158}
159
160void TerrainPage::calculateError( int _lod )
161{
162        float   sumError = 0.0f;
163        int             numErrors = 0;
164        int size = owner->getPageSize();
165        if( _lod!=0 )
166        {
167                int stride = 1 << _lod, x0, y0, xi, yi;
168                // Altough these four nested loops look very scary, they're not
169                // that bad and require only about O(n^2).
170                for( y0 = 0 ; y0 < size-stride; y0 += stride ) {
171                        for( x0 = 0; x0 < size-stride; x0 += stride ) {
172                                for( yi = 1; yi < stride; yi++ ) {
173                                        for( xi = 1; xi < stride; xi++ )
174                                        {
175                                                int     x = x0+xi,
176                                                y = y0+yi;
177                                                float   fx0 = ( float )xi/( float )stride, fx1 = 1.0f-fx0,
178                                                                fy0 = ( float )yi/( float )stride, fy1 = 1.0f-fy0;
179                                               
180                                                float   height00 = getAltitude( x0, y0 ),
181                                                                height10 = getAltitude( x0+stride,y0 ),
182                                                                height01 = getAltitude( x0,y0+stride ),
183                                                                height11 = getAltitude( x0+stride, y0+stride );
184                                               
185                                                float   paintHeight =   fx1*fy1 * height00 +
186                                                        fx0*fy1 * height10 +
187                                                        fx1*fy0 * height01 +
188                                                        fx0*fy0 * height11,
189                                                        correctHeight =  getAltitude( x, y );
190                                               
191                                                float   er = ( float )fabs( correctHeight - paintHeight );
192                                               
193                                                numErrors++;
194                                                sumError += er;
195                                        }
196                                }
197                        }
198                }
199                float error = sumError / numErrors;
200                getVertex(size/2, size/2, errors[_lod].correct);
201                errors[_lod].real = errors[_lod].correct;
202                errors[_lod].real.y += error;
203                errors[_lod].diff = error;
204        }
205}
206
207void TerrainPage::calculateBounds()
208{
209        int size = owner->getPageSize();
210        float alt = 0.0f;
211       
212        Triple  min( xOffset*scale.x ,0.0f, zOffset*scale.z ), 
213                        max( (xOffset+1)*scale.x, 0.0f, (zOffset+1)*scale.z);
214       
215        min.y = max.y = getAltitude( 0, 0 );
216        for ( int x = 0; x < size; ++x ) {
217                for ( int z = 0; z < size; ++z ) {
218                        alt = getAltitude( x, z );
219                        min.y = fmin( min.y, alt );
220                        max.y = fmax( max.y, alt );
221                }
222        }
223        bounds.set( min, max );
224}
225
226float TerrainPage::getAltitude( int _x, int _z ) const
227{
228        assert( _x >= 0 && _x < 17 );
229        assert( _z >= 0 && _z < 17 );
230        return position.y+scale.y*owner->getAltitude( 
231                        _x+(owner->getPageSize()-1)*xOffset, 
232                        _z+(owner->getPageSize()-1)*zOffset );
233}
234
235bool TerrainPage::needsRetesselation()
236{
237       
238        bool    leftChanged     = ( left && left->isActive() ) &&
239                                ( left->wantedLOD != left->currentLOD ),
240                        rightChanged    = ( right && right->isActive() ) && 
241                                ( right->wantedLOD != right->currentLOD ),
242                        topChanged              = ( top && top->isActive() ) && 
243                                ( top->wantedLOD != currentLOD ),
244                        bottomChanged   = ( bottom && bottom->isActive() ) && 
245                                ( bottom->wantedLOD != bottom->currentLOD ),
246                        iChanged                =  wantedLOD != currentLOD;
247                               
248        return ( leftChanged || rightChanged || topChanged || bottomChanged || forceTesselation || iChanged );
249}
250
251void TerrainPage::updateTesselation( )
252{
253
254        if ( needsRetesselation() ) {
255                tesselate( wantedLOD );
256        }       
257        currentLOD = wantedLOD;
258        //Check if the page is a level four page. If yes, copy the vertex and index data into
259        //
260        if ( currentLOD == TerrainPage::MAX_LODS-1 ) {
261                owner->addLevelFourPage( numVertices, vertices, 
262                        numIndices, indices );
263        }
264        forceTesselation = false;
265}
266
267void TerrainPage::tesselateLevelFourPage( bool _adapt[] )
268{
269        assert( indices ); assert( vertices );
270        numIndices = numVertices = 0;
271        const int       halfStride = 8, stride = 16;
272       
273        enum { ADAPT_L = 1, ADAPT_R = 2, ADAPT_B = 4, ADAPT_T = 8,
274                ADAPT_LR = 3, ADAPT_LB = 5, ADAPT_LT = 9, ADAPT_RB = 6, 
275                ADAPT_RT = 10, ADAPT_BT = 12, ADAPT_LRB = 7, ADAPT_LBT = 13, ADAPT_LRT = 11, 
276                ADAPT_RBT = 14, ADAPT_LRBT = 15, ADAPT_NONE = 0 };
277               
278        int                     code =  ( _adapt[TP_LEFT]       ? ADAPT_L : 0 ) | 
279                                                ( _adapt[TP_RIGHT]      ? ADAPT_R : 0 ) | 
280                                                ( _adapt[TP_BOTTOM] ? ADAPT_B : 0 ) | 
281                                                ( _adapt[TP_TOP]        ? ADAPT_T : 0 );
282        switch( code ) {
283                case ADAPT_NONE:
284                        addIndex( getIndex( 0, 0 ) );
285                        addIndex( getIndex( 0, stride ) );
286                        addIndex( getIndex( stride, 0 ) );
287                        addIndex( getIndex( stride, stride ) );
288                        break;
289                       
290                case ADAPT_L:
291                        addIndex( getIndex( 0, 0 ) );
292                        addIndex( getIndex( 0, halfStride ) );
293                        addIndex( getIndex( stride, 0 ) );
294                        addIndex( getIndex( 0, stride ) );
295                        addIndex( getIndex( stride, stride ) );
296                        addAgain(  );
297                        break;
298               
299                case ADAPT_R:
300                        addIndex( getIndex( stride, stride ) );
301                        addIndex( getIndex( stride, halfStride ) );
302                        addIndex( getIndex( 0, stride ) );
303                        addIndex( getIndex( stride, 0 ) );
304                        addIndex( getIndex( 0, 0 ) );
305                        addAgain(  );
306                        break;
307
308                case ADAPT_LR:
309                        addIndex( getIndex( 0, 0 ) );
310                        addIndex( getIndex( 0, halfStride ) );
311                        addIndex( getIndex( stride, 0 ) );
312                        addIndex( getIndex( 0, stride ) );
313                        addIndex( getIndex( stride, halfStride ) );
314                        addIndex( getIndex( stride, stride ) );
315                        break;
316
317                case ADAPT_B:
318                        addIndex( getIndex( 0, 0 ) );
319                        addAgain(  );
320                        addIndex( getIndex( halfStride, 0 ) );
321                        addIndex( getIndex( 0, stride ) );
322                        addIndex( getIndex( stride, 0 ) );
323                        addIndex( getIndex( stride, stride ) );
324                        break;
325
326                case ADAPT_LB:
327                        addIndex( getIndex( 0, 0 ) );
328                        addIndex( getIndex( 0, halfStride ) );
329                        addIndex( getIndex( halfStride, 0 ) );
330                        addIndex( getIndex( 0, stride ) );
331                        addIndex( getIndex( stride, 0 ) );
332                        addIndex( getIndex( stride, stride ) );
333                        break;
334
335                case ADAPT_RB:
336                        addIndex( getIndex( 0, 0 ) );
337                        addIndex( getIndex( 0, stride ) );
338                        addIndex( getIndex( halfStride, 0 ) );
339                        addIndex( getIndex( stride, 0 ) );
340                        addAgain( );
341                        addIndex( getIndex( 0, stride ) );
342                        addIndex( getIndex( stride, halfStride ) );
343                        addIndex( getIndex( stride, stride ) );
344                        break;
345
346                case ADAPT_LRB:
347                        addIndex( getIndex( stride, stride ) );
348                        addIndex( getIndex( stride, halfStride ) );
349                        addIndex( getIndex( 0, stride ) );
350                        addIndex( getIndex( stride, 0 ) );
351                        addIndex( getIndex( 0, halfStride ) );
352                        addIndex( getIndex( halfStride, 0 ) );
353                        addIndex( getIndex( 0, 0 ) );
354                        addAgain( );
355                        break;
356
357                case ADAPT_T:
358                        addIndex( getIndex( stride, stride ) );
359                        addAgain( );
360                        addIndex( getIndex( halfStride, stride ) );
361                        addIndex( getIndex( stride, 0 ) );
362                        addIndex( getIndex( 0, stride ) );
363                        addIndex( getIndex( 0, 0 ) );
364                        break;
365
366                case ADAPT_LT:
367                        addIndex( getIndex( stride, stride ) );
368                        addIndex( getIndex( stride, 0 ) );
369                        addIndex( getIndex( halfStride, stride ) );
370                        addIndex( getIndex( 0, stride ) );
371                        addAgain( );
372                        addIndex( getIndex( stride, 0 ) );
373                        addIndex( getIndex( 0, halfStride ) );
374                        addIndex( getIndex( 0, 0 ) );
375                        break;
376
377                case ADAPT_RT:
378                        addIndex( getIndex( stride, stride ) );
379                        addIndex( getIndex( stride, halfStride ) );
380                        addIndex( getIndex( halfStride, stride ) );
381                        addIndex( getIndex( stride, 0 ) );
382                        addIndex( getIndex( 0, stride ) );
383                        addIndex( getIndex( 0, 0 ) );
384                        break;
385
386                case ADAPT_LRT:
387                        addIndex( getIndex( 0, 0 ) );
388                        addIndex( getIndex( 0, halfStride ) );
389                        addIndex( getIndex( stride, 0 ) );
390                        addIndex( getIndex( 0, stride ) );
391                        addIndex( getIndex( stride, halfStride ) );
392                        addIndex( getIndex( halfStride, stride ) );
393                        addIndex( getIndex( stride, stride ) );
394                        addAgain( );
395                        break;
396
397                case ADAPT_BT:
398                        addIndex( getIndex( 0, 0 ) );
399                        addAgain( );
400                        addIndex( getIndex( halfStride, 0 ) );
401                        addIndex( getIndex( 0, stride ) );
402                        addIndex( getIndex( stride, 0 ) );
403                        addIndex( getIndex( halfStride, stride ) );
404                        addIndex( getIndex( stride, stride ) );
405                        addAgain( );
406                        break;
407
408                case ADAPT_LBT:
409                        addIndex( getIndex( 0, 0 ) );
410                        addIndex( getIndex( 0, halfStride ) );
411                        addIndex( getIndex( halfStride, 0 ) );
412                        addIndex( getIndex( 0, stride ) );
413                        addIndex( getIndex( stride, 0 ) );
414                        addIndex( getIndex( halfStride, stride ) );
415                        addIndex( getIndex( stride, stride ) );
416                        addAgain( );
417                        break;
418
419                case ADAPT_RBT:
420                        addIndex( getIndex( stride, stride ) );
421                        addIndex( getIndex( stride, halfStride ) );
422                        addIndex( getIndex( halfStride, stride ) );
423                        addIndex( getIndex( stride, 0 ) );
424                        addIndex( getIndex( 0, stride ) );
425                        addIndex( getIndex( halfStride, 0 ) );
426                        addIndex( getIndex( 0, 0 ) );
427                        addAgain( );
428                        break;
429
430                case ADAPT_LRBT:
431                        addIndex( getIndex( 0, 0 ) );
432                        addIndex( getIndex( 0, halfStride ) );
433                        addIndex( getIndex( halfStride, 0 ) );
434                        addIndex( getIndex( 0, stride ) );
435                        addIndex( getIndex( stride, 0 ) );
436                        addIndex( getIndex( halfStride, stride ) );
437                        addIndex( getIndex( stride, halfStride ) );
438                        addIndex( getIndex( stride, stride ) );
439                        break;
440        }
441        assert( numIndices % 2 == 0 );
442}
443
444
445void TerrainPage::tesselate( int _lod )
446{
447
448        memset( indexHash, 0xffff, 
449                        sizeof(unsigned short)*Terrain::MAX_VERTICES );
450       
451        numVertices = 0; numIndices = 0;
452       
453        //Calculate the pace, based on the lod.
454        int stride = 1 << _lod;
455               
456        bool adapt[4];
457        determineBorderAdaption( adapt );
458        assert( isVisible );
459#ifdef USE_VBO
460        if ( _lod == TerrainPage::MAX_LODS-1 ) {
461                if ( vbIdentifier && ibIdentifier ) {
462                        owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );
463                        vbIdentifier = ibIdentifier = 0;
464                }
465                if ( !vertices ) 
466                        vertices =  new Vertex[8]; 
467                if ( !indices )
468                        indices = new unsigned short[8];
469        }
470        else {
471                if ( !vbIdentifier && !ibIdentifier ) {
472                        owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
473                        if ( vertices )
474                                delete[] vertices;
475                        if ( indices )
476                                delete[] indices;
477                        vertices = NULL; indices = NULL;       
478                }
479                assert( vbIdentifier ); assert( ibIdentifier );
480                glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
481
482                // The call to glBufferDataARB with a null argument for data is to make things faster.
483                // Then calling call glMapBuffer() tells the driver that the previous
484                // data aren’t valid. As a consequence, if the GPU is still working on them, there won’t
485                // be a conflict because we invalidated these data. The function glMapBuffer() returns a
486                // new pointer that we can use while the GPU is working on the previous set of data..
487
488                glBufferDataARB( GL_ARRAY_BUFFER_ARB, Terrain::MAX_VERTICES*sizeof( Vertex ), 
489                        NULL, GL_DYNAMIC_DRAW_ARB );
490
491                vertices = (Vertex*)glMapBufferARB( GL_ARRAY_BUFFER_ARB, 
492                        GL_WRITE_ONLY_ARB );
493
494                glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );
495
496                glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
497                        Terrain::MAX_INDICES*sizeof( short ), NULL, GL_DYNAMIC_DRAW_ARB );     
498
499                indices = (unsigned short*)glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 
500                        GL_WRITE_ONLY_ARB );
501
502        }       
503
504#endif 
505
506        assert( indices );      assert( vertices );
507        if ( _lod == TerrainPage::MAX_LODS-1 ) {
508                tesselateLevelFourPage( adapt );
509                return;
510        }
511       
512        int zStart = 0, zEnd = owner->getPageSize()-stride;
513       
514        if ( adapt[TP_BOTTOM] ) {
515                tesselateRow( 0, stride / 2, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
516                zStart+= stride;
517        }
518       
519        if ( adapt[TP_TOP] )
520                zEnd-= stride;
521               
522        for ( int z = zStart; z < zEnd; z+=stride )
523                tesselateRow( z, stride, stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
524       
525
526        if ( adapt[TP_TOP] ) {
527                addAgain( );
528                addIndex( getIndex( 0, owner->getPageSize()-1-stride ) );
529                tesselateRow( owner->getPageSize()-1-stride, stride / 2, 
530                        stride, adapt[TP_LEFT], adapt[TP_RIGHT] );
531        }
532       
533#ifdef USE_VBO
534        if ( vbIdentifier && ibIdentifier ) {
535                glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
536                indices = NULL;
537                glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB );
538                vertices = NULL;
539        }       
540#endif
541
542}
543
544
545void TerrainPage::show( )
546{
547       
548#ifdef USE_VBO 
549        //This is done later on...
550        //owner->getBufferBroker()->acquire( vbIdentifier, ibIdentifier );
551        vertices = NULL;
552        indices = NULL;
553#else
554        vertices = new Vertex[Terrain::MAX_VERTICES];
555        indices = new unsigned short[Terrain::MAX_INDICES];
556#endif 
557        vbIdentifier = 0; ibIdentifier = 0;
558        indexHash = new unsigned short[Terrain::MAX_VERTICES]; 
559        forceTesselation = true;
560        activate();
561        active = true;
562}
563
564void TerrainPage::hide( )
565{
566#ifdef USE_VBO
567        owner->getBufferBroker()->release( vbIdentifier, ibIdentifier );       
568#endif
569        if ( vertices ) {
570                delete[] vertices;
571                vertices = NULL;
572        }
573        if ( indices ) {
574                delete[] indices;
575                indices = NULL;
576                numIndices = 0;
577        }
578        deactivate();
579}
580
581void TerrainPage::drawBox()
582{
583        glMatrixMode( GL_MODELVIEW );
584        glPushMatrix();
585        glTranslatef( bounds.corner.x, bounds.corner.y, bounds.corner.z );
586        glBegin( GL_QUADS );
587                glVertex3f( 0.0f, 0.0f, 0.0f );
588                glVertex3f(  bounds.x, 0.0f, 0.0f );
589                glVertex3f( bounds.x, bounds.y, 0.0f );
590                glVertex3f( 0.0f, bounds.y, 0.0f );
591               
592                glVertex3f( 0.0f, 0.0f, bounds.z );
593                glVertex3f(  bounds.x, 0.0f, bounds.z );
594                glVertex3f( bounds.x, bounds.y, bounds.z );
595                glVertex3f( 0.0f, bounds.y, bounds.z );         
596               
597                glVertex3f( 0.0f, 0.0f, 0.0 );
598                glVertex3f(  0.0, 0.0f, bounds.z );
599                glVertex3f( 0.0f, bounds.y, bounds.z );
600                glVertex3f( 0.0f, bounds.y, 0.0f );                             
601               
602                glVertex3f( bounds.x, 0.0f, 0.0 );
603                glVertex3f(  bounds.x, 0.0f, bounds.z );
604                glVertex3f( bounds.x, bounds.y, bounds.z );
605                glVertex3f( bounds.x, bounds.y, 0.0f );                                         
606        glEnd();
607        glPopMatrix();
608}
609//TODO: put all the pages that have a coarses tesselation level than 4 into a
610//              separate list!
611void TerrainPage::draw( )
612{
613        assert( glIsEnabled( GL_VERTEX_ARRAY ) );
614        assert( !glIsEnabled( GL_NORMAL_ARRAY ) );
615       
616        if ( currentLOD == TerrainPage::MAX_LODS-1 )
617                return;
618               
619        assert( isVisible ); assert( numIndices > 0 );
620        assert( active );
621        active = false;
622        CHECK_GL_ERROR( "1" ); 
623       
624#ifdef USE_VBO
625       
626        glBindBufferARB( GL_ARRAY_BUFFER_ARB, vbIdentifier );
627        glClientActiveTextureARB( GL_TEXTURE0_ARB );
628        glInterleavedArrays( GL_T2F_V3F, 0, NULL );
629       
630        glClientActiveTextureARB( GL_TEXTURE1_ARB );
631        glInterleavedArrays( GL_T2F_V3F, 0, NULL );
632       
633        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ibIdentifier );   
634       
635        glDrawElements( GL_TRIANGLE_STRIP, numIndices, 
636                                        GL_UNSIGNED_SHORT, NULL );     
637#else   
638        glClientActiveTextureARB( GL_TEXTURE0_ARB );
639        glInterleavedArrays( GL_T2F_V3F, 0, vertices );
640       
641        glClientActiveTextureARB( GL_TEXTURE1_ARB );
642        glInterleavedArrays( GL_T2F_V3F, 0, vertices );
643       
644        glDrawElements( GL_TRIANGLE_STRIP, numIndices, 
645                                        GL_UNSIGNED_SHORT, indices );   
646#endif
647       
648
649       
650        if ( owner->debug() )
651                drawBox( );
652               
653        CHECK_GL_ERROR( "2" ); 
654}
655
656unsigned short TerrainPage::getIndex( int _x, int _z )
657{
658        unsigned short index = _z*owner->getPageSize()+_x;
659        if ( indexHash[index] == 0xffff ) {
660                //The vertex didn't exists before, lets create it.
661                indexHash[index] = numVertices;
662                getVertex( _x, _z, vertices[numVertices].p );
663                getCoord( _x, _z, vertices[numVertices].t );
664                numVertices++;
665        }
666        return indexHash[index];
667}
668
669void TerrainPage::getCoord( int _x, int _z, TexCoord& _coord ) const 
670{
671        owner->getCoord( _x+xOffset*(owner->getPageSize()-1 ), 
672                                         _z+zOffset*(owner->getPageSize()-1 ), _coord );
673}
674
675void TerrainPage::getVertex( int _x, int _z, Triple& _vertex ) const
676{
677        _vertex.x = position.x+scale.x*_x/
678                ( owner->getPageSize()-1 );
679        _vertex.y = getAltitude( _x, _z );
680        _vertex.z = position.z+scale.z*_z/( owner->getPageSize()-1 );
681}
682
683void TerrainPage::calculateErrors()
684{
685        for ( int i = 0; i < TerrainPage::MAX_LODS; ++i )
686                calculateError( i );
687}
Note: See TracBrowser for help on using the repository browser.