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

Revision 9969, 30.5 kB (checked in by robert, 4 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.

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
20#include <osgDB/FileUtils>
21
22#include <osg/io_utils>
23#include <osg/Texture2D>
24#include <osg/Texture1D>
25#include <osg/TexEnvCombine>
26#include <osg/Program>
27#include <osg/Math>
28#include <osg/Timer>
29
30using namespace osgTerrain;
31
32#define NEW_COORD_CODE
33
34GeometryTechnique::GeometryTechnique():
35    _currentReadOnlyBuffer(1),
36    _currentWriteBuffer(0)
37   
38{
39    setFilterBias(0);
40    setFilterWidth(0.1);
41    setFilterMatrixAs(GAUSSIAN);
42   
43}
44
45GeometryTechnique::GeometryTechnique(const GeometryTechnique& gt,const osg::CopyOp& copyop):
46    TerrainTechnique(gt,copyop),
47    _currentReadOnlyBuffer(1),
48    _currentWriteBuffer(0)
49{
50    setFilterBias(gt._filterBias);
51    setFilterWidth(gt._filterWidth);
52    setFilterMatrix(gt._filterMatrix);
53}
54
55GeometryTechnique::~GeometryTechnique()
56{
57}
58
59void GeometryTechnique::swapBuffers()
60{
61    std::swap(_currentReadOnlyBuffer,_currentWriteBuffer);
62}
63
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
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
108void GeometryTechnique::init()
109{
110    osg::notify(osg::INFO)<<"Doing GeometryTechnique::init()"<<std::endl;
111   
112    if (!_terrainTile) return;
113
114    BufferData& buffer = getWriteBuffer();
115   
116    Locator* masterLocator = computeMasterLocator();
117   
118    osg::Vec3d centerModel = computeCenterModel(masterLocator);
119   
120    generateGeometry(masterLocator, centerModel);
121   
122    applyColorLayers();
123    applyTransparency();
124   
125    // smoothGeometry();
126
127    if (buffer._transform.valid()) buffer._transform->setThreadSafeRefUnref(true);
128
129    swapBuffers();
130}
131
132Locator* GeometryTechnique::computeMasterLocator()
133{
134    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
135    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
136
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;
144        return 0;
145    }
146   
147    return masterLocator;
148}
149
150osg::Vec3d GeometryTechnique::computeCenterModel(Locator* masterLocator)
151{
152    if (!masterLocator) return osg::Vec3d(0.0,0.0,0.0);
153
154    BufferData& buffer = getWriteBuffer();
155   
156    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
157    osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
158
159    Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0;
160    Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0;
161   
162    if (!elevationLocator) elevationLocator = masterLocator;
163    if (!colorLocator) colorLocator = masterLocator;
164
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
198    osg::notify(osg::INFO)<<"bottomLeftNDC = "<<bottomLeftNDC<<std::endl;
199    osg::notify(osg::INFO)<<"topRightNDC = "<<topRightNDC<<std::endl;
200
201    buffer._transform = new osg::MatrixTransform;
202
203    osg::Vec3d centerNDC = (bottomLeftNDC + topRightNDC)*0.5;
204    osg::Vec3d centerModel = (bottomLeftNDC + topRightNDC)*0.5;
205    masterLocator->convertLocalToModel(centerNDC, centerModel);
206   
207    buffer._transform->setMatrix(osg::Matrix::translate(centerModel));
208   
209    return centerModel;
210}
211
212void GeometryTechnique::generateGeometry(Locator* masterLocator, const osg::Vec3d& centerModel)
213{
214    BufferData& buffer = getWriteBuffer();
215   
216    osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer();
217
218    buffer._geode = new osg::Geode;
219    if(buffer._transform.valid())
220        buffer._transform->addChild(buffer._geode.get());
221   
222    buffer._geometry = new osg::Geometry;
223    buffer._geode->addDrawable(buffer._geometry.get());
224       
225    osg::Geometry* geometry = buffer._geometry.get();
226
227    unsigned int numRows = 20;
228    unsigned int numColumns = 20;
229   
230    if (elevationLayer)
231    {
232        numColumns = elevationLayer->getNumColumns();
233        numRows = elevationLayer->getNumRows();
234    }
235   
236    float sampleRatio = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getSampleRatio() : 1.0f;
237   
238    double i_sampleFactor = 1.0;
239    double j_sampleFactor = 1.0;
240
241    // osg::notify(osg::NOTICE)<<"Sample ratio="<<sampleRatio<<std::endl;
242
243    if (sampleRatio!=1.0f)
244    {
245   
246        unsigned int originalNumColumns = numColumns;
247        unsigned int originalNumRows = numRows;
248   
249        numColumns = std::max((unsigned int) (float(originalNumColumns)*sqrtf(sampleRatio)), 4u);
250        numRows = std::max((unsigned int) (float(originalNumRows)*sqrtf(sampleRatio)),4u);
251
252        i_sampleFactor = double(originalNumColumns-1)/double(numColumns-1);
253        j_sampleFactor = double(originalNumRows-1)/double(numRows-1);
254    }
255   
256   
257
258    bool treatBoundariesToValidDataAsDefaultValue = _terrainTile->getTreatBoundariesToValidDataAsDefaultValue();
259    osg::notify(osg::INFO)<<"TreatBoundariesToValidDataAsDefaultValue="<<treatBoundariesToValidDataAsDefaultValue<<std::endl;
260   
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   
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;
273
274    // allocate and assign vertices
275    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
276    vertices->reserve(numVertices);
277    geometry->setVertexArray(vertices.get());
278
279    // allocate and assign normals
280    osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
281    if (normals.valid()) normals->reserve(numVertices);
282    geometry->setNormalArray(normals.get());
283    geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
284   
285
286    //float minHeight = 0.0;
287    float scaleHeight = _terrainTile->getTerrain() ? _terrainTile->getTerrain()->getVerticalScale() : 1.0f;
288
289    // allocate and assign tex coords
290    typedef std::pair< osg::ref_ptr<osg::Vec2Array>, Locator* > TexCoordLocatorPair;
291    typedef std::map< Layer*, TexCoordLocatorPair > LayerToTexCoordMap;
292
293    LayerToTexCoordMap layerToTexCoordMap;
294    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
295    {
296        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
297        if (colorLayer)
298        {
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            {
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 &&
314                            static_cast<unsigned int>(switchLayer->getActiveLayer())<switchLayer->getNumLayers() &&
315                            switchLayer->getLayer(switchLayer->getActiveLayer()))
316                        {
317                            locator = switchLayer->getLayer(switchLayer->getActiveLayer())->getLocator();
318                        }
319                    }
320                }           
321           
322                TexCoordLocatorPair& tclp = layerToTexCoordMap[colorLayer];
323                tclp.first = new osg::Vec2Array;
324                tclp.first->reserve(numVertices);
325                tclp.second = locator ? locator : masterLocator;
326                geometry->setTexCoordArray(layerNum, tclp.first.get());
327            }
328        }
329    }
330
331    osg::ref_ptr<osg::FloatArray> elevations = new osg::FloatArray;
332    if (elevations.valid()) elevations->reserve(numVertices);
333       
334
335    // allocate and assign color
336    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
337    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
338   
339    geometry->setColorArray(colors.get());
340    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
341
342
343    typedef std::vector<int> Indices;
344    Indices indices(numVertices, -1);
345   
346    // populate vertex and tex coord arrays
347    unsigned int i, j;
348    for(j=0; j<numRows; ++j)
349    {
350        for(i=0; i<numColumns; ++i)
351        {
352            unsigned int iv = j*numColumns + i;
353            osg::Vec3d ndc( ((double)i)/(double)(numColumns-1), ((double)j)/(double)(numRows-1), 0.0);
354     
355            bool validValue = true;
356     
357           
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           
361            if (elevationLayer)
362            {
363                float value = 0.0f;
364                validValue = elevationLayer->getValidValue(i_equiv,j_equiv, value);
365                // osg::notify(osg::INFO)<<"i="<<i<<" j="<<j<<" z="<<value<<std::endl;
366                ndc.z() = value*scaleHeight;
367            }
368           
369            if (validValue)
370            {
371                indices[iv] = vertices->size();
372           
373                osg::Vec3d model;
374                masterLocator->convertLocalToModel(ndc, model);
375
376                (*vertices).push_back(model - centerModel);
377
378                for(LayerToTexCoordMap::iterator itr = layerToTexCoordMap.begin();
379                    itr != layerToTexCoordMap.end();
380                    ++itr)
381                {
382                    osg::Vec2Array* texcoords = itr->second.first.get();
383                    Locator* colorLocator = itr->second.second;
384                    if (colorLocator != masterLocator)
385                    {
386                        osg::Vec3d color_ndc;
387                        Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
388                        (*texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
389                    }
390                    else
391                    {
392                        (*texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
393                    }
394                }
395
396                if (elevations.valid())
397                {
398                    (*elevations).push_back(ndc.z());
399                }
400
401                // compute the local normal
402                osg::Vec3d ndc_one = ndc; ndc_one.z() += 1.0;
403                osg::Vec3d model_one;
404                masterLocator->convertLocalToModel(ndc_one, model_one);
405                model_one = model_one - model;
406                model_one.normalize();           
407                (*normals).push_back(model_one);
408            }
409            else
410            {
411                indices[iv] = -1;
412            }
413        }
414    }
415   
416    // populate primitive sets
417//    bool optimizeOrientations = elevations!=0;
418    bool swapOrientation = !(masterLocator->orientationOpenGL());
419
420    bool smallTile = numVertices <= 16384;
421
422    // osg::notify(osg::NOTICE)<<"smallTile = "<<smallTile<<std::endl;
423   
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);
429
430    geometry->addPrimitiveSet(elements.get());
431
432    for(j=0; j<numRows-1; ++j)
433    {
434        for(i=0; i<numColumns-1; ++i)
435        {
436            int i00;
437            int i01;
438            if (swapOrientation)
439            {
440                i01 = j*numColumns + i;
441                i00 = i01+numColumns;
442            }
443            else
444            {
445                i00 = j*numColumns + i;
446                i01 = i00+numColumns;
447            }
448
449            int i10 = i00+1;
450            int i11 = i01+1;
451
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)
465            {
466                float e00 = (*elevations)[i00];
467                float e10 = (*elevations)[i10];
468                float e01 = (*elevations)[i01];
469                float e11 = (*elevations)[i11];
470
471                if (fabsf(e00-e11)<fabsf(e01-e10))
472                {
473                    elements->addElement(i01);
474                    elements->addElement(i00);
475                    elements->addElement(i11);
476
477                    elements->addElement(i00);
478                    elements->addElement(i10);
479                    elements->addElement(i11);
480                }
481                else
482                {
483                    elements->addElement(i01);
484                    elements->addElement(i00);
485                    elements->addElement(i10);
486
487                    elements->addElement(i01);
488                    elements->addElement(i10);
489                    elements->addElement(i11);
490                }
491            }
492            else if (numValid==3)
493            {
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);
498            }
499           
500        }
501    }
502   
503    osg::ref_ptr<osg::Vec3Array> skirtVectors = new osg::Vec3Array((*normals));
504   
505    if (elevationLayer)
506    {
507        smoothGeometry();
508       
509        normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
510       
511        if (!normals) createSkirt = false;
512    }
513
514    if (createSkirt)
515    {
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));
519
520        // create bottom skirt vertices
521        int r,c;
522        r=0;
523        for(c=0;c<static_cast<int>(numColumns);++c)
524        {
525            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
526            if (orig_i>=0)
527            {
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]);
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                }
539               
540                skirtDrawElements->addElement(orig_i);
541                skirtDrawElements->addElement(new_i);
542            }
543            else
544            {
545                if (skirtDrawElements->getNumIndices()!=0)
546                {
547                    geometry->addPrimitiveSet(skirtDrawElements.get());
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));
551                }
552               
553            }
554        }
555
556        if (skirtDrawElements->getNumIndices()!=0)
557        {
558            geometry->addPrimitiveSet(skirtDrawElements.get());
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));
562        }
563
564        // create right skirt vertices
565        c=numColumns-1;
566        for(r=0;r<static_cast<int>(numRows);++r)
567        {
568            int orig_i = indices[(r)*numColumns+c]; // index of original vertex of grid
569            if (orig_i>=0)
570            {
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]);
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                }
581               
582                skirtDrawElements->addElement(orig_i);
583                skirtDrawElements->addElement(new_i);
584            }
585            else
586            {
587                if (skirtDrawElements->getNumIndices()!=0)
588                {
589                    geometry->addPrimitiveSet(skirtDrawElements.get());
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));
593                }
594               
595            }
596        }
597
598        if (skirtDrawElements->getNumIndices()!=0)
599        {
600            geometry->addPrimitiveSet(skirtDrawElements.get());
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));
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            {
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]);
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                }
623               
624                skirtDrawElements->addElement(orig_i);
625                skirtDrawElements->addElement(new_i);
626            }
627            else
628            {
629                if (skirtDrawElements->getNumIndices()!=0)
630                {
631                    geometry->addPrimitiveSet(skirtDrawElements.get());
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));
635                }
636               
637            }
638        }
639
640        if (skirtDrawElements->getNumIndices()!=0)
641        {
642            geometry->addPrimitiveSet(skirtDrawElements.get());
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));
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            {
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]);
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                }
665               
666                skirtDrawElements->addElement(orig_i);
667                skirtDrawElements->addElement(new_i);
668            }
669            else
670            {
671                if (skirtDrawElements->getNumIndices()!=0)
672                {
673                    geometry->addPrimitiveSet(skirtDrawElements.get());
674                    skirtDrawElements = new osg::DrawElementsUShort(GL_QUAD_STRIP);
675                }
676               
677            }
678        }
679
680        if (skirtDrawElements->getNumIndices()!=0)
681        {
682            geometry->addPrimitiveSet(skirtDrawElements.get());
683            smallTile ?
684                static_cast<osg::DrawElements*>(new osg::DrawElementsUShort(GL_QUAD_STRIP)) :
685                static_cast<osg::DrawElements*>(new osg::DrawElementsUInt(GL_QUAD_STRIP));
686        }
687    }
688
689
690    //geometry->setUseDisplayList(false);
691    geometry->setUseVertexBufferObjects(true);
692   
693   
694    if (osgDB::Registry::instance()->getBuildKdTreesHint()==osgDB::ReaderWriter::Options::BUILD_KDTREES &&
695        osgDB::Registry::instance()->getKdTreeBuilder())
696    {
697   
698       
699        //osg::Timer_t before = osg::Timer::instance()->tick();
700        //osg::notify(osg::NOTICE)<<"osgTerrain::GeometryTechnique::build kd tree"<<std::endl;
701        osg::ref_ptr<osg::KdTreeBuilder> builder = osgDB::Registry::instance()->getKdTreeBuilder()->clone();
702        buffer._geode->accept(*builder);
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;
705    }
706}
707
708void GeometryTechnique::applyColorLayers()
709{
710    BufferData& buffer = getWriteBuffer();
711
712    typedef std::map<osgTerrain::Layer*, osg::Texture*> LayerToTextureMap;
713    LayerToTextureMap layerToTextureMap;
714   
715    for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum)
716    {
717        osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum);
718        if (!colorLayer) continue;
719
720        osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(colorLayer);
721        if (switchLayer)
722        {
723            if (switchLayer->getActiveLayer()<0 ||
724                static_cast<unsigned int>(switchLayer->getActiveLayer())>=switchLayer->getNumLayers())
725            {
726                continue;
727            }
728           
729            colorLayer = switchLayer->getLayer(switchLayer->getActiveLayer());
730            if (!colorLayer) continue;
731        }
732
733        osg::Image* image = colorLayer->getImage();
734        if (!image) continue;
735
736        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(colorLayer);
737        osgTerrain::ContourLayer* contourLayer = dynamic_cast<osgTerrain::ContourLayer*>(colorLayer);
738        if (imageLayer)
739        {
740            osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
741
742            osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(layerToTextureMap[colorLayer]);
743            if (!texture2D)
744            {
745                texture2D = new osg::Texture2D;
746                texture2D->setImage(image);
747                texture2D->setMaxAnisotropy(16.0f);
748                texture2D->setResizeNonPowerOfTwoHint(false);
749
750                texture2D->setFilter(osg::Texture::MIN_FILTER, colorLayer->getMinFilter());
751                texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
752               
753                texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
754                texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
755
756                layerToTextureMap[colorLayer] = texture2D;
757
758                // osg::notify(osg::NOTICE)<<"Creating new ImageLayer texture "<<layerNum<<" image->s()="<<image->s()<<"  image->t()="<<image->t()<<std::endl;
759
760            }
761            else
762            {
763                // osg::notify(osg::NOTICE)<<"Reusing ImageLayer texture "<<layerNum<<std::endl;
764            }
765
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)
775            {
776                texture1D = new osg::Texture1D;
777                texture1D->setImage(image);
778                texture1D->setResizeNonPowerOfTwoHint(false);
779                texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);
780                texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter());
781
782                layerToTextureMap[colorLayer] = texture1D;
783            }
784           
785            stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON);
786
787        }
788    }
789}
790
791void GeometryTechnique::applyTransparency()
792{
793    BufferData& buffer = getWriteBuffer();
794   
795    bool containsTransparency = false;
796    for(unsigned int i=0; i<_terrainTile->getNumColorLayers(); ++i)
797    {
798        osg::Image* image = _terrainTile->getColorLayer(i)->getImage();
799        if (image)
800        {
801            containsTransparency = image->isImageTranslucent();
802            break;
803        }       
804    }
805   
806    if (containsTransparency)
807    {
808        osg::StateSet* stateset = buffer._geode->getOrCreateStateSet();
809        stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
810        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
811    }
812
813}
814
815void GeometryTechnique::smoothGeometry()
816{
817    BufferData& buffer = getWriteBuffer();
818   
819    if (buffer._geometry.valid())
820    {
821        osgUtil::SmoothingVisitor smoother;
822        smoother.smooth(*buffer._geometry);
823    }
824}
825
826void GeometryTechnique::update(osgUtil::UpdateVisitor* uv)
827{
828    if (_terrainTile) _terrainTile->osg::Group::traverse(*uv);
829}
830
831
832void GeometryTechnique::cull(osgUtil::CullVisitor* cv)
833{
834    BufferData& buffer = getReadOnlyBuffer();
835
836#if 0
837    if (buffer._terrainTile) buffer._terrainTile->osg::Group::traverse(*cv);
838#else
839    if (buffer._transform.valid())
840    {
841        buffer._transform->accept(*cv);
842    }
843#endif   
844}
845
846
847void GeometryTechnique::traverse(osg::NodeVisitor& nv)
848{
849    if (!_terrainTile) return;
850
851    // if app traversal update the frame count.
852    if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR)
853    {
854        if (_terrainTile->getDirty()) _terrainTile->init();
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
875    if (_terrainTile->getDirty())
876    {
877        osg::notify(osg::INFO)<<"******* Doing init ***********"<<std::endl;
878        _terrainTile->init();
879    }
880
881    BufferData& buffer = getReadOnlyBuffer();
882    if (buffer._transform.valid()) buffer._transform->accept(nv);
883}
884
885
886void GeometryTechnique::cleanSceneGraph()
887{
888}
Note: See TracBrowser for help on using the browser.