~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgTerrain/GeometryTechnique.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
*/
13
13
 
14
14
#include <osgTerrain/GeometryTechnique>
 
15
#include <osgTerrain/TerrainTile>
15
16
#include <osgTerrain/Terrain>
16
17
 
17
18
#include <osgUtil/SmoothingVisitor>
27
28
 
28
29
using namespace osgTerrain;
29
30
 
 
31
#define NEW_COORD_CODE
 
32
 
30
33
GeometryTechnique::GeometryTechnique():
31
34
    _currentReadOnlyBuffer(1),
32
35
    _currentWriteBuffer(0)
98
101
 
99
102
void GeometryTechnique::init()
100
103
{
101
 
    osg::notify(osg::INFO)<<"Doing init()"<<std::endl;
 
104
    // osg::notify(osg::NOTICE)<<"Doing GeometryTechnique::init()"<<std::endl;
102
105
    
103
 
    if (!_terrain) return;
 
106
    if (!_terrainTile) return;
104
107
 
105
108
    BufferData& buffer = getWriteBuffer();
106
109
    
111
114
    generateGeometry(masterLocator, centerModel);
112
115
    
113
116
    applyColorLayers();
114
 
    
115
 
    applyTransferFunctions();
116
 
    
117
117
    applyTransparency();
118
118
    
119
 
    smoothGeometry();
 
119
    // smoothGeometry();
120
120
 
121
121
    if (buffer._transform.valid()) buffer._transform->setThreadSafeRefUnref(true);
122
122
 
127
127
 
128
128
Locator* GeometryTechnique::computeMasterLocator()
129
129
{
130
 
    osgTerrain::Layer* elevationLayer = _terrain->getElevationLayer();
131
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
 
130
    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
 
131
    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
132
132
 
133
133
    Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0;
134
134
    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
149
149
 
150
150
    BufferData& buffer = getWriteBuffer();
151
151
    
152
 
    osgTerrain::Layer* elevationLayer = _terrain->getElevationLayer();
153
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
154
 
    osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
155
 
 
156
 
    if ((elevationLayer==colorLayer) && colorTF) colorLayer = 0;
 
152
    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
 
153
    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
157
154
 
158
155
    Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0;
159
156
    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
212
209
{
213
210
    BufferData& buffer = getWriteBuffer();
214
211
    
215
 
    osgTerrain::Layer* elevationLayer = _terrain->getElevationLayer();
216
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
217
 
    osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
218
 
    
219
 
    if ((elevationLayer==colorLayer) && colorTF) colorLayer = 0;
220
 
 
221
 
    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
222
 
 
223
 
    if (!colorLocator) colorLocator = masterLocator;
224
 
    
 
212
    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
 
213
 
225
214
    buffer._geode = new osg::Geode;
226
215
    if(buffer._transform.valid())
227
216
        buffer._transform->addChild(buffer._geode.get());
228
217
    
229
218
    buffer._geometry = new osg::Geometry;
230
 
    if (buffer._geometry.valid()) buffer._geode->addDrawable(buffer._geometry.get());
231
 
    
232
 
    unsigned int numRows = 100;
233
 
    unsigned int numColumns = 100;
 
219
    buffer._geode->addDrawable(buffer._geometry.get());
 
220
        
 
221
    osg::Geometry* geometry = buffer._geometry.get();
 
222
 
 
223
    unsigned int numRows = 20;
 
224
    unsigned int numColumns = 20;
234
225
    
235
226
    if (elevationLayer)
236
227
    {
238
229
        numRows = elevationLayer->getNumRows();
239
230
    }
240
231
    
241
 
    bool treatBoundariesToValidDataAsDefaultValue = _terrain->getTreatBoundariesToValidDataAsDefaultValue();
 
232
    float sampleRatio = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getSampleRatio() : 1.0f;
 
233
    
 
234
    double i_sampleFactor = 1.0;
 
235
    double j_sampleFactor = 1.0;
 
236
 
 
237
    if (sampleRatio!=1.0f)
 
238
    {
 
239
    
 
240
        unsigned int originalNumColumns = numColumns;
 
241
        unsigned int originalNumRows = numRows;
 
242
    
 
243
        numColumns = std::max((unsigned int) (float(originalNumColumns)*sqrtf(sampleRatio)), 4u);
 
244
        numRows = std::max((unsigned int) (float(originalNumRows)*sqrtf(sampleRatio)),4u);
 
245
 
 
246
        i_sampleFactor = double(originalNumColumns-1)/double(numColumns-1);
 
247
        j_sampleFactor = double(originalNumRows-1)/double(numRows-1);
 
248
    }
 
249
    
 
250
    
 
251
 
 
252
    bool treatBoundariesToValidDataAsDefaultValue = _terrainTile->getTreatBoundariesToValidDataAsDefaultValue();
242
253
    osg::notify(osg::INFO)<<"TreatBoundariesToValidDataAsDefaultValue="<<treatBoundariesToValidDataAsDefaultValue<<std::endl;
243
254
    
244
 
    unsigned int numVertices = numRows * numColumns;
 
255
    float skirtHeight = 0.0f;
 
256
    HeightFieldLayer* hfl = dynamic_cast<HeightFieldLayer*>(elevationLayer);
 
257
    if (hfl && hfl->getHeightField()) 
 
258
    {
 
259
        skirtHeight = hfl->getHeightField()->getSkirtHeight();
 
260
    }
 
261
    
 
262
    bool createSkirt = skirtHeight != 0.0f;
 
263
  
 
264
    unsigned int numVerticesInBody = numColumns*numRows;
 
265
    unsigned int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
 
266
    unsigned int numVertices = numVerticesInBody+numVerticesInSkirt;
245
267
 
246
268
    // allocate and assign vertices
247
 
    osg::Vec3Array* _vertices = new osg::Vec3Array;
248
 
    if (buffer._geometry.valid()) buffer._geometry->setVertexArray(_vertices);
 
269
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
 
270
    vertices->reserve(numVertices);
 
271
    geometry->setVertexArray(vertices.get());
249
272
 
250
273
    // allocate and assign normals
251
 
    osg::Vec3Array* _normals = new osg::Vec3Array;
252
 
    if (buffer._geometry.valid())
253
 
    {
254
 
        buffer._geometry->setNormalArray(_normals);
255
 
        buffer._geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
256
 
    }
 
274
    osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
 
275
    if (normals.valid()) normals->reserve(numVertices);
 
276
    geometry->setNormalArray(normals.get());
 
277
    geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
257
278
    
258
 
    int texcoord_index = 0;
259
 
    int color_index = -1;
260
 
    int tf_index = -1;
261
279
 
262
280
    float minHeight = 0.0;
263
281
    float scaleHeight = 1.0;
264
282
 
265
283
    // allocate and assign tex coords
266
 
    osg::Vec2Array* _texcoords = 0;
267
 
    if (colorLayer)
268
 
    {
269
 
        color_index = texcoord_index;
270
 
        ++texcoord_index;
271
 
 
272
 
        _texcoords = new osg::Vec2Array;
273
 
        
274
 
        if (buffer._geometry.valid()) buffer._geometry->setTexCoordArray(color_index, _texcoords);
275
 
    }
276
 
 
277
 
    osg::FloatArray* _elevations = new osg::FloatArray;
278
 
    osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
279
 
    if (tf)
280
 
    {
281
 
        tf_index = texcoord_index;
282
 
        ++texcoord_index;
283
 
 
284
 
        if (!colorLayer)
 
284
    typedef std::pair< osg::ref_ptr<osg::Vec2Array>, Locator* > TexCoordLocatorPair;
 
285
    typedef std::map< Layer*, TexCoordLocatorPair > LayerToTexCoordMap;
 
286
 
 
287
    LayerToTexCoordMap layerToTexCoordMap;
 
288
    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
 
289
    {
 
290
        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
 
291
        if (colorLayer)
285
292
        {
286
 
            // _elevations = new osg::FloatArray(numVertices);
287
 
            if (buffer._geometry.valid()) buffer._geometry->setTexCoordArray(tf_index, _elevations);
288
 
 
289
 
            minHeight = tf->getMinimum();
290
 
            scaleHeight = 1.0f/(tf->getMaximum()-tf->getMinimum());
 
293
            LayerToTexCoordMap::iterator itr = layerToTexCoordMap.find(colorLayer);
 
294
            if (itr!=layerToTexCoordMap.end())
 
295
            {
 
296
                geometry->setTexCoordArray(layerNum, itr->second.first.get());
 
297
            }
 
298
            else
 
299
            {
 
300
                TexCoordLocatorPair& tclp = layerToTexCoordMap[colorLayer];
 
301
                tclp.first = new osg::Vec2Array;
 
302
                tclp.first->reserve(numVertices);
 
303
                tclp.second = colorLayer->getLocator() ? colorLayer->getLocator() : masterLocator;
 
304
                geometry->setTexCoordArray(layerNum, tclp.first.get());
 
305
            }
291
306
        }
292
307
    }
293
308
 
294
 
    if (_vertices) _vertices->reserve(numVertices);
295
 
    if (_texcoords) _texcoords->reserve(numVertices);
296
 
    if (_elevations) _elevations->reserve(numVertices);
297
 
    if (_normals) _normals->reserve(numVertices);
 
309
    osg::ref_ptr<osg::FloatArray> elevations = new osg::FloatArray;
 
310
    if (elevations.valid()) elevations->reserve(numVertices);
298
311
        
 
312
 
299
313
    // allocate and assign color
300
 
    osg::Vec4Array* _colors = new osg::Vec4Array(1);
301
 
    (*_colors)[0].set(1.0f,1.0f,1.0f,1.0f);
 
314
    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
 
315
    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
302
316
    
303
 
    if (buffer._geometry.valid())
304
 
    {
305
 
        buffer._geometry->setColorArray(_colors);
306
 
        buffer._geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
307
 
    }
 
317
    geometry->setColorArray(colors.get());
 
318
    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
308
319
 
309
320
 
310
321
    typedef std::vector<int> Indices;
311
 
    Indices indices(numColumns*numRows, -1);
 
322
    Indices indices(numVertices, -1);
312
323
    
313
324
    // populate vertex and tex coord arrays
314
 
    unsigned int j;
 
325
    unsigned int i, j;
315
326
    for(j=0; j<numRows; ++j)
316
327
    {
317
 
        for(unsigned int i=0; i<numColumns; ++i)
 
328
        for(i=0; i<numColumns; ++i)
318
329
        {
319
330
            unsigned int iv = j*numColumns + i;
320
331
            osg::Vec3d ndc( ((double)i)/(double)(numColumns-1), ((double)j)/(double)(numRows-1), 0.0);
322
333
            bool validValue = true;
323
334
     
324
335
            
 
336
            unsigned int i_equiv = i_sampleFactor==1.0 ? i : (unsigned int) (double(i)*i_sampleFactor);
 
337
            unsigned int j_equiv = i_sampleFactor==1.0 ? j : (unsigned int) (double(j)*j_sampleFactor);
 
338
            
325
339
            if (elevationLayer)
326
340
            {
327
341
                float value = 0.0f;
328
 
                validValue = elevationLayer->getValidValue(i,j, value);
 
342
                validValue = elevationLayer->getValidValue(i_equiv,j_equiv, value);
329
343
                // osg::notify(osg::INFO)<<"i="<<i<<" j="<<j<<" z="<<value<<std::endl;
330
344
                ndc.z() = value;
331
345
            }
332
346
            
333
347
            if (validValue)
334
348
            {
335
 
                indices[iv] = _vertices->size();
 
349
                indices[iv] = vertices->size();
336
350
            
337
351
                osg::Vec3d model;
338
352
                masterLocator->convertLocalToModel(ndc, model);
339
353
 
340
 
                (*_vertices).push_back(model - centerModel);
 
354
                (*vertices).push_back(model - centerModel);
341
355
 
342
 
                if (colorLayer)
 
356
                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
 
357
                    itr != layerToTexCoordMap.end();
 
358
                    ++itr)
343
359
                {
344
 
                    if (colorLocator!= masterLocator)
 
360
                    osg::Vec2Array* texcoords = itr->second.first.get();
 
361
                    Locator* colorLocator = itr->second.second;
 
362
                    if (colorLocator != masterLocator)
345
363
                    {
346
364
                        osg::Vec3d color_ndc;
347
365
                        Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
348
 
                        (*_texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
 
366
                        (*texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
349
367
                    }
350
368
                    else
351
369
                    {
352
 
                        (*_texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
 
370
                        (*texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
353
371
                    }
354
 
 
355
372
                }
356
373
 
357
 
                if (_elevations)
 
374
                if (elevations.valid())
358
375
                {
359
 
                    (*_elevations).push_back((ndc.z()-minHeight)*scaleHeight);
 
376
                    (*elevations).push_back((ndc.z()-minHeight)*scaleHeight);
360
377
                }
361
378
 
362
379
                // compute the local normal
363
 
                osg::Vec3d ndc_one( (double)i/(double)(numColumns-1), (double)j/(double)(numColumns-1), 1.0);
 
380
                osg::Vec3d ndc_one = ndc; ndc_one.z() += 1.0;
364
381
                osg::Vec3d model_one;
365
382
                masterLocator->convertLocalToModel(ndc_one, model_one);
366
383
                model_one = model_one - model;
367
384
                model_one.normalize();            
368
 
                (*_normals).push_back(model_one);
 
385
                (*normals).push_back(model_one);
369
386
            }
370
387
            else
371
388
            {
373
390
            }
374
391
        }
375
392
    }
376
 
 
 
393
    
377
394
    // populate primitive sets
378
 
//    bool optimizeOrientations = _elevations!=0;
 
395
//    bool optimizeOrientations = elevations!=0;
379
396
    bool swapOrientation = !(masterLocator->orientationOpenGL());
380
397
    
381
 
    osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLES);
 
398
    osg::ref_ptr<osg::DrawElementsUInt> elements = new osg::DrawElementsUInt(GL_TRIANGLES);
382
399
    elements->reserve((numRows-1) * (numColumns-1) * 6);
383
400
 
384
 
    if (buffer._geometry.valid()) buffer._geometry->addPrimitiveSet(elements);
 
401
    geometry->addPrimitiveSet(elements.get());
385
402
 
386
 
    for(unsigned int j=0; j<numRows-1; ++j)
 
403
    for(j=0; j<numRows-1; ++j)
387
404
    {
388
 
        for(unsigned int i=0; i<numColumns-1; ++i)
 
405
        for(i=0; i<numColumns-1; ++i)
389
406
        {
390
407
            int i00;
391
408
            int i01;
417
434
            
418
435
            if (numValid==4)
419
436
            {
420
 
                float e00 = (*_elevations)[i00];
421
 
                float e10 = (*_elevations)[i10];
422
 
                float e01 = (*_elevations)[i01];
423
 
                float e11 = (*_elevations)[i11];
 
437
                float e00 = (*elevations)[i00];
 
438
                float e10 = (*elevations)[i10];
 
439
                float e01 = (*elevations)[i01];
 
440
                float e11 = (*elevations)[i11];
424
441
 
425
442
                if (fabsf(e00-e11)<fabsf(e01-e10))
426
443
                {
454
471
        }
455
472
    }
456
473
    
457
 
    // if (_terrainGeometry.valid()) _terrainGeometry->setUseDisplayList(false);
458
 
    if (buffer._geometry.valid()) buffer._geometry->setUseVertexBufferObjects(true);
 
474
    osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*normals));
 
475
    
 
476
    if (elevationLayer)
 
477
    {
 
478
        smoothGeometry();
 
479
        
 
480
        normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
 
481
        
 
482
        if (!normals) createSkirt = false;
 
483
    }
 
484
 
 
485
    if (createSkirt)
 
486
    {
 
487
        osg::ref_ptr<osg::DrawElementsUShort> skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
488
 
 
489
        // create bottom skirt vertices
 
490
        int r,c;
 
491
        r=0;
 
492
        for(c=0;c<static_cast<int>(numColumns);++c)
 
493
        {
 
494
            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
 
495
            if (orig_i>=0)
 
496
            {
 
497
                unsigned int new_i = vertices->size(); // index of new index of added skirt point
 
498
                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
 
499
                (*vertices).push_back(new_v);
 
500
                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
 
501
 
 
502
                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
 
503
                    itr != layerToTexCoordMap.end();
 
504
                    ++itr)
 
505
                {
 
506
                    itr->second.first->push_back((*itr->second.first)[orig_i]);
 
507
                }
 
508
                
 
509
                skirtDrawElements->push_back(orig_i);
 
510
                skirtDrawElements->push_back(new_i);
 
511
            }
 
512
            else
 
513
            {
 
514
                if (!skirtDrawElements->empty())
 
515
                {
 
516
                    geometry->addPrimitiveSet(skirtDrawElements.get());
 
517
                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
518
                }
 
519
                
 
520
            }
 
521
        }
 
522
 
 
523
        if (!skirtDrawElements->empty())
 
524
        {
 
525
            geometry->addPrimitiveSet(skirtDrawElements.get());
 
526
            skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
527
        }
 
528
 
 
529
        // create right skirt vertices
 
530
        c=numColumns-1;
 
531
        for(r=0;r<static_cast<int>(numRows);++r)
 
532
        {
 
533
            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
 
534
            if (orig_i>=0)
 
535
            {
 
536
                unsigned int new_i = vertices->size(); // index of new index of added skirt point
 
537
                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
 
538
                (*vertices).push_back(new_v);
 
539
                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
 
540
                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
 
541
                    itr != layerToTexCoordMap.end();
 
542
                    ++itr)
 
543
                {
 
544
                    itr->second.first->push_back((*itr->second.first)[orig_i]);
 
545
                }
 
546
                
 
547
                skirtDrawElements->push_back(orig_i);
 
548
                skirtDrawElements->push_back(new_i);
 
549
            }
 
550
            else
 
551
            {
 
552
                if (!skirtDrawElements->empty())
 
553
                {
 
554
                    geometry->addPrimitiveSet(skirtDrawElements.get());
 
555
                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
556
                }
 
557
                
 
558
            }
 
559
        }
 
560
 
 
561
        if (!skirtDrawElements->empty())
 
562
        {
 
563
            geometry->addPrimitiveSet(skirtDrawElements.get());
 
564
            skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
565
        }
 
566
 
 
567
        // create top skirt vertices
 
568
        r=numRows-1;
 
569
        for(c=numColumns-1;c>=0;--c)
 
570
        {
 
571
            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
 
572
            if (orig_i>=0)
 
573
            {
 
574
                unsigned int new_i = vertices->size(); // index of new index of added skirt point
 
575
                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
 
576
                (*vertices).push_back(new_v);
 
577
                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
 
578
                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
 
579
                    itr != layerToTexCoordMap.end();
 
580
                    ++itr)
 
581
                {
 
582
                    itr->second.first->push_back((*itr->second.first)[orig_i]);
 
583
                }
 
584
                
 
585
                skirtDrawElements->push_back(orig_i);
 
586
                skirtDrawElements->push_back(new_i);
 
587
            }
 
588
            else
 
589
            {
 
590
                if (!skirtDrawElements->empty())
 
591
                {
 
592
                    geometry->addPrimitiveSet(skirtDrawElements.get());
 
593
                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
594
                }
 
595
                
 
596
            }
 
597
        }
 
598
 
 
599
        if (!skirtDrawElements->empty())
 
600
        {
 
601
            geometry->addPrimitiveSet(skirtDrawElements.get());
 
602
            skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
603
        }
 
604
 
 
605
        // create left skirt vertices
 
606
        c=0;
 
607
        for(r=numRows-1;r>=0;--r)
 
608
        {
 
609
            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
 
610
            if (orig_i>=0)
 
611
            {
 
612
                unsigned int new_i = vertices->size(); // index of new index of added skirt point
 
613
                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
 
614
                (*vertices).push_back(new_v);
 
615
                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
 
616
                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
 
617
                    itr != layerToTexCoordMap.end();
 
618
                    ++itr)
 
619
                {
 
620
                    itr->second.first->push_back((*itr->second.first)[orig_i]);
 
621
                }
 
622
                
 
623
                skirtDrawElements->push_back(orig_i);
 
624
                skirtDrawElements->push_back(new_i);
 
625
            }
 
626
            else
 
627
            {
 
628
                if (!skirtDrawElements->empty())
 
629
                {
 
630
                    geometry->addPrimitiveSet(skirtDrawElements.get());
 
631
                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
632
                }
 
633
                
 
634
            }
 
635
        }
 
636
 
 
637
        if (!skirtDrawElements->empty())
 
638
        {
 
639
            geometry->addPrimitiveSet(skirtDrawElements.get());
 
640
            skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
 
641
        }
 
642
    }
 
643
 
 
644
 
 
645
    //geometry->setUseDisplayList(false);
 
646
    geometry->setUseVertexBufferObjects(true);
459
647
}
460
648
 
461
649
void GeometryTechnique::applyColorLayers()
462
650
{
463
651
    BufferData& buffer = getWriteBuffer();
464
 
    
465
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
466
 
    osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
467
 
    osgTerrain::Terrain::Filter filter = _terrain->getColorFilter(0);
468
 
    
469
 
    osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
470
 
    
471
 
    int color_index = -1;
472
 
    
473
 
    if (colorLayer)
 
652
 
 
653
    typedef std::map<osgTerrain::Layer*, osg::Texture*> LayerToTextureMap;
 
654
    LayerToTextureMap layerToTextureMap;
 
655
    
 
656
    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
474
657
    {
475
 
        color_index++;
 
658
        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
 
659
        if (!colorLayer) continue;
 
660
 
 
661
        osg::Image* image = colorLayer->getImage();
 
662
        if (!image) continue;
 
663
 
476
664
        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
 
665
        osgTerrain::ContourLayer* contourLayer = dynamic_cast<osgTerrain::ContourLayer*>(colorLayer);
477
666
        if (imageLayer)
478
667
        {
479
 
            osg::Image* image = imageLayer->getImage();
480
 
            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
481
 
 
482
 
            osg::Texture2D* texture2D = new osg::Texture2D;
483
 
            texture2D->setImage(image);
484
 
            texture2D->setResizeNonPowerOfTwoHint(false);
485
 
            stateset->setTextureAttributeAndModes(color_index, texture2D, osg::StateAttribute::ON);
486
 
 
487
 
            texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
488
 
            texture2D->setFilter(osg::Texture::MAG_FILTER, filter==Terrain::LINEAR ? osg::Texture::LINEAR :  osg::Texture::NEAREST);
489
 
            
490
 
            if (tf)
491
 
            {
492
 
                // up the precision of hte internal texture format to its maximum.
493
 
                //image->setInternalTextureFormat(GL_LUMINANCE32F_ARB);
494
 
                image->setInternalTextureFormat(GL_LUMINANCE16);
495
 
            }
496
 
        }
497
 
    }
498
 
}
499
 
 
500
 
void GeometryTechnique::applyTransferFunctions()
501
 
{
502
 
    BufferData& buffer = getWriteBuffer();
503
 
    
504
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
505
 
    osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
506
 
    osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
507
 
    
508
 
    int color_index = -1;
509
 
    int tf_index = -1;
510
 
    
511
 
    if (colorLayer) {
512
 
        color_index++;
513
 
        tf_index++;
514
 
    }
515
 
    
516
 
    if (tf)
517
 
    {
518
 
        osg::notify(osg::INFO)<<"Requires TransferFunction"<<std::endl;
519
 
        tf_index++;
520
 
        osg::Image* image = tf->getImage();
521
 
        osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
522
 
        osg::Texture1D* texture1D = new osg::Texture1D;
523
 
        texture1D->setImage(image);
524
 
        texture1D->setResizeNonPowerOfTwoHint(false);
525
 
        texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
526
 
        texture1D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
527
 
        stateset->setTextureAttributeAndModes(tf_index, texture1D, osg::StateAttribute::ON);
528
 
 
529
 
        if (colorLayer)
530
 
        {
531
 
            osg::notify(osg::INFO)<<"Using fragment program"<<std::endl;
532
 
        
533
 
            osg::Program* program = new osg::Program;
534
 
            stateset->setAttribute(program);
535
 
 
536
 
            // get shaders from source
537
 
            std::string vertexShaderFile = osgDB::findDataFile("shaders/lookup.vert");
538
 
            if (!vertexShaderFile.empty())
539
 
            {
540
 
                program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, vertexShaderFile));
541
 
            }
542
 
            else
543
 
            {
544
 
                osg::notify(osg::INFO)<<"Not found lookup.vert"<<std::endl;
545
 
            }
546
 
 
547
 
            std::string fragmentShaderFile = osgDB::findDataFile("shaders/lookup.frag");
548
 
            if (!fragmentShaderFile.empty())
549
 
            {
550
 
                program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, fragmentShaderFile));
551
 
            }
552
 
            else
553
 
            {
554
 
                osg::notify(osg::INFO)<<"Not found lookup.frag"<<std::endl;
555
 
            }
556
 
 
557
 
            osg::Uniform* sourceSampler = new osg::Uniform("sourceTexture",color_index);
558
 
            stateset->addUniform(sourceSampler);
559
 
 
560
 
            osg::Uniform* lookupTexture = new osg::Uniform("lookupTexture",tf_index);
561
 
            stateset->addUniform(lookupTexture);
562
 
 
563
 
            stateset->addUniform(_filterWidthUniform.get());
564
 
            stateset->addUniform(_filterMatrixUniform.get());
565
 
            stateset->addUniform(_filterBiasUniform.get());
566
 
 
567
 
            osg::Uniform* lightingEnabled = new osg::Uniform("lightingEnabled",true);
568
 
            stateset->addUniform(lightingEnabled);
569
 
 
570
 
            osg::Uniform* minValue = new osg::Uniform("minValue", tf->getMinimum());
571
 
            stateset->addUniform(minValue);
572
 
 
573
 
            osg::Uniform* inverseRange = new osg::Uniform("inverseRange", 1.0f/(tf->getMaximum()-tf->getMinimum()));
574
 
            stateset->addUniform(inverseRange);
575
 
        }
576
 
        else
577
 
        {
578
 
            osg::notify(osg::INFO)<<"Using standard OpenGL fixed function pipeline"<<std::endl;
 
668
            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
 
669
 
 
670
            osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(layerToTextureMap[colorLayer]);
 
671
            if (!texture2D)
 
672
            {
 
673
                texture2D = new osg::Texture2D;
 
674
                texture2D->setImage(image);
 
675
                texture2D->setMaxAnisotropy(16.0f);
 
676
                texture2D->setResizeNonPowerOfTwoHint(false);
 
677
                texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
 
678
                texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getFilter()==Layer::LINEAR ? osg::Texture::LINEAR :  osg::Texture::NEAREST);
 
679
                texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
 
680
                texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
 
681
 
 
682
                layerToTextureMap[colorLayer] = texture2D;
 
683
 
 
684
                // osg::notify(osg::NOTICE)<<"Creating new ImageLayer texture "<<layerNum<<std::endl;
 
685
 
 
686
            }
 
687
            else
 
688
            {
 
689
                // osg::notify(osg::NOTICE)<<"Reusing ImageLayer texture "<<layerNum<<std::endl;
 
690
            }
 
691
 
 
692
            stateset->setTextureAttributeAndModes(layerNum, texture2D, osg::StateAttribute::ON);
 
693
            
 
694
        }
 
695
        else if (contourLayer)
 
696
        {
 
697
            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
 
698
 
 
699
            osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(layerToTextureMap[colorLayer]);
 
700
            if (!texture1D)
 
701
            {
 
702
                texture1D = new osg::Texture1D;
 
703
                texture1D->setImage(image);
 
704
                texture1D->setResizeNonPowerOfTwoHint(false);
 
705
                texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
 
706
                texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getFilter()==Layer::LINEAR ? osg::Texture::LINEAR :  osg::Texture::NEAREST);
 
707
 
 
708
                layerToTextureMap[colorLayer] = texture1D;
 
709
            }
 
710
            
 
711
            stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON);
 
712
 
579
713
        }
580
714
    }
581
715
}
584
718
{
585
719
    BufferData& buffer = getWriteBuffer();
586
720
    
587
 
    osgTerrain::Layer* elevationLayer = _terrain->getElevationLayer();
588
 
    osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
589
 
    osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
590
 
 
591
 
    // if the elevationLayer and colorLayer are the same, and there is colorTF then
592
 
    // simply assing as a texture coordinate.
593
 
    if ((elevationLayer==colorLayer) && colorTF) colorLayer = 0;
594
 
    
595
721
    bool containsTransparency = false;
596
 
    
597
 
    if (colorLayer)
 
722
    for(unsigned int i=0; i<_terrainTile->getNumColorLayers(); ++i)
598
723
    {
599
 
        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
600
 
        if (imageLayer) {
601
 
            osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
602
 
            if (tf) containsTransparency = tf->getImage()->isImageTranslucent();
603
 
            else containsTransparency = imageLayer->getImage()->isImageTranslucent();
604
 
        }  
 
724
        osg::Image* image = _terrainTile->getColorLayer(i)->getImage();
 
725
        if (image)
 
726
        {
 
727
            containsTransparency = image->isImageTranslucent();
 
728
            break;
 
729
        }        
605
730
    }
606
731
    
607
732
    if (containsTransparency)
626
751
 
627
752
void GeometryTechnique::update(osgUtil::UpdateVisitor* uv)
628
753
{
629
 
    if (_terrain) _terrain->osg::Group::traverse(*uv);
 
754
    if (_terrainTile) _terrainTile->osg::Group::traverse(*uv);
630
755
}
631
756
 
632
757
 
635
760
    BufferData& buffer = getReadOnlyBuffer();
636
761
 
637
762
#if 0
638
 
    if (buffer._terrain) buffer._terrain->osg::Group::traverse(*cv);
 
763
    if (buffer._terrainTile) buffer._terrainTile->osg::Group::traverse(*cv);
639
764
#else
640
765
    if (buffer._transform.valid())
641
766
    {
647
772
 
648
773
void GeometryTechnique::traverse(osg::NodeVisitor& nv)
649
774
{
650
 
    if (!_terrain) return;
 
775
    if (!_terrainTile) return;
651
776
 
652
777
    // if app traversal update the frame count.
653
778
    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
654
779
    {
655
 
        if (_dirty) init();
 
780
        if (_dirty) _terrainTile->init();
656
781
 
657
782
        osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
658
783
        if (uv)
676
801
    if (_dirty) 
677
802
    {
678
803
        osg::notify(osg::INFO)<<"******* Doing init ***********"<<std::endl;
679
 
        init();
 
804
        _terrainTile->init();
680
805
    }
681
806
 
682
807
    BufferData& buffer = getReadOnlyBuffer();