root/OpenSceneGraph/trunk/src/osgTerrain/GeometryTechnique.cpp @ 11287

Revision 11287, 32.9 kB (checked in by robert, 5 years ago)

Introduced the use of linear interpolation of evelvations when sampling

Line 
1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgTerrain/GeometryTechnique>
15#include <osgTerrain/TerrainTile>
16#include <osgTerrain/Terrain>
17
18#include <osgUtil/SmoothingVisitor>
19#include <osgUtil/MeshOptimizers>
20
21#include <osgDB/FileUtils>
22
23#include <osg/io_utils>
24#include <osg/Texture2D>
25#include <osg/Texture1D>
26#include <osg/TexEnvCombine>
27#include <osg/Program>
28#include <osg/Math>
29#include <osg/Timer>
30
31using namespace osgTerrain;
32
33#define NEW_COORD_CODE
34
35GeometryTechnique::GeometryTechnique():
36    _currentReadOnlyBuffer(1),
37    _currentWriteBuffer(0)
38   
39{
40    setFilterBias(0);
41    setFilterWidth(0.1);
42    setFilterMatrixAs(GAUSSIAN);
43   
44}
45
46GeometryTechnique::GeometryTechnique(const GeometryTechnique& gt,const osg::CopyOp& copyop):
47    TerrainTechnique(gt,copyop),
48    _currentReadOnlyBuffer(1),
49    _currentWriteBuffer(0)
50{
51    setFilterBias(gt._filterBias);
52    setFilterWidth(gt._filterWidth);
53    setFilterMatrix(gt._filterMatrix);
54}
55
56GeometryTechnique::~GeometryTechnique()
57{
58}
59
60void GeometryTechnique::swapBuffers()
61{
62    std::swap(_currentReadOnlyBuffer,_currentWriteBuffer);
63}
64
65void GeometryTechnique::setFilterBias(float filterBias)
66{
67    _filterBias = filterBias;
68    if (!_filterBiasUniform) _filterBiasUniform = new osg::Uniform("filterBias",_filterBias);
69    else _filterBiasUniform->set(filterBias);
70}
71
72void GeometryTechnique::setFilterWidth(float filterWidth)
73{
74    _filterWidth = filterWidth;
75    if (!_filterWidthUniform) _filterWidthUniform = new osg::Uniform("filterWidth",_filterWidth);
76    else _filterWidthUniform->set(filterWidth);
77}
78
79void GeometryTechnique::setFilterMatrix(const osg::Matrix3& matrix)
80{
81    _filterMatrix = matrix;
82    if (!_filterMatrixUniform) _filterMatrixUniform = new osg::Uniform("filterMatrix",_filterMatrix);
83    else _filterMatrixUniform->set(_filterMatrix);
84}
85
86void GeometryTechnique::setFilterMatrixAs(FilterType filterType)
87{
88    switch(filterType)
89    {
90        case(SMOOTH):
91            setFilterMatrix(osg::Matrix3(0.0, 0.5/2.5, 0.0,
92                                         0.5/2.5, 0.5/2.5, 0.5/2.5,
93                                         0.0, 0.5/2.5, 0.0));
94            break;
95        case(GAUSSIAN):
96            setFilterMatrix(osg::Matrix3(0.0, 1.0/8.0, 0.0,
97                                         1.0/8.0, 4.0/8.0, 1.0/8.0,
98                                         0.0, 1.0/8.0, 0.0));
99            break;
100        case(SHARPEN):
101            setFilterMatrix(osg::Matrix3(0.0, -1.0, 0.0,
102                                         -1.0, 5.0, -1.0,
103                                         0.0, -1.0, 0.0));
104            break;
105
106    };
107}
108
109void GeometryTechnique::init()
110{
111    OSG_INFO<<"Doing GeometryTechnique::init()"<<std::endl;
112   
113    if (!_terrainTile) return;
114
115    BufferData& buffer = getWriteBuffer();
116
117    Locator* masterLocator = computeMasterLocator();
118
119    osg::Vec3d centerModel = computeCenterModel(masterLocator);
120
121    generateGeometry(masterLocator, centerModel);
122
123    applyColorLayers();
124
125    applyTransparency();
126
127    // smoothGeometry();
128
129    if (buffer._transform.valid()) buffer._transform->setThreadSafeRefUnref(true);
130
131    swapBuffers();
132}
133
134Locator* GeometryTechnique::computeMasterLocator()
135{
136    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
137    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
138
139    Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0;
140    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
141   
142    Locator* masterLocator = elevationLocator ? elevationLocator : colorLocator;
143    if (!masterLocator)
144    {
145        OSG_NOTICE<<"Problem, no locator found in any of the terrain layers"<<std::endl;
146        return 0;
147    }
148   
149    return masterLocator;
150}
151
152osg::Vec3d GeometryTechnique::computeCenterModel(Locator* masterLocator)
153{
154    if (!masterLocator) return osg::Vec3d(0.0,0.0,0.0);
155
156    BufferData& buffer = getWriteBuffer();
157   
158    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
159    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
160
161    Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0;
162    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
163   
164    if (!elevationLocator) elevationLocator = masterLocator;
165    if (!colorLocator) colorLocator = masterLocator;
166
167    osg::Vec3d bottomLeftNDC(DBL_MAX, DBL_MAX, 0.0);
168    osg::Vec3d topRightNDC(-DBL_MAX, -DBL_MAX, 0.0);
169   
170    if (elevationLayer)
171    {
172        if (elevationLocator!= masterLocator)
173        {
174            masterLocator->computeLocalBounds(*elevationLocator, bottomLeftNDC, topRightNDC);
175        }
176        else
177        {
178            bottomLeftNDC.x() = osg::minimum(bottomLeftNDC.x(), 0.0);
179            bottomLeftNDC.y() = osg::minimum(bottomLeftNDC.y(), 0.0);
180            topRightNDC.x() = osg::maximum(topRightNDC.x(), 1.0);
181            topRightNDC.y() = osg::maximum(topRightNDC.y(), 1.0);
182        }
183    }
184
185    if (colorLayer)
186    {
187        if (colorLocator!= masterLocator)
188        {
189            masterLocator->computeLocalBounds(*colorLocator, bottomLeftNDC, topRightNDC);
190        }
191        else
192        {
193            bottomLeftNDC.x() = osg::minimum(bottomLeftNDC.x(), 0.0);
194            bottomLeftNDC.y() = osg::minimum(bottomLeftNDC.y(), 0.0);
195            topRightNDC.x() = osg::maximum(topRightNDC.x(), 1.0);
196            topRightNDC.y() = osg::maximum(topRightNDC.y(), 1.0);
197        }
198    }
199
200    OSG_INFO<<"bottomLeftNDC = "<<bottomLeftNDC<<std::endl;
201    OSG_INFO<<"topRightNDC = "<<topRightNDC<<std::endl;
202
203    buffer._transform = new osg::MatrixTransform;
204
205    osg::Vec3d centerNDC = (bottomLeftNDC + topRightNDC)*0.5;
206    osg::Vec3d centerModel = (bottomLeftNDC + topRightNDC)*0.5;
207    masterLocator->convertLocalToModel(centerNDC, centerModel);
208   
209    buffer._transform->setMatrix(osg::Matrix::translate(centerModel));
210   
211    return centerModel;
212}
213
214void GeometryTechnique::generateGeometry(Locator* masterLocator, const osg::Vec3d& centerModel)
215{
216    BufferData& buffer = getWriteBuffer();
217   
218    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
219
220    buffer._geode = new osg::Geode;
221    if(buffer._transform.valid())
222        buffer._transform->addChild(buffer._geode.get());
223   
224    buffer._geometry = new osg::Geometry;
225    buffer._geode->addDrawable(buffer._geometry.get());
226       
227    osg::Geometry* geometry = buffer._geometry.get();
228
229    unsigned int numRows = 20;
230    unsigned int numColumns = 20;
231   
232    if (elevationLayer)
233    {
234        numColumns = elevationLayer->getNumColumns();
235        numRows = elevationLayer->getNumRows();
236    }
237   
238    float sampleRatio = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getSampleRatio() : 1.0f;
239   
240    double i_sampleFactor = 1.0;
241    double j_sampleFactor = 1.0;
242
243    // OSG_NOTICE<<"Sample ratio="<<sampleRatio<<std::endl;
244
245    unsigned int minimumNumColumns = 16u;
246    unsigned int minimumNumRows = 16u;
247
248    if ((sampleRatio!=1.0f) && (numColumns>minimumNumColumns) && (numRows>minimumNumRows))
249    {
250        unsigned int originalNumColumns = numColumns;
251        unsigned int originalNumRows = numRows;
252   
253        numColumns = std::max((unsigned int) (float(originalNumColumns)*sqrtf(sampleRatio)), minimumNumColumns);
254        numRows = std::max((unsigned int) (float(originalNumRows)*sqrtf(sampleRatio)),minimumNumRows);
255
256        i_sampleFactor = double(originalNumColumns-1)/double(numColumns-1);
257        j_sampleFactor = double(originalNumRows-1)/double(numRows-1);
258    }
259   
260   
261
262    bool treatBoundariesToValidDataAsDefaultValue = _terrainTile->getTreatBoundariesToValidDataAsDefaultValue();
263    OSG_INFO<<"TreatBoundariesToValidDataAsDefaultValue="<<treatBoundariesToValidDataAsDefaultValue<<std::endl;
264   
265    float skirtHeight = 0.0f;
266    HeightFieldLayer* hfl = dynamic_cast<HeightFieldLayer*>(elevationLayer);
267    if (hfl && hfl->getHeightField())
268    {
269        skirtHeight = hfl->getHeightField()->getSkirtHeight();
270    }
271   
272    bool createSkirt = skirtHeight != 0.0f;
273 
274    unsigned int numVerticesInBody = numColumns*numRows;
275    unsigned int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0;
276    unsigned int numVertices = numVerticesInBody+numVerticesInSkirt;
277
278    // allocate and assign vertices
279    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
280    vertices->reserve(numVertices);
281    geometry->setVertexArray(vertices.get());
282
283    // allocate and assign normals
284    osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
285    if (normals.valid()) normals->reserve(numVertices);
286    geometry->setNormalArray(normals.get());
287    geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
288   
289
290    //float minHeight = 0.0;
291    float scaleHeight = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getVerticalScale() : 1.0f;
292
293    // allocate and assign tex coords
294    typedef std::pair< osg::ref_ptr<osg::Vec2Array>, Locator* > TexCoordLocatorPair;
295    typedef std::map< Layer*, TexCoordLocatorPair > LayerToTexCoordMap;
296
297    LayerToTexCoordMap layerToTexCoordMap;
298    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
299    {
300        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
301        if (colorLayer)
302        {
303            LayerToTexCoordMap::iterator itr = layerToTexCoordMap.find(colorLayer);
304            if (itr!=layerToTexCoordMap.end())
305            {
306                geometry->setTexCoordArray(layerNum, itr->second.first.get());
307            }
308            else
309            {
310
311                Locator* locator = colorLayer->getLocator();
312                if (!locator)
313                {
314                    osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(colorLayer);
315                    if (switchLayer)
316                    {
317                        if (switchLayer->getActiveLayer()>=0 &&
318                            static_cast<unsigned int>(switchLayer->getActiveLayer())<switchLayer->getNumLayers() &&
319                            switchLayer->getLayer(switchLayer->getActiveLayer()))
320                        {
321                            locator = switchLayer->getLayer(switchLayer->getActiveLayer())->getLocator();
322                        }
323                    }
324                }
325
326                TexCoordLocatorPair& tclp = layerToTexCoordMap[colorLayer];
327                tclp.first = new osg::Vec2Array;
328                tclp.first->reserve(numVertices);
329                tclp.second = locator ? locator : masterLocator;
330                geometry->setTexCoordArray(layerNum, tclp.first.get());
331            }
332        }
333    }
334
335    osg::ref_ptr<osg::FloatArray> elevations = new osg::FloatArray;
336    if (elevations.valid()) elevations->reserve(numVertices);
337       
338
339    // allocate and assign color
340    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
341    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
342   
343    geometry->setColorArray(colors.get());
344    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
345
346
347    typedef std::vector<int> Indices;
348    Indices indices(numVertices, -1);
349   
350    // populate vertex and tex coord arrays
351    unsigned int i, j;
352    for(j=0; j<numRows; ++j)
353    {
354        for(i=0; i<numColumns; ++i)
355        {
356            unsigned int iv = j*numColumns + i;
357            osg::Vec3d ndc( ((double)i)/(double)(numColumns-1), ((double)j)/(double)(numRows-1), 0.0);
358
359            bool validValue = true;
360            if (elevationLayer)
361            {
362                float value = 0.0f;
363                if (sampleRatio==1.0) validValue = elevationLayer->getValidValue(i,j,value);
364                else validValue = elevationLayer->getInterpolatedValidValue(ndc.x(), ndc.y(), value);
365                ndc.z() = value*scaleHeight;
366            }
367
368            if (validValue)
369            {
370                indices[iv] = vertices->size();
371
372                osg::Vec3d model;
373                masterLocator->convertLocalToModel(ndc, model);
374
375                (*vertices).push_back(model - centerModel);
376
377                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
378                    itr != layerToTexCoordMap.end();
379                    ++itr)
380                {
381                    osg::Vec2Array* texcoords = itr->second.first.get();
382                    Locator* colorLocator = itr->second.second;
383                    if (colorLocator != masterLocator)
384                    {
385                        osg::Vec3d color_ndc;
386                        Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
387                        (*texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
388                    }
389                    else
390                    {
391                        (*texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
392                    }
393                }
394
395                if (elevations.valid())
396                {
397                    (*elevations).push_back(ndc.z());
398                }
399
400                // compute the local normal
401                osg::Vec3d ndc_one = ndc; ndc_one.z() += 1.0;
402                osg::Vec3d model_one;
403                masterLocator->convertLocalToModel(ndc_one, model_one);
404                model_one = model_one - model;
405                model_one.normalize();           
406                (*normals).push_back(model_one);
407            }
408            else
409            {
410                indices[iv] = -1;
411            }
412        }
413    }
414
415    // populate primitive sets
416//    bool optimizeOrientations = elevations!=0;
417    bool swapOrientation = !(masterLocator->orientationOpenGL());
418
419    bool smallTile = numVertices <= 16384;
420
421    // OSG_NOTICE<<"smallTile = "<<smallTile<<std::endl;
422   
423    osg::ref_ptr<osg::DrawElements> elements = smallTile ?
424        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_TRIANGLES)) :
425        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_TRIANGLES));
426       
427    elements->reserveElements((numRows-1) * (numColumns-1) * 6);
428
429    geometry->addPrimitiveSet(elements.get());
430
431    for(j=0; j<numRows-1; ++j)
432    {
433        for(i=0; i<numColumns-1; ++i)
434        {
435            int i00;
436            int i01;
437            if (swapOrientation)
438            {
439                i01 = j*numColumns + i;
440                i00 = i01+numColumns;
441            }
442            else
443            {
444                i00 = j*numColumns + i;
445                i01 = i00+numColumns;
446            }
447
448            int i10 = i00+1;
449            int i11 = i01+1;
450
451            // remap indices to final vertex positions
452            i00 = indices[i00];
453            i01 = indices[i01];
454            i10 = indices[i10];
455            i11 = indices[i11];
456           
457            unsigned int numValid = 0;
458            if (i00>=0) ++numValid;
459            if (i01>=0) ++numValid;
460            if (i10>=0) ++numValid;
461            if (i11>=0) ++numValid;
462           
463            if (numValid==4)
464            {
465                float e00 = (*elevations)[i00];
466                float e10 = (*elevations)[i10];
467                float e01 = (*elevations)[i01];
468                float e11 = (*elevations)[i11];
469
470                if (fabsf(e00-e11)<fabsf(e01-e10))
471                {
472                    elements->addElement(i01);
473                    elements->addElement(i00);
474                    elements->addElement(i11);
475
476                    elements->addElement(i00);
477                    elements->addElement(i10);
478                    elements->addElement(i11);
479                }
480                else
481                {
482                    elements->addElement(i01);
483                    elements->addElement(i00);
484                    elements->addElement(i10);
485
486                    elements->addElement(i01);
487                    elements->addElement(i10);
488                    elements->addElement(i11);
489                }
490            }
491            else if (numValid==3)
492            {
493                if (i00>=0) elements->addElement(i00);
494                if (i01>=0) elements->addElement(i01);
495                if (i11>=0) elements->addElement(i11);
496                if (i10>=0) elements->addElement(i10);
497            }
498           
499        }
500    }
501   
502    osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*normals));
503   
504    if (elevationLayer)
505    {
506        smoothGeometry();
507       
508        normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
509       
510        if (!normals) createSkirt = false;
511    }
512
513    if (createSkirt)
514    {
515        osg::ref_ptr<osg::DrawElements> skirtDrawElements = smallTile ?
516            static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
517            static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
518
519        // create bottom skirt vertices
520        int r,c;
521        r=0;
522        for(c=0;c<static_cast<int>(numColumns);++c)
523        {
524            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
525            if (orig_i>=0)
526            {
527                unsigned int new_i = vertices->size(); // index of new index of added skirt point
528                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
529                (*vertices).push_back(new_v);
530                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
531
532                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
533                    itr != layerToTexCoordMap.end();
534                    ++itr)
535                {
536                    itr->second.first->push_back((*itr->second.first)[orig_i]);
537                }
538               
539                skirtDrawElements->addElement(orig_i);
540                skirtDrawElements->addElement(new_i);
541            }
542            else
543            {
544                if (skirtDrawElements->getNumIndices()!=0)
545                {
546                    geometry->addPrimitiveSet(skirtDrawElements.get());
547                    skirtDrawElements = smallTile ?
548                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
549                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
550                }
551               
552            }
553        }
554
555        if (skirtDrawElements->getNumIndices()!=0)
556        {
557            geometry->addPrimitiveSet(skirtDrawElements.get());
558            skirtDrawElements = smallTile ?
559                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
560                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
561        }
562
563        // create right skirt vertices
564        c=numColumns-1;
565        for(r=0;r<static_cast<int>(numRows);++r)
566        {
567            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
568            if (orig_i>=0)
569            {
570                unsigned int new_i = vertices->size(); // index of new index of added skirt point
571                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
572                (*vertices).push_back(new_v);
573                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
574                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
575                    itr != layerToTexCoordMap.end();
576                    ++itr)
577                {
578                    itr->second.first->push_back((*itr->second.first)[orig_i]);
579                }
580               
581                skirtDrawElements->addElement(orig_i);
582                skirtDrawElements->addElement(new_i);
583            }
584            else
585            {
586                if (skirtDrawElements->getNumIndices()!=0)
587                {
588                    geometry->addPrimitiveSet(skirtDrawElements.get());
589                    skirtDrawElements = smallTile ?
590                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
591                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
592                }
593               
594            }
595        }
596
597        if (skirtDrawElements->getNumIndices()!=0)
598        {
599            geometry->addPrimitiveSet(skirtDrawElements.get());
600            skirtDrawElements = smallTile ?
601                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
602                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
603        }
604
605        // create top skirt vertices
606        r=numRows-1;
607        for(c=numColumns-1;c>=0;--c)
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->addElement(orig_i);
624                skirtDrawElements->addElement(new_i);
625            }
626            else
627            {
628                if (skirtDrawElements->getNumIndices()!=0)
629                {
630                    geometry->addPrimitiveSet(skirtDrawElements.get());
631                    skirtDrawElements = smallTile ?
632                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
633                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
634                }
635               
636            }
637        }
638
639        if (skirtDrawElements->getNumIndices()!=0)
640        {
641            geometry->addPrimitiveSet(skirtDrawElements.get());
642            skirtDrawElements = smallTile ?
643                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
644                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
645        }
646
647        // create left skirt vertices
648        c=0;
649        for(r=numRows-1;r>=0;--r)
650        {
651            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
652            if (orig_i>=0)
653            {
654                unsigned int new_i = vertices->size(); // index of new index of added skirt point
655                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
656                (*vertices).push_back(new_v);
657                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
658                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
659                    itr != layerToTexCoordMap.end();
660                    ++itr)
661                {
662                    itr->second.first->push_back((*itr->second.first)[orig_i]);
663                }
664               
665                skirtDrawElements->addElement(orig_i);
666                skirtDrawElements->addElement(new_i);
667            }
668            else
669            {
670                if (skirtDrawElements->getNumIndices()!=0)
671                {
672                    geometry->addPrimitiveSet(skirtDrawElements.get());
673                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
674                }
675               
676            }
677        }
678
679        if (skirtDrawElements->getNumIndices()!=0)
680        {
681            geometry->addPrimitiveSet(skirtDrawElements.get());
682            smallTile ?
683                static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
684                static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
685        }
686    }
687
688
689    geometry->setUseDisplayList(false);
690    geometry->setUseVertexBufferObjects(true);
691
692#if 0
693    {
694        osgUtil::VertexCacheMissVisitor vcmv_before;
695        osgUtil::VertexCacheMissVisitor vcmv_after;
696        osgUtil::VertexCacheVisitor vcv;
697        osgUtil::VertexAccessOrderVisitor vaov;
698
699        vcmv_before.doGeometry(*geometry);
700        vcv.optimizeVertices(*geometry);
701        vaov.optimizeOrder(*geometry);
702        vcmv_after.doGeometry(*geometry);
703#if 0
704        OSG_NOTICE<<"vcmv_before.triangles="<<vcmv_before.triangles<<std::endl;
705        OSG_NOTICE<<"vcmv_before.misses="<<vcmv_before.misses<<std::endl;
706        OSG_NOTICE<<"vcmv_after.misses="<<vcmv_after.misses<<std::endl;
707        OSG_NOTICE<<std::endl;
708#endif
709    }
710#endif
711
712    if (osgDB::Registry::instance()->getBuildKdTreesHint()==osgDB::ReaderWriter::Options::BUILD_KDTREES &&
713        osgDB::Registry::instance()->getKdTreeBuilder())
714    {
715
716        //osg::Timer_t before = osg::Timer::instance()->tick();
717        //OSG_NOTICE<<"osgTerrain::GeometryTechnique::build kd tree"<<std::endl;
718        osg::ref_ptr<osg::KdTreeBuilder> builder = osgDB::Registry::instance()->getKdTreeBuilder()->clone();
719        buffer._geode->accept(*builder);
720        //osg::Timer_t after = osg::Timer::instance()->tick();
721        //OSG_NOTICE<<"KdTree build time "<<osg::Timer::instance()->delta_m(before, after)<<std::endl;
722    }
723}
724
725void GeometryTechnique::applyColorLayers()
726{
727    BufferData& buffer = getWriteBuffer();
728
729    typedef std::map<osgTerrain::Layer*, osg::Texture*> LayerToTextureMap;
730    LayerToTextureMap layerToTextureMap;
731   
732    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
733    {
734        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
735        if (!colorLayer) continue;
736
737        osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(colorLayer);
738        if (switchLayer)
739        {
740            if (switchLayer->getActiveLayer()<0 ||
741                static_cast<unsigned int>(switchLayer->getActiveLayer())>=switchLayer->getNumLayers())
742            {
743                continue;
744            }
745
746            colorLayer = switchLayer->getLayer(switchLayer->getActiveLayer());
747            if (!colorLayer) continue;
748        }
749
750        osg::Image* image = colorLayer->getImage();
751        if (!image) continue;
752
753        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
754        osgTerrain::ContourLayer* contourLayer = dynamic_cast<osgTerrain::ContourLayer*>(colorLayer);
755        if (imageLayer)
756        {
757            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
758
759            osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(layerToTextureMap[colorLayer]);
760            if (!texture2D)
761            {
762                texture2D = new osg::Texture2D;
763                texture2D->setImage(image);
764                texture2D->setMaxAnisotropy(16.0f);
765                texture2D->setResizeNonPowerOfTwoHint(false);
766
767                texture2D->setFilter(osg::Texture::MIN_FILTER, colorLayer->getMinFilter());
768                texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
769
770                texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
771                texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
772
773                bool mipMapping = !(texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::LINEAR || texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::NEAREST);
774                bool s_NotPowerOfTwo = image->s()==0 || (image->s() & (image->s() - 1));
775                bool t_NotPowerOfTwo = image->t()==0 || (image->t() & (image->t() - 1));
776
777                if (mipMapping && (s_NotPowerOfTwo || t_NotPowerOfTwo))
778                {
779                    OSG_INFO<<"Disabling mipmapping for non power of two tile size("<<image->s()<<", "<<image->t()<<")"<<std::endl;
780                    texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
781                }
782
783
784                layerToTextureMap[colorLayer] = texture2D;
785
786                // OSG_NOTICE<<"Creating new ImageLayer texture "<<layerNum<<" image->s()="<<image->s()<<"  image->t()="<<image->t()<<std::endl;
787
788            }
789            else
790            {
791                // OSG_NOTICE<<"Reusing ImageLayer texture "<<layerNum<<std::endl;
792            }
793
794            stateset->setTextureAttributeAndModes(layerNum, texture2D, osg::StateAttribute::ON);
795           
796        }
797        else if (contourLayer)
798        {
799            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
800
801            osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(layerToTextureMap[colorLayer]);
802            if (!texture1D)
803            {
804                texture1D = new osg::Texture1D;
805                texture1D->setImage(image);
806                texture1D->setResizeNonPowerOfTwoHint(false);
807                texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
808                texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
809
810                layerToTextureMap[colorLayer] = texture1D;
811            }
812           
813            stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON);
814
815        }
816    }
817}
818
819void GeometryTechnique::applyTransparency()
820{
821    TerrainTile::BlendingPolicy blendingPolicy = _terrainTile->getBlendingPolicy();
822    if (blendingPolicy == TerrainTile::INHERIT && _terrainTile->getTerrain())
823    {
824        OSG_INFO<<"GeometryTechnique::applyTransparency() inheriting policy from Terrain"<<std::endl;
825        blendingPolicy = _terrainTile->getTerrain()->getBlendingPolicy();
826    }
827
828    if (blendingPolicy == TerrainTile::INHERIT)
829    {
830        OSG_INFO<<"GeometryTechnique::applyTransparency() policy is INHERIT, defaulting to ENABLE_BLENDING_WHEN_ALPHA_PRESENT"<<std::endl;
831        blendingPolicy = TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT;
832    }
833
834    if (blendingPolicy == TerrainTile::DO_NOT_SET_BLENDING)
835    {
836        OSG_INFO<<"blendingPolicy == TerrainTile::DO_NOT_SET_BLENDING"<<std::endl;
837        return;
838    }
839
840    bool enableBlending = false;
841
842    if (blendingPolicy == TerrainTile::ENABLE_BLENDING)
843    {
844        OSG_INFO<<"blendingPolicy == TerrainTile::ENABLE_BLENDING"<<std::endl;
845        enableBlending = true;
846    }
847    else if (blendingPolicy == TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT)
848    {
849        OSG_INFO<<"blendingPolicy == TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT"<<std::endl;
850        for(unsigned int i=0; i<_terrainTile->getNumColorLayers(); ++i)
851        {
852            osg::Image* image = (_terrainTile->getColorLayer(i)!=0) ? _terrainTile->getColorLayer(i)->getImage() : 0;
853            if (image)
854            {
855                enableBlending = image->isImageTranslucent();
856                break;
857            }
858        }
859    }
860
861    if (enableBlending)
862    {
863        BufferData& buffer = getWriteBuffer();
864        osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
865        stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
866        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
867    }
868
869}
870
871void GeometryTechnique::smoothGeometry()
872{
873    BufferData& buffer = getWriteBuffer();
874   
875    if (buffer._geometry.valid())
876    {
877        osgUtil::SmoothingVisitor smoother;
878        smoother.smooth(*buffer._geometry);
879    }
880}
881
882void GeometryTechnique::update(osgUtil::UpdateVisitor* uv)
883{
884    if (_terrainTile) _terrainTile->osg::Group::traverse(*uv);
885}
886
887
888void GeometryTechnique::cull(osgUtil::CullVisitor* cv)
889{
890    BufferData& buffer = getReadOnlyBuffer();
891
892#if 0
893    if (buffer._terrainTile) buffer._terrainTile->osg::Group::traverse(*cv);
894#else
895    if (buffer._transform.valid())
896    {
897        buffer._transform->accept(*cv);
898    }
899#endif   
900}
901
902
903void GeometryTechnique::traverse(osg::NodeVisitor& nv)
904{
905    if (!_terrainTile) return;
906
907    // if app traversal update the frame count.
908    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
909    {
910        if (_terrainTile->getDirty()) _terrainTile->init();
911
912        osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
913        if (uv)
914        {
915            update(uv);
916            return;
917        }       
918       
919    }
920    else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
921    {
922        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
923        if (cv)
924        {
925            cull(cv);
926            return;
927        }
928    }
929
930
931    if (_terrainTile->getDirty())
932    {
933        OSG_INFO<<"******* Doing init ***********"<<std::endl;
934        _terrainTile->init();
935    }
936
937    BufferData& buffer = getReadOnlyBuffer();
938    if (buffer._transform.valid()) buffer._transform->accept(nv);
939}
940
941
942void GeometryTechnique::cleanSceneGraph()
943{
944}
945
946void GeometryTechnique::releaseGLObjects(osg::State* state) const
947{
948    if (_bufferData[0]._transform.valid()) _bufferData[0]._transform->releaseGLObjects(state);
949    if (_bufferData[1]._transform.valid()) _bufferData[1]._transform->releaseGLObjects(state);   
950}
Note: See TracBrowser for help on using the browser.