238
229
numRows = elevationLayer->getNumRows();
241
bool treatBoundariesToValidDataAsDefaultValue = _terrain->getTreatBoundariesToValidDataAsDefaultValue();
232
float sampleRatio = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getSampleRatio() : 1.0f;
234
double i_sampleFactor = 1.0;
235
double j_sampleFactor = 1.0;
237
if (sampleRatio!=1.0f)
240
unsigned int originalNumColumns = numColumns;
241
unsigned int originalNumRows = numRows;
243
numColumns = std::max((unsigned int) (float(originalNumColumns)*sqrtf(sampleRatio)), 4u);
244
numRows = std::max((unsigned int) (float(originalNumRows)*sqrtf(sampleRatio)),4u);
246
i_sampleFactor = double(originalNumColumns-1)/double(numColumns-1);
247
j_sampleFactor = double(originalNumRows-1)/double(numRows-1);
252
bool treatBoundariesToValidDataAsDefaultValue = _terrainTile->getTreatBoundariesToValidDataAsDefaultValue();
242
253
osg::notify(osg::INFO)<<"TreatBoundariesToValidDataAsDefaultValue="<<treatBoundariesToValidDataAsDefaultValue<<std::endl;
244
unsigned int numVertices = numRows * numColumns;
255
float skirtHeight = 0.0f;
256
HeightFieldLayer* hfl = dynamic_cast<HeightFieldLayer*>(elevationLayer);
257
if (hfl && hfl->getHeightField())
259
skirtHeight = hfl->getHeightField()->getSkirtHeight();
262
bool createSkirt = skirtHeight != 0.0f;
264
unsigned int numVerticesInBody = numColumns*numRows;
265
unsigned int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
266
unsigned int numVertices = numVerticesInBody+numVerticesInSkirt;
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());
250
273
// allocate and assign normals
251
osg::Vec3Array* _normals = new osg::Vec3Array;
252
if (buffer._geometry.valid())
254
buffer._geometry->setNormalArray(_normals);
255
buffer._geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
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);
258
int texcoord_index = 0;
259
int color_index = -1;
262
280
float minHeight = 0.0;
263
281
float scaleHeight = 1.0;
265
283
// allocate and assign tex coords
266
osg::Vec2Array* _texcoords = 0;
269
color_index = texcoord_index;
272
_texcoords = new osg::Vec2Array;
274
if (buffer._geometry.valid()) buffer._geometry->setTexCoordArray(color_index, _texcoords);
277
osg::FloatArray* _elevations = new osg::FloatArray;
278
osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
281
tf_index = texcoord_index;
284
typedef std::pair< osg::ref_ptr<osg::Vec2Array>, Locator* > TexCoordLocatorPair;
285
typedef std::map< Layer*, TexCoordLocatorPair > LayerToTexCoordMap;
287
LayerToTexCoordMap layerToTexCoordMap;
288
for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
290
osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
286
// _elevations = new osg::FloatArray(numVertices);
287
if (buffer._geometry.valid()) buffer._geometry->setTexCoordArray(tf_index, _elevations);
289
minHeight = tf->getMinimum();
290
scaleHeight = 1.0f/(tf->getMaximum()-tf->getMinimum());
293
LayerToTexCoordMap::iterator itr = layerToTexCoordMap.find(colorLayer);
294
if (itr!=layerToTexCoordMap.end())
296
geometry->setTexCoordArray(layerNum, itr->second.first.get());
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());
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);
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);
303
if (buffer._geometry.valid())
305
buffer._geometry->setColorArray(_colors);
306
buffer._geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
317
geometry->setColorArray(colors.get());
318
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
310
321
typedef std::vector<int> Indices;
311
Indices indices(numColumns*numRows, -1);
322
Indices indices(numVertices, -1);
313
324
// populate vertex and tex coord arrays
315
326
for(j=0; j<numRows; ++j)
317
for(unsigned int i=0; i<numColumns; ++i)
328
for(i=0; i<numColumns; ++i)
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;
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);
325
339
if (elevationLayer)
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;
335
indices[iv] = _vertices->size();
349
indices[iv] = vertices->size();
337
351
osg::Vec3d model;
338
352
masterLocator->convertLocalToModel(ndc, model);
340
(*_vertices).push_back(model - centerModel);
354
(*vertices).push_back(model - centerModel);
356
for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
357
itr != layerToTexCoordMap.end();
344
if (colorLocator!= masterLocator)
360
osg::Vec2Array* texcoords = itr->second.first.get();
361
Locator* colorLocator = itr->second.second;
362
if (colorLocator != masterLocator)
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()));
352
(*_texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
370
(*texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
374
if (elevations.valid())
359
(*_elevations).push_back((ndc.z()-minHeight)*scaleHeight);
376
(*elevations).push_back((ndc.z()-minHeight)*scaleHeight);
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);
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));
480
normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
482
if (!normals) createSkirt = false;
487
osg::ref_ptr<osg::DrawElementsUShort> skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
489
// create bottom skirt vertices
492
for(c=0;c<static_cast<int>(numColumns);++c)
494
int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
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]);
502
for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
503
itr != layerToTexCoordMap.end();
506
itr->second.first->push_back((*itr->second.first)[orig_i]);
509
skirtDrawElements->push_back(orig_i);
510
skirtDrawElements->push_back(new_i);
514
if (!skirtDrawElements->empty())
516
geometry->addPrimitiveSet(skirtDrawElements.get());
517
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
523
if (!skirtDrawElements->empty())
525
geometry->addPrimitiveSet(skirtDrawElements.get());
526
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
529
// create right skirt vertices
531
for(r=0;r<static_cast<int>(numRows);++r)
533
int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
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();
544
itr->second.first->push_back((*itr->second.first)[orig_i]);
547
skirtDrawElements->push_back(orig_i);
548
skirtDrawElements->push_back(new_i);
552
if (!skirtDrawElements->empty())
554
geometry->addPrimitiveSet(skirtDrawElements.get());
555
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
561
if (!skirtDrawElements->empty())
563
geometry->addPrimitiveSet(skirtDrawElements.get());
564
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
567
// create top skirt vertices
569
for(c=numColumns-1;c>=0;--c)
571
int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
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();
582
itr->second.first->push_back((*itr->second.first)[orig_i]);
585
skirtDrawElements->push_back(orig_i);
586
skirtDrawElements->push_back(new_i);
590
if (!skirtDrawElements->empty())
592
geometry->addPrimitiveSet(skirtDrawElements.get());
593
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
599
if (!skirtDrawElements->empty())
601
geometry->addPrimitiveSet(skirtDrawElements.get());
602
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
605
// create left skirt vertices
607
for(r=numRows-1;r>=0;--r)
609
int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
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();
620
itr->second.first->push_back((*itr->second.first)[orig_i]);
623
skirtDrawElements->push_back(orig_i);
624
skirtDrawElements->push_back(new_i);
628
if (!skirtDrawElements->empty())
630
geometry->addPrimitiveSet(skirtDrawElements.get());
631
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
637
if (!skirtDrawElements->empty())
639
geometry->addPrimitiveSet(skirtDrawElements.get());
640
skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
645
//geometry->setUseDisplayList(false);
646
geometry->setUseVertexBufferObjects(true);
461
649
void GeometryTechnique::applyColorLayers()
463
651
BufferData& buffer = getWriteBuffer();
465
osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
466
osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
467
osgTerrain::Terrain::Filter filter = _terrain->getColorFilter(0);
469
osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
471
int color_index = -1;
653
typedef std::map<osgTerrain::Layer*, osg::Texture*> LayerToTextureMap;
654
LayerToTextureMap layerToTextureMap;
656
for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
658
osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
659
if (!colorLayer) continue;
661
osg::Image* image = colorLayer->getImage();
662
if (!image) continue;
476
664
osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
665
osgTerrain::ContourLayer* contourLayer = dynamic_cast<osgTerrain::ContourLayer*>(colorLayer);
479
osg::Image* image = imageLayer->getImage();
480
osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
482
osg::Texture2D* texture2D = new osg::Texture2D;
483
texture2D->setImage(image);
484
texture2D->setResizeNonPowerOfTwoHint(false);
485
stateset->setTextureAttributeAndModes(color_index, texture2D, osg::StateAttribute::ON);
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);
492
// up the precision of hte internal texture format to its maximum.
493
//image->setInternalTextureFormat(GL_LUMINANCE32F_ARB);
494
image->setInternalTextureFormat(GL_LUMINANCE16);
500
void GeometryTechnique::applyTransferFunctions()
502
BufferData& buffer = getWriteBuffer();
504
osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0);
505
osg::TransferFunction* colorTF = _terrain->getColorTransferFunction(0);
506
osg::TransferFunction1D* tf = dynamic_cast<osg::TransferFunction1D*>(colorTF);
508
int color_index = -1;
518
osg::notify(osg::INFO)<<"Requires TransferFunction"<<std::endl;
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);
531
osg::notify(osg::INFO)<<"Using fragment program"<<std::endl;
533
osg::Program* program = new osg::Program;
534
stateset->setAttribute(program);
536
// get shaders from source
537
std::string vertexShaderFile = osgDB::findDataFile("shaders/lookup.vert");
538
if (!vertexShaderFile.empty())
540
program->addShader(osg::Shader::readShaderFile(osg::Shader::VERTEX, vertexShaderFile));
544
osg::notify(osg::INFO)<<"Not found lookup.vert"<<std::endl;
547
std::string fragmentShaderFile = osgDB::findDataFile("shaders/lookup.frag");
548
if (!fragmentShaderFile.empty())
550
program->addShader(osg::Shader::readShaderFile(osg::Shader::FRAGMENT, fragmentShaderFile));
554
osg::notify(osg::INFO)<<"Not found lookup.frag"<<std::endl;
557
osg::Uniform* sourceSampler = new osg::Uniform("sourceTexture",color_index);
558
stateset->addUniform(sourceSampler);
560
osg::Uniform* lookupTexture = new osg::Uniform("lookupTexture",tf_index);
561
stateset->addUniform(lookupTexture);
563
stateset->addUniform(_filterWidthUniform.get());
564
stateset->addUniform(_filterMatrixUniform.get());
565
stateset->addUniform(_filterBiasUniform.get());
567
osg::Uniform* lightingEnabled = new osg::Uniform("lightingEnabled",true);
568
stateset->addUniform(lightingEnabled);
570
osg::Uniform* minValue = new osg::Uniform("minValue", tf->getMinimum());
571
stateset->addUniform(minValue);
573
osg::Uniform* inverseRange = new osg::Uniform("inverseRange", 1.0f/(tf->getMaximum()-tf->getMinimum()));
574
stateset->addUniform(inverseRange);
578
osg::notify(osg::INFO)<<"Using standard OpenGL fixed function pipeline"<<std::endl;
668
osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
670
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(layerToTextureMap[colorLayer]);
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);
682
layerToTextureMap[colorLayer] = texture2D;
684
// osg::notify(osg::NOTICE)<<"Creating new ImageLayer texture "<<layerNum<<std::endl;
689
// osg::notify(osg::NOTICE)<<"Reusing ImageLayer texture "<<layerNum<<std::endl;
692
stateset->setTextureAttributeAndModes(layerNum, texture2D, osg::StateAttribute::ON);
695
else if (contourLayer)
697
osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
699
osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(layerToTextureMap[colorLayer]);
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);
708
layerToTextureMap[colorLayer] = texture1D;
711
stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON);