osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_osgterrain/Tile.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003 * Copyright 2008-2010 Pelican Mapping
00004 * http://osgearth.org
00005 *
00006 * osgEarth is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU Lesser General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU Lesser General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU Lesser General Public License
00017 * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018 */
00019 #include "Tile"
00020 #include "Terrain"
00021 #include "CustomTerrainTechnique"
00022 #include "TransparentLayer"
00023 
00024 #include <osgEarth/Registry>
00025 #include <osgEarth/Locators>
00026 #include <osgEarth/Map>
00027 #include <osgEarth/FindNode>
00028 
00029 #include <osg/NodeCallback>
00030 #include <osg/NodeVisitor>
00031 #include <osg/Node>
00032 #include <osg/Texture2D>
00033 #include <osgGA/EventVisitor>
00034 
00035 #include <OpenThreads/ScopedLock>
00036 
00037 
00038 using namespace osgEarth;
00039 using namespace OpenThreads;
00040 
00041 #define LC "[Tile] "
00042 
00043 //----------------------------------------------------------------------------
00044 
00045 Tile::Tile( const TileKey& key, GeoLocator* keyLocator, bool quickReleaseGLObjects ) :
00046 _key( key ),
00047 _locator( keyLocator ),
00048 _quickReleaseGLObjects( quickReleaseGLObjects ),
00049 _hasBeenTraversed( false ),
00050 _verticalScale( 1.0f ),
00051 _parentTileSet( false ),
00052 _tileId( key.getTileId() ),
00053 _dirty( true )
00054 {
00055     this->setThreadSafeRefUnref( true );
00056     this->setName( key.str() );
00057 
00058     // initially bump the update requirement so that this tile will receive an update
00059     // traversal the first time through. It is on the first update traversal that we
00060     // know the tile is in the scene graph and that it can be registered with the terrain.
00061     ADJUST_UPDATE_TRAV_COUNT( this, 1 );
00062 }
00063 
00064 Tile::~Tile()
00065 {
00066     //nop
00067 }
00068 
00069 void
00070 Tile::init()
00071 {
00072     if ( _tech.valid() )
00073     {
00074         _tech->init();
00075         _dirty = false;
00076     }
00077 }
00078 
00079 void
00080 Tile::setTerrainTechnique( TerrainTechnique* tech )
00081 {
00082     tech->_tile = this;
00083     _tech = tech;
00084     _dirty = true;
00085 }
00086 
00087 void
00088 Tile::attachToTerrain( Terrain* terrain )
00089 {
00090     _terrain = terrain;
00091     if ( terrain )
00092         terrain->registerTile( this );
00093 }
00094 
00095 void
00096 Tile::setVerticalScale (float verticalScale )
00097 {
00098     if (_verticalScale != verticalScale)
00099     {
00100         _verticalScale = verticalScale;
00101         dirtyBound();
00102     }
00103 }
00104 
00105 void
00106 Tile::setCustomColorLayer( const CustomColorLayer& layer, bool writeLock )
00107 {
00108     if ( writeLock )
00109     {
00110         Threading::ScopedWriteLock exclusiveTileLock( _tileLayersMutex );
00111         setCustomColorLayer( layer, false );
00112     }
00113     else
00114     {
00115         int delta = 0;
00116         ColorLayersByUID::const_iterator i = _colorLayers.find( layer.getUID() );
00117         if ( i != _colorLayers.end() && i->second.getMapLayer()->isDynamic() )
00118             --delta;
00119         
00120        _colorLayers[layer.getUID()] = layer;
00121        
00122         if ( layer.getMapLayer()->isDynamic() )
00123             ++delta;
00124 
00125         if ( delta != 0 )
00126             ADJUST_UPDATE_TRAV_COUNT( this, delta );
00127     }
00128 }
00129 
00130 void
00131 Tile::removeCustomColorLayer( UID layerUID, bool writeLock )
00132 {
00133     if ( writeLock )
00134     {
00135         Threading::ScopedWriteLock exclusiveTileLock( _tileLayersMutex );
00136         removeCustomColorLayer( layerUID, false );
00137     }
00138     else
00139     {
00140         ColorLayersByUID::iterator i = _colorLayers.find(layerUID);
00141         if ( i != _colorLayers.end() )
00142         {
00143             if ( i->second.getMapLayer()->isDynamic() )
00144                 ADJUST_UPDATE_TRAV_COUNT( this, -1 );
00145 
00146             _colorLayers.erase( i );
00147         }
00148     }
00149 }
00150 
00151 bool
00152 Tile::getCustomColorLayer( UID layerUID, CustomColorLayer& out, bool readLock ) const
00153 {
00154     if ( readLock )
00155     {
00156         Threading::ScopedReadLock sharedTileLock( const_cast<Tile*>(this)->_tileLayersMutex );
00157         return getCustomColorLayer( layerUID, out, false );
00158     }
00159     else
00160     {
00161         ColorLayersByUID::const_iterator i = _colorLayers.find( layerUID );
00162         if ( i != _colorLayers.end() )
00163         {
00164             out = i->second;
00165             return true;
00166         }
00167     }
00168     return false;
00169 }
00170 
00171 void
00172 Tile::getCustomColorLayers( ColorLayersByUID& out, bool readLock ) const
00173 {
00174     if ( readLock )
00175     {
00176         Threading::ScopedReadLock sharedTileLock( const_cast<Tile*>(this)->_tileLayersMutex );
00177         return getCustomColorLayers( out, false );
00178     }
00179     else
00180         out = _colorLayers;
00181 }
00182 
00183 void
00184 Tile::setCustomColorLayers( const ColorLayersByUID& in, bool writeLock )
00185 {
00186     if ( writeLock )
00187     {
00188         Threading::ScopedWriteLock exclusiveLock( _tileLayersMutex );
00189         setCustomColorLayers( in, false );
00190     }
00191     else
00192     {
00193         int delta = 0;
00194         for( ColorLayersByUID::const_iterator i = _colorLayers.begin(); i != _colorLayers.end(); ++i )
00195             if ( i->second.getMapLayer()->isDynamic() )
00196                 --delta;
00197 
00198         _colorLayers = in;
00199 
00200         for( ColorLayersByUID::const_iterator i = _colorLayers.begin(); i != _colorLayers.end(); ++i )
00201             if ( i->second.getMapLayer()->isDynamic() )
00202                 ++delta;
00203 
00204         if ( delta != 0 )
00205             ADJUST_UPDATE_TRAV_COUNT( this, delta );
00206     }
00207 }
00208 
00209 osg::BoundingSphere
00210 Tile::computeBound() const
00211 {
00212     //Overriden computeBound that takes into account the vertical scale.
00213     //OE_NOTICE << "Tile::computeBound verticalScale = " << _verticalScale << std::endl;
00214 
00215     osg::BoundingSphere bs;
00216 
00217     if (_elevationLayer.valid())
00218     {        
00219         if (!_elevationLayer->getLocator()) return bs;
00220 
00221         osg::BoundingBox bb;
00222         unsigned int numColumns = _elevationLayer->getNumColumns();
00223         unsigned int numRows = _elevationLayer->getNumRows();
00224         for(unsigned int r=0;r<numRows;++r)
00225         {
00226             for(unsigned int c=0;c<numColumns;++c)
00227             {
00228                 float value = 0.0f;
00229                 bool validValue = _elevationLayer->getValidValue(c,r, value);
00230                 if (validValue) 
00231                 {
00232                     //Multiply by the vertical scale.
00233                     value *= _verticalScale;
00234                     osg::Vec3d ndc, v;
00235                     ndc.x() = ((double)c)/(double)(numColumns-1), 
00236                         ndc.y() = ((double)r)/(double)(numRows-1);
00237                     ndc.z() = value;
00238 
00239                     if (_elevationLayer->getLocator()->convertLocalToModel(ndc, v))
00240                     {
00241                         bb.expandBy(v);
00242                     }
00243                 }
00244             }
00245         }
00246         bs.expandBy(bb);
00247 
00248     }
00249     else
00250     {
00251         for(ColorLayersByUID::const_iterator i = _colorLayers.begin(); i != _colorLayers.end(); ++i )
00252         {
00253             bs.expandBy( i->second.computeBound() ); 
00254         }
00255     }
00256 
00257     return bs;    
00258 }
00259 
00260 void
00261 Tile::queueTileUpdate( TileUpdate::Action action, int value )
00262 {
00263     _dirty = true;
00264 }
00265 
00266 void
00267 Tile::applyImmediateTileUpdate( TileUpdate::Action action, int value )
00268 {
00269     CustomTerrainTechnique* tech = dynamic_cast<CustomTerrainTechnique*>( _tech.get() );
00270     if ( tech )
00271     {
00272         tech->compile( TileUpdate(action, value), 0L );
00273         tech->applyTileUpdates();
00274     }
00275     else
00276     {
00277         queueTileUpdate( action, value );
00278     }
00279 }
00280 
00281 void
00282 Tile::traverse( osg::NodeVisitor& nv )
00283 {    
00284     // set the parent tile in the technique:
00285     if ( !_parentTileSet && _terrain.valid() )
00286     {
00287         osg::ref_ptr<Tile> parentTile;
00288         //Take a reference
00289         osg::ref_ptr< Terrain > terrain = _terrain.get();
00290         if (terrain.valid())
00291         {
00292             terrain->getTile( _key.createParentKey().getTileId(), parentTile );
00293             CustomTerrainTechnique* tech = dynamic_cast<CustomTerrainTechnique*>( _tech.get() );
00294             if ( tech )
00295                 tech->setParentTile( parentTile.get() );
00296             _parentTileSet = true;
00297         }
00298     }
00299 
00300     // this block runs the first time the tile is traversed while in the scene graph.
00301     if ( !_hasBeenTraversed )
00302     {
00303         if ( nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR )
00304         {
00305             Threading::ScopedWriteLock lock( this->_tileLayersMutex );
00306             {
00307                 if ( !_hasBeenTraversed && _terrain.valid() )
00308                 {
00309                     _hasBeenTraversed = true;
00310 
00311                     // we constructed this tile with an update traversal count of 1 so it would get
00312                     // here and we could register the tile. Now we can decrement it back to normal.
00313                     // this MUST be called from the UPDATE traversal.
00314                     ADJUST_UPDATE_TRAV_COUNT( this, -1 );
00315                 }
00316             }
00317         }
00318     }
00319 
00320     // code copied from osgTerrain::TerrainTile... TODO: evaluate this... -gw
00321     if ( nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR )
00322     {
00323         osg::ClusterCullingCallback* ccc = dynamic_cast<osg::ClusterCullingCallback*>(getCullCallback());
00324         if (ccc)
00325         {
00326             if (ccc->cull(&nv,0,static_cast<osg::State *>(0))) return;
00327         }
00328     }
00329 
00330     if ( _dirty )
00331     {
00332         init();
00333     }
00334 
00335     if ( _tech.valid() )
00336     {
00337         _tech->traverse( nv );
00338     }
00339 }
00340 
00341 void
00342 Tile::releaseGLObjects(osg::State* state) const
00343 {
00344     osg::Node::releaseGLObjects( state );
00345     
00346     if ( _tech.valid() )
00347     {
00348         //NOTE: crashes sometimes if OSG_RELEASE_DELAY is set -gw
00349         _tech->releaseGLObjects( state );
00350     }
00351 }
00352 
00353 //------------------------------------------------------------------------
00354 
00355 TileFrame::TileFrame( Tile* tile ) :
00356 _tileKey(tile->getKey())
00357 {
00358     Threading::ScopedReadLock sharedLock( tile->_tileLayersMutex );
00359     _colorLayers    = tile->_colorLayers;
00360     _elevationLayer = tile->getElevationLayer();
00361     _locator        = tile->getLocator();
00362     osg::ref_ptr< Terrain > terrain = tile->getTerrain();
00363     if (terrain.valid())
00364     {
00365         _sampleRatio  = terrain->getSampleRatio();
00366     }
00367     _masks          = MaskLayerVector(tile->getTerrainMasks());
00368 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines