root/OpenSceneGraph/trunk/src/osgTerrain/TerrainTile.cpp @ 13041

Revision 13041, 13.9 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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/TerrainTile>
15#include <osgTerrain/Terrain>
16#include <osgTerrain/GeometryTechnique>
17
18#include <osg/ClusterCullingCallback>
19
20#include <osgDB/ReadFile>
21
22
23using namespace osg;
24using namespace osgTerrain;
25
26/////////////////////////////////////////////////////////////////////////////////
27//
28// TileID
29//
30TileID::TileID():
31    level(-1),
32    x(-1),
33    y(-1)
34{
35}
36
37TileID::TileID(int in_level, int in_x, int in_y):
38    level(in_level),
39    x(in_x),
40    y(in_y)
41{
42}
43
44/////////////////////////////////////////////////////////////////////////////////
45//
46// TerrainTile
47//
48void TerrainTile::setTileLoadedCallback(TerrainTile::TileLoadedCallback* lc)
49{
50    getTileLoadedCallback() = lc;
51}
52
53osg::ref_ptr<TerrainTile::TileLoadedCallback>& TerrainTile::getTileLoadedCallback()
54{
55    static osg::ref_ptr<TileLoadedCallback> s_TileLoadedCallback;
56    return s_TileLoadedCallback;
57}
58
59TerrainTile::TerrainTile():
60    _terrain(0),
61    _dirtyMask(NOT_DIRTY),
62    _hasBeenTraversal(false),
63    _requiresNormals(true),
64    _treatBoundariesToValidDataAsDefaultValue(false),
65    _blendingPolicy(INHERIT)
66{
67    setThreadSafeRefUnref(true);
68}
69
70TerrainTile::TerrainTile(const TerrainTile& terrain,const osg::CopyOp& copyop):
71    Group(terrain,copyop),
72    _terrain(0),
73    _dirtyMask(NOT_DIRTY),
74    _hasBeenTraversal(false),
75    _elevationLayer(terrain._elevationLayer),
76    _colorLayers(terrain._colorLayers),
77    _requiresNormals(terrain._requiresNormals),
78    _treatBoundariesToValidDataAsDefaultValue(terrain._treatBoundariesToValidDataAsDefaultValue),
79    _blendingPolicy(terrain._blendingPolicy)
80{
81    if (terrain.getTerrainTechnique())
82    {
83        setTerrainTechnique(dynamic_cast<TerrainTechnique*>(terrain.getTerrainTechnique()->cloneType()));
84    }
85}
86
87TerrainTile::~TerrainTile()
88{
89    if (_terrainTechnique.valid())
90    {
91        _terrainTechnique->setTerrainTile(0);
92    }
93
94    if (_terrain) setTerrain(0);
95}
96
97void TerrainTile::setTerrain(Terrain* ts)
98{
99    if (_terrain == ts) return;
100
101    if (_terrain) _terrain->unregisterTerrainTile(this);
102
103    _terrain = ts;
104
105    if (_terrain) _terrain->registerTerrainTile(this);
106}
107
108void TerrainTile::setTileID(const TileID& tileID)
109{
110    if (_tileID == tileID) return;
111
112    if (_terrain) _terrain->unregisterTerrainTile(this);
113
114    _tileID = tileID;
115
116    if (_terrain) _terrain->registerTerrainTile(this);
117}
118
119
120void TerrainTile::traverse(osg::NodeVisitor& nv)
121{
122    if (!_hasBeenTraversal)
123    {
124        if (!_terrain)
125        {
126            osg::NodePath& nodePath = nv.getNodePath();
127            if (!nodePath.empty())
128            {
129                for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
130                    itr != nodePath.rend() && !_terrain;
131                    ++itr)
132                {
133                    osgTerrain::Terrain* ts = dynamic_cast<Terrain*>(*itr);
134                    if (ts)
135                    {
136                        OSG_INFO<<"Assigning terrain system "<<ts<<std::endl;
137                        setTerrain(ts);
138                    }
139                }
140            }
141        }
142
143        init(getDirtyMask(), false);
144
145        _hasBeenTraversal = true;
146    }
147
148    if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR)
149    {
150        osg::ClusterCullingCallback* ccc = dynamic_cast<osg::ClusterCullingCallback*>(getCullCallback());
151        if (ccc)
152        {
153            if (ccc->cull(&nv,0,static_cast<State *>(0))) return;
154        }
155    }
156
157    if (_terrainTechnique.valid())
158    {
159        _terrainTechnique->traverse(nv);
160    }
161    else
162    {
163        osg::Group::traverse(nv);
164    }
165}
166
167void TerrainTile::init(int dirtyMask, bool assumeMultiThreaded)
168{
169    if (!_terrainTechnique)
170    {
171        if (_terrain && _terrain->getTerrainTechniquePrototype())
172        {
173            osg::ref_ptr<osg::Object> object = _terrain->getTerrainTechniquePrototype()->clone(osg::CopyOp::DEEP_COPY_ALL);
174            setTerrainTechnique(dynamic_cast<TerrainTechnique*>(object.get()));
175        }
176        else
177        {
178            setTerrainTechnique(new GeometryTechnique);
179        }
180    }
181
182    if (_terrainTechnique.valid())
183    {
184        _terrainTechnique->init(dirtyMask, assumeMultiThreaded);
185    }
186}
187
188void TerrainTile::setTerrainTechnique(TerrainTechnique* terrainTechnique)
189{
190    if (_terrainTechnique == terrainTechnique) return;
191
192    int dirtyDelta = (_dirtyMask==NOT_DIRTY) ? 0 : -1;
193
194    if (_terrainTechnique.valid())
195    {
196        _terrainTechnique->setTerrainTile(0);
197    }
198
199    _terrainTechnique = terrainTechnique;
200
201    if (_terrainTechnique.valid())
202    {
203        _terrainTechnique->setTerrainTile(this);
204        ++dirtyDelta;
205    }
206
207    if (dirtyDelta>0) setDirtyMask(ALL_DIRTY);
208    else if (dirtyDelta<0) setDirtyMask(NOT_DIRTY);
209}
210
211void TerrainTile::setDirtyMask(int dirtyMask)
212{
213    if (_dirtyMask==dirtyMask) return;
214
215    int dirtyDelta = (_dirtyMask==NOT_DIRTY) ? 0 : -1;
216
217    _dirtyMask = dirtyMask;
218
219    if (_dirtyMask!=NOT_DIRTY) dirtyDelta += 1;
220
221#if 1
222    if (dirtyDelta>0)
223    {
224        // need to signal that we need an update
225        if (_terrain) _terrain->updateTerrainTileOnNextFrame(this);
226    }
227#else
228
229    // setNumChildrenRequeingUpdateTraversal() isn't thread safe so should avoid using it.
230    if (dirtyDelta>0)
231    {
232        setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
233    }
234    else if (dirtyDelta<0 && getNumChildrenRequiringUpdateTraversal()>0)
235    {
236        setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1);
237    }
238#endif
239}
240
241
242
243void TerrainTile::setElevationLayer(Layer* layer)
244{
245    _elevationLayer = layer;
246}
247
248void TerrainTile::setColorLayer(unsigned int i, Layer* layer)
249{
250    if (_colorLayers.size() <= i) _colorLayers.resize(i+1);
251
252    _colorLayers[i] = layer;
253}
254
255osg::BoundingSphere TerrainTile::computeBound() const
256{
257    osg::BoundingSphere bs;
258
259    if (_elevationLayer.valid())
260    {
261        bs.expandBy(_elevationLayer->computeBound(true));
262    }
263    else
264    {
265        for(Layers::const_iterator itr = _colorLayers.begin();
266            itr != _colorLayers.end();
267            ++itr)
268        {
269            if (itr->valid()) bs.expandBy((*itr)->computeBound(false));
270        }
271    }
272
273    return bs;
274}
275
276
277/////////////////////////////////////////////////////////////////////////////////
278//
279// WhiteListTileLoadedCallback
280//
281WhiteListTileLoadedCallback::WhiteListTileLoadedCallback()
282{
283    _minumumNumberOfLayers = 0;
284    _replaceSwitchLayer = false;
285    _allowAll = false;
286}
287
288WhiteListTileLoadedCallback::~WhiteListTileLoadedCallback()
289{
290}
291
292bool WhiteListTileLoadedCallback::layerAcceptable(const std::string& setname) const
293{
294    if (_allowAll) return true;
295
296    if (setname.empty()) return true;
297
298    return _setWhiteList.count(setname)!=0;
299}
300
301bool WhiteListTileLoadedCallback::readImageLayer(osgTerrain::ImageLayer* imageLayer, const osgDB::ReaderWriter::Options* options) const
302{
303   if (!imageLayer->getImage() &&
304        !imageLayer->getFileName().empty())
305    {
306        if (layerAcceptable(imageLayer->getSetName()))
307        {
308            osg::ref_ptr<osg::Image> image = osgDB::readImageFile(imageLayer->getFileName(), options);
309            imageLayer->setImage(image.get());
310        }
311    }
312    return imageLayer->getImage()!=0;
313}
314
315bool WhiteListTileLoadedCallback::deferExternalLayerLoading() const
316{
317    return true;
318}
319
320void WhiteListTileLoadedCallback::loaded(osgTerrain::TerrainTile* tile, const osgDB::ReaderWriter::Options* options) const
321{
322
323    // read any external layers
324    for(unsigned int i=0; i<tile->getNumColorLayers(); ++i)
325    {
326        osgTerrain::Layer* layer = tile->getColorLayer(i);
327        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(layer);
328        if (imageLayer)
329        {
330            readImageLayer(imageLayer, options);
331            continue;
332        }
333
334        osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(layer);
335        if (switchLayer)
336        {
337            for(unsigned int si=0; si<switchLayer->getNumLayers(); ++si)
338            {
339                osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(si));
340                if (imageLayer)
341                {
342                    if (readImageLayer(imageLayer, options))
343                    {
344                        // replace SwitchLayer by
345                        if (_replaceSwitchLayer) tile->setColorLayer(i, imageLayer);
346                        else if (switchLayer->getActiveLayer()<0) switchLayer->setActiveLayer(si);
347
348                        continue;
349                    }
350                }
351            }
352            continue;
353        }
354
355        osgTerrain::CompositeLayer* compositeLayer = dynamic_cast<osgTerrain::CompositeLayer*>(layer);
356        if (compositeLayer)
357        {
358            for(unsigned int ci=0; ci<compositeLayer->getNumLayers(); ++ci)
359            {
360                osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(compositeLayer->getLayer(ci));
361                if (imageLayer)
362                {
363                    readImageLayer(imageLayer, options);
364                }
365            }
366            continue;
367        }
368    }
369
370    // assign colour layers over missing layers
371    osgTerrain::Layer* validLayer = 0;
372    for(unsigned int i=0; i<tile->getNumColorLayers(); ++i)
373    {
374        osgTerrain::Layer* layer = tile->getColorLayer(i);
375        osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(layer);
376        if (imageLayer)
377        {
378            if (imageLayer->getImage()!=0)
379            {
380                validLayer = imageLayer;
381            }
382            continue;
383        }
384
385        osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(layer);
386        if (switchLayer)
387        {
388            for(unsigned int si=0; si<switchLayer->getNumLayers(); ++si)
389            {
390                osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(si));
391                if (imageLayer && imageLayer->getImage()!=0)
392                {
393                    validLayer = imageLayer;
394                }
395            }
396            continue;
397        }
398
399        osgTerrain::CompositeLayer* compositeLayer = dynamic_cast<osgTerrain::CompositeLayer*>(layer);
400        if (compositeLayer)
401        {
402            for(unsigned int ci=0; ci<compositeLayer->getNumLayers(); ++ci)
403            {
404                osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(ci));
405                if (imageLayer && imageLayer->getImage()!=0)
406                {
407                    validLayer = imageLayer;
408                }
409            }
410            continue;
411        }
412    }
413
414    if (validLayer)
415    {
416        // fill in any missing layers
417        for(unsigned int i=0; i<tile->getNumColorLayers(); ++i)
418        {
419            osgTerrain::Layer* layer = tile->getColorLayer(i);
420            osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(layer);
421            if (imageLayer)
422            {
423                if (imageLayer->getImage()==0)
424                {
425                    tile->setColorLayer(i, validLayer);
426                    break;
427                }
428                continue;
429            }
430
431            osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(layer);
432            if (switchLayer)
433            {
434                for(unsigned int si=0; si<switchLayer->getNumLayers(); ++si)
435                {
436                    osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(si));
437                    if (imageLayer && imageLayer->getImage()==0)
438                    {
439                        if (_replaceSwitchLayer) tile->setColorLayer(i, imageLayer);
440                        else
441                        {
442                            switchLayer->setLayer(si, validLayer);
443                            if (switchLayer->getActiveLayer()<0) switchLayer->setActiveLayer(si);
444                        }
445                        break;
446                    }
447                }
448                if (switchLayer->getNumLayers()==0)
449                {
450                    if (_replaceSwitchLayer) tile->setColorLayer(i, validLayer);
451                    else
452                    {
453                        switchLayer->setLayer(0, validLayer);
454                        switchLayer->setActiveLayer(0);
455                    }
456                }
457            }
458
459            osgTerrain::CompositeLayer* compositeLayer = dynamic_cast<osgTerrain::CompositeLayer*>(layer);
460            if (compositeLayer)
461            {
462                for(unsigned int ci=0; ci<compositeLayer->getNumLayers(); ++ci)
463                {
464                    osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(ci));
465                    if (imageLayer && imageLayer->getImage()==0)
466                    {
467                        tile->setColorLayer(i, validLayer);
468                        break;
469                    }
470                }
471                continue;
472            }
473        }
474
475        if (_minumumNumberOfLayers>tile->getNumColorLayers())
476        {
477            for(unsigned int i=tile->getNumColorLayers(); i<_minumumNumberOfLayers; ++i)
478            {
479                tile->setColorLayer(i, validLayer);
480            }
481        }
482
483    }
484}
485
486void TerrainTile::releaseGLObjects(osg::State* state) const
487{
488    Group::releaseGLObjects(state);
489
490    if (_terrainTechnique.valid())
491    {
492        _terrainTechnique->releaseGLObjects( state );
493    }
494}
Note: See TracBrowser for help on using the browser.