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

Revision 11259, 33.2 kB (checked in by robert, 4 years ago)

Added a minimum tiles size of 16 to prevent down sampling from being overly aggressive.

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     
361           
362            unsigned int i_equiv = i_sampleFactor==1.0 ? i : (unsigned int) (double(i)*i_sampleFactor);
363            unsigned int j_equiv = i_sampleFactor==1.0 ? j : (unsigned int) (double(j)*j_sampleFactor);
364           
365            if (elevationLayer)
366            {
367                float value = 0.0f;
368                validValue = elevationLayer->getValidValue(i_equiv,j_equiv, value);
369                // OSG_INFO<<"i="<<i<<" j="<<j<<" z="<<value<<std::endl;
370                ndc.z() = value*scaleHeight;
371            }
372           
373            if (validValue)
374            {
375                indices[iv] = vertices->size();
376           
377                osg::Vec3d model;
378                masterLocator->convertLocalToModel(ndc, model);
379
380                (*vertices).push_back(model - centerModel);
381
382                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
383                    itr != layerToTexCoordMap.end();
384                    ++itr)
385                {
386                    osg::Vec2Array* texcoords = itr->second.first.get();
387                    Locator* colorLocator = itr->second.second;
388                    if (colorLocator != masterLocator)
389                    {
390                        osg::Vec3d color_ndc;
391                        Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
392                        (*texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
393                    }
394                    else
395                    {
396                        (*texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
397                    }
398                }
399
400                if (elevations.valid())
401                {
402                    (*elevations).push_back(ndc.z());
403                }
404
405                // compute the local normal
406                osg::Vec3d ndc_one = ndc; ndc_one.z() += 1.0;
407                osg::Vec3d model_one;
408                masterLocator->convertLocalToModel(ndc_one, model_one);
409                model_one = model_one - model;
410                model_one.normalize();           
411                (*normals).push_back(model_one);
412            }
413            else
414            {
415                indices[iv] = -1;
416            }
417        }
418    }
419   
420    // populate primitive sets
421//    bool optimizeOrientations = elevations!=0;
422    bool swapOrientation = !(masterLocator->orientationOpenGL());
423
424    bool smallTile = numVertices <= 16384;
425
426    // OSG_NOTICE<<"smallTile = "<<smallTile<<std::endl;
427   
428    osg::ref_ptr<osg::DrawElements> elements = smallTile ?
429        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_TRIANGLES)) :
430        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_TRIANGLES));
431       
432    elements->reserveElements((numRows-1) * (numColumns-1) * 6);
433
434    geometry->addPrimitiveSet(elements.get());
435
436    for(j=0; j<numRows-1; ++j)
437    {
438        for(i=0; i<numColumns-1; ++i)
439        {
440            int i00;
441            int i01;
442            if (swapOrientation)
443            {
444                i01 = j*numColumns + i;
445                i00 = i01+numColumns;
446            }
447            else
448            {
449                i00 = j*numColumns + i;
450                i01 = i00+numColumns;
451            }
452
453            int i10 = i00+1;
454            int i11 = i01+1;
455
456            // remap indices to final vertex positions
457            i00 = indices[i00];
458            i01 = indices[i01];
459            i10 = indices[i10];
460            i11 = indices[i11];
461           
462            unsigned int numValid = 0;
463            if (i00>=0) ++numValid;
464            if (i01>=0) ++numValid;
465            if (i10>=0) ++numValid;
466            if (i11>=0) ++numValid;
467           
468            if (numValid==4)
469            {
470                float e00 = (*elevations)[i00];
471                float e10 = (*elevations)[i10];
472                float e01 = (*elevations)[i01];
473                float e11 = (*elevations)[i11];
474
475                if (fabsf(e00-e11)<fabsf(e01-e10))
476                {
477                    elements->addElement(i01);
478                    elements->addElement(i00);
479                    elements->addElement(i11);
480
481                    elements->addElement(i00);
482                    elements->addElement(i10);
483                    elements->addElement(i11);
484                }
485                else
486                {
487                    elements->addElement(i01);
488                    elements->addElement(i00);
489                    elements->addElement(i10);
490
491                    elements->addElement(i01);
492                    elements->addElement(i10);
493                    elements->addElement(i11);
494                }
495            }
496            else if (numValid==3)
497            {
498                if (i00>=0) elements->addElement(i00);
499                if (i01>=0) elements->addElement(i01);
500                if (i11>=0) elements->addElement(i11);
501                if (i10>=0) elements->addElement(i10);
502            }
503           
504        }
505    }
506   
507    osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*normals));
508   
509    if (elevationLayer)
510    {
511        smoothGeometry();
512       
513        normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
514       
515        if (!normals) createSkirt = false;
516    }
517
518    if (createSkirt)
519    {
520        osg::ref_ptr<osg::DrawElements> skirtDrawElements = smallTile ?
521            static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
522            static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
523
524        // create bottom skirt vertices
525        int r,c;
526        r=0;
527        for(c=0;c<static_cast<int>(numColumns);++c)
528        {
529            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
530            if (orig_i>=0)
531            {
532                unsigned int new_i = vertices->size(); // index of new index of added skirt point
533                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
534                (*vertices).push_back(new_v);
535                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
536
537                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
538                    itr != layerToTexCoordMap.end();
539                    ++itr)
540                {
541                    itr->second.first->push_back((*itr->second.first)[orig_i]);
542                }
543               
544                skirtDrawElements->addElement(orig_i);
545                skirtDrawElements->addElement(new_i);
546            }
547            else
548            {
549                if (skirtDrawElements->getNumIndices()!=0)
550                {
551                    geometry->addPrimitiveSet(skirtDrawElements.get());
552                    skirtDrawElements = smallTile ?
553                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
554                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
555                }
556               
557            }
558        }
559
560        if (skirtDrawElements->getNumIndices()!=0)
561        {
562            geometry->addPrimitiveSet(skirtDrawElements.get());
563            skirtDrawElements = smallTile ?
564                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
565                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
566        }
567
568        // create right skirt vertices
569        c=numColumns-1;
570        for(r=0;r<static_cast<int>(numRows);++r)
571        {
572            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
573            if (orig_i>=0)
574            {
575                unsigned int new_i = vertices->size(); // index of new index of added skirt point
576                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
577                (*vertices).push_back(new_v);
578                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
579                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
580                    itr != layerToTexCoordMap.end();
581                    ++itr)
582                {
583                    itr->second.first->push_back((*itr->second.first)[orig_i]);
584                }
585               
586                skirtDrawElements->addElement(orig_i);
587                skirtDrawElements->addElement(new_i);
588            }
589            else
590            {
591                if (skirtDrawElements->getNumIndices()!=0)
592                {
593                    geometry->addPrimitiveSet(skirtDrawElements.get());
594                    skirtDrawElements = smallTile ?
595                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
596                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
597                }
598               
599            }
600        }
601
602        if (skirtDrawElements->getNumIndices()!=0)
603        {
604            geometry->addPrimitiveSet(skirtDrawElements.get());
605            skirtDrawElements = smallTile ?
606                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
607                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
608        }
609
610        // create top skirt vertices
611        r=numRows-1;
612        for(c=numColumns-1;c>=0;--c)
613        {
614            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
615            if (orig_i>=0)
616            {
617                unsigned int new_i = vertices->size(); // index of new index of added skirt point
618                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
619                (*vertices).push_back(new_v);
620                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
621                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
622                    itr != layerToTexCoordMap.end();
623                    ++itr)
624                {
625                    itr->second.first->push_back((*itr->second.first)[orig_i]);
626                }
627               
628                skirtDrawElements->addElement(orig_i);
629                skirtDrawElements->addElement(new_i);
630            }
631            else
632            {
633                if (skirtDrawElements->getNumIndices()!=0)
634                {
635                    geometry->addPrimitiveSet(skirtDrawElements.get());
636                    skirtDrawElements = smallTile ?
637                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
638                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
639                }
640               
641            }
642        }
643
644        if (skirtDrawElements->getNumIndices()!=0)
645        {
646            geometry->addPrimitiveSet(skirtDrawElements.get());
647            skirtDrawElements = smallTile ?
648                        static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
649                        static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
650        }
651
652        // create left skirt vertices
653        c=0;
654        for(r=numRows-1;r>=0;--r)
655        {
656            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
657            if (orig_i>=0)
658            {
659                unsigned int new_i = vertices->size(); // index of new index of added skirt point
660                osg::Vec3 new_v = (*vertices)[orig_i] - ((*skirtVectors)[orig_i])*skirtHeight;
661                (*vertices).push_back(new_v);
662                if (normals.valid()) (*normals).push_back((*normals)[orig_i]);
663                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
664                    itr != layerToTexCoordMap.end();
665                    ++itr)
666                {
667                    itr->second.first->push_back((*itr->second.first)[orig_i]);
668                }
669               
670                skirtDrawElements->addElement(orig_i);
671                skirtDrawElements->addElement(new_i);
672            }
673            else
674            {
675                if (skirtDrawElements->getNumIndices()!=0)
676                {
677                    geometry->addPrimitiveSet(skirtDrawElements.get());
678                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
679                }
680               
681            }
682        }
683
684        if (skirtDrawElements->getNumIndices()!=0)
685        {
686            geometry->addPrimitiveSet(skirtDrawElements.get());
687            smallTile ?
688                static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
689                static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
690        }
691    }
692
693
694    geometry->setUseDisplayList(false);
695    geometry->setUseVertexBufferObjects(true);
696
697#if 0
698    {
699        osgUtil::VertexCacheMissVisitor vcmv_before;
700        osgUtil::VertexCacheMissVisitor vcmv_after;
701        osgUtil::VertexCacheVisitor vcv;
702        osgUtil::VertexAccessOrderVisitor vaov;
703
704        vcmv_before.doGeometry(*geometry);
705        vcv.optimizeVertices(*geometry);
706        vaov.optimizeOrder(*geometry);
707        vcmv_after.doGeometry(*geometry);
708#if 0
709        OSG_NOTICE<<"vcmv_before.triangles="<<vcmv_before.triangles<<std::endl;
710        OSG_NOTICE<<"vcmv_before.misses="<<vcmv_before.misses<<std::endl;
711        OSG_NOTICE<<"vcmv_after.misses="<<vcmv_after.misses<<std::endl;
712        OSG_NOTICE<<std::endl;
713#endif
714    }
715#endif
716
717    if (osgDB::Registry::instance()->getBuildKdTreesHint()==osgDB::ReaderWriter::Options::BUILD_KDTREES &&
718        osgDB::Registry::instance()->getKdTreeBuilder())
719    {
720
721        //osg::Timer_t before = osg::Timer::instance()->tick();
722        //OSG_NOTICE<<"osgTerrain::GeometryTechnique::build kd tree"<<std::endl;
723        osg::ref_ptr<osg::KdTreeBuilder> builder = osgDB::Registry::instance()->getKdTreeBuilder()->clone();
724        buffer._geode->accept(*builder);
725        //osg::Timer_t after = osg::Timer::instance()->tick();
726        //OSG_NOTICE<<"KdTree build time "<<osg::Timer::instance()->delta_m(before, after)<<std::endl;
727    }
728}
729
730void GeometryTechnique::applyColorLayers()
731{
732    BufferData& buffer = getWriteBuffer();
733
734    typedef std::map<osgTerrain::Layer*, osg::Texture*> LayerToTextureMap;
735    LayerToTextureMap layerToTextureMap;
736   
737    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
738    {
739        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
740        if (!colorLayer) continue;
741
742        osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(colorLayer);
743        if (switchLayer)
744        {
745            if (switchLayer->getActiveLayer()<0 ||
746                static_cast<unsigned int>(switchLayer->getActiveLayer())>=switchLayer->getNumLayers())
747            {
748                continue;
749            }
750
751            colorLayer = switchLayer->getLayer(switchLayer->getActiveLayer());
752            if (!colorLayer) continue;
753        }
754
755        osg::Image* image = colorLayer->getImage();
756        if (!image) continue;
757
758        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
759        osgTerrain::ContourLayer* contourLayer = dynamic_cast<osgTerrain::ContourLayer*>(colorLayer);
760        if (imageLayer)
761        {
762            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
763
764            osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(layerToTextureMap[colorLayer]);
765            if (!texture2D)
766            {
767                texture2D = new osg::Texture2D;
768                texture2D->setImage(image);
769                texture2D->setMaxAnisotropy(16.0f);
770                texture2D->setResizeNonPowerOfTwoHint(false);
771
772                texture2D->setFilter(osg::Texture::MIN_FILTER, colorLayer->getMinFilter());
773                texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
774
775                texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
776                texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
777
778                bool mipMapping = !(texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::LINEAR || texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::NEAREST);
779                bool s_NotPowerOfTwo = image->s()==0 || (image->s() & (image->s() - 1));
780                bool t_NotPowerOfTwo = image->t()==0 || (image->t() & (image->t() - 1));
781
782                if (mipMapping && (s_NotPowerOfTwo || t_NotPowerOfTwo))
783                {
784                    OSG_INFO<<"Disabling mipmapping for non power of two tile size("<<image->s()<<", "<<image->t()<<")"<<std::endl;
785                    texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
786                }
787
788
789                layerToTextureMap[colorLayer] = texture2D;
790
791                // OSG_NOTICE<<"Creating new ImageLayer texture "<<layerNum<<" image->s()="<<image->s()<<"  image->t()="<<image->t()<<std::endl;
792
793            }
794            else
795            {
796                // OSG_NOTICE<<"Reusing ImageLayer texture "<<layerNum<<std::endl;
797            }
798
799            stateset->setTextureAttributeAndModes(layerNum, texture2D, osg::StateAttribute::ON);
800           
801        }
802        else if (contourLayer)
803        {
804            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
805
806            osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(layerToTextureMap[colorLayer]);
807            if (!texture1D)
808            {
809                texture1D = new osg::Texture1D;
810                texture1D->setImage(image);
811                texture1D->setResizeNonPowerOfTwoHint(false);
812                texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
813                texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
814
815                layerToTextureMap[colorLayer] = texture1D;
816            }
817           
818            stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON);
819
820        }
821    }
822}
823
824void GeometryTechnique::applyTransparency()
825{
826    TerrainTile::BlendingPolicy blendingPolicy = _terrainTile->getBlendingPolicy();
827    if (blendingPolicy == TerrainTile::INHERIT && _terrainTile->getTerrain())
828    {
829        OSG_INFO<<"GeometryTechnique::applyTransparency() inheriting policy from Terrain"<<std::endl;
830        blendingPolicy = _terrainTile->getTerrain()->getBlendingPolicy();
831    }
832
833    if (blendingPolicy == TerrainTile::INHERIT)
834    {
835        OSG_INFO<<"GeometryTechnique::applyTransparency() policy is INHERIT, defaulting to ENABLE_BLENDING_WHEN_ALPHA_PRESENT"<<std::endl;
836        blendingPolicy = TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT;
837    }
838
839    if (blendingPolicy == TerrainTile::DO_NOT_SET_BLENDING)
840    {
841        OSG_INFO<<"blendingPolicy == TerrainTile::DO_NOT_SET_BLENDING"<<std::endl;
842        return;
843    }
844
845    bool enableBlending = false;
846
847    if (blendingPolicy == TerrainTile::ENABLE_BLENDING)
848    {
849        OSG_INFO<<"blendingPolicy == TerrainTile::ENABLE_BLENDING"<<std::endl;
850        enableBlending = true;
851    }
852    else if (blendingPolicy == TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT)
853    {
854        OSG_INFO<<"blendingPolicy == TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT"<<std::endl;
855        for(unsigned int i=0; i<_terrainTile->getNumColorLayers(); ++i)
856        {
857            osg::Image* image = (_terrainTile->getColorLayer(i)!=0) ? _terrainTile->getColorLayer(i)->getImage() : 0;
858            if (image)
859            {
860                enableBlending = image->isImageTranslucent();
861                break;
862            }
863        }
864    }
865
866    if (enableBlending)
867    {
868        BufferData& buffer = getWriteBuffer();
869        osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
870        stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
871        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
872    }
873
874}
875
876void GeometryTechnique::smoothGeometry()
877{
878    BufferData& buffer = getWriteBuffer();
879   
880    if (buffer._geometry.valid())
881    {
882        osgUtil::SmoothingVisitor smoother;
883        smoother.smooth(*buffer._geometry);
884    }
885}
886
887void GeometryTechnique::update(osgUtil::UpdateVisitor* uv)
888{
889    if (_terrainTile) _terrainTile->osg::Group::traverse(*uv);
890}
891
892
893void GeometryTechnique::cull(osgUtil::CullVisitor* cv)
894{
895    BufferData& buffer = getReadOnlyBuffer();
896
897#if 0
898    if (buffer._terrainTile) buffer._terrainTile->osg::Group::traverse(*cv);
899#else
900    if (buffer._transform.valid())
901    {
902        buffer._transform->accept(*cv);
903    }
904#endif   
905}
906
907
908void GeometryTechnique::traverse(osg::NodeVisitor& nv)
909{
910    if (!_terrainTile) return;
911
912    // if app traversal update the frame count.
913    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
914    {
915        if (_terrainTile->getDirty()) _terrainTile->init();
916
917        osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv);
918        if (uv)
919        {
920            update(uv);
921            return;
922        }       
923       
924    }
925    else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
926    {
927        osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
928        if (cv)
929        {
930            cull(cv);
931            return;
932        }
933    }
934
935
936    if (_terrainTile->getDirty())
937    {
938        OSG_INFO<<"******* Doing init ***********"<<std::endl;
939        _terrainTile->init();
940    }
941
942    BufferData& buffer = getReadOnlyBuffer();
943    if (buffer._transform.valid()) buffer._transform->accept(nv);
944}
945
946
947void GeometryTechnique::cleanSceneGraph()
948{
949}
950
951void GeometryTechnique::releaseGLObjects(osg::State* state) const
952{
953    if (_bufferData[0]._transform.valid()) _bufferData[0]._transform->releaseGLObjects(state);
954    if (_bufferData[1]._transform.valid()) _bufferData[1]._transform->releaseGLObjects(state);   
955}
Note: See TracBrowser for help on using the browser.