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

Revision 9969, 30.5 kB (checked in by robert, 6 years ago)

Added new virtual reseveElements, setElement, getElment and addElement methods to DrawElements?
to make is easier to write code that can work on DrawElementUByte, UShort or UInt.

Changed the osgTerrain::GeometryTechnique? so that it automatically chooses
the use of DrawElementUShort or DrawElementsUInt accordining to the size of the tile.

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