osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_osgterrain/StreamingTerrain.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 "StreamingTerrain"
00020 #include "StreamingTile"
00021 #include "TransparentLayer"
00022 
00023 #include <osgEarth/Registry>
00024 #include <osgEarth/Map>
00025 #include <osgEarth/FindNode>
00026 
00027 #include <osg/NodeCallback>
00028 #include <osg/NodeVisitor>
00029 #include <osg/Node>
00030 #include <osgGA/EventVisitor>
00031 
00032 #include <OpenThreads/ScopedLock>
00033 
00034 using namespace osgEarth;
00035 using namespace OpenThreads;
00036 
00037 #define LC "[StreamingTerrain] "
00038 
00039 //----------------------------------------------------------------------------
00040 
00041 StreamingTerrain::StreamingTerrain(const MapFrame& update_mapf, 
00042                                    const MapFrame& cull_mapf, 
00043                                    OSGTileFactory* tileFactory,
00044                                    bool            quickReleaseGLObjects ) :
00045 
00046 Terrain( update_mapf, cull_mapf, tileFactory, quickReleaseGLObjects ),
00047 _numLoadingThreads( 0 )
00048 {
00049     _loadingPolicy = tileFactory->getTerrainOptions().loadingPolicy().get();
00050 
00051     setNumChildrenRequiringUpdateTraversal( 1 );
00052     _alwaysUpdate = true;
00053     _numLoadingThreads = computeLoadingThreads(_loadingPolicy);
00054 
00055     OE_INFO << LC << "Using a total of " << _numLoadingThreads << " loading threads " << std::endl;
00056 }
00057 
00058 StreamingTerrain::~StreamingTerrain()
00059 {
00060     //nop
00061 }
00062 
00063 Tile*
00064 StreamingTerrain::createTile(const TileKey& key, GeoLocator* locator) const
00065 {
00066     return new StreamingTile( key, locator, this->getQuickReleaseGLObjects() );
00067 }
00068 
00069 // This method is called by StreamingTerrain::traverse() in the UPDATE TRAVERSAL.
00070 void
00071 StreamingTerrain::refreshFamily(const MapInfo&           mapInfo,
00072                                 const TileKey&           key,
00073                                 StreamingTile::Relative* family,
00074                                 bool                     tileTableLocked )
00075 {
00076     osgTerrain::TileID tileId = key.getTileId();
00077 
00078     // geocentric maps wrap around in the X dimension.
00079     bool wrapX = mapInfo.isGeocentric();
00080     unsigned int tileCountX, tileCountY;
00081     mapInfo.getProfile()->getNumTiles( tileId.level, tileCountX, tileCountY );
00082 
00083     // Relative::PARENT
00084     {
00085         family[StreamingTile::Relative::PARENT].expected = true; // TODO: is this always correct?
00086         family[StreamingTile::Relative::PARENT].elevLOD = -1;
00087         family[StreamingTile::Relative::PARENT].imageLODs.clear();
00088         family[StreamingTile::Relative::PARENT].tileID = osgTerrain::TileID( tileId.level-1, tileId.x/2, tileId.y/2 );
00089 
00090         osg::ref_ptr<StreamingTile> parent;
00091         getTile( family[StreamingTile::Relative::PARENT].tileID, parent, !tileTableLocked );
00092         if ( parent.valid() )
00093         {
00094             family[StreamingTile::Relative::PARENT].elevLOD = parent->getElevationLOD();
00095 
00096             ColorLayersByUID relLayers;
00097             parent->getCustomColorLayers( relLayers );
00098 
00099             for( ColorLayersByUID::const_iterator i = relLayers.begin(); i != relLayers.end(); ++i )
00100             {
00101                 family[StreamingTile::Relative::PARENT].imageLODs[i->first] = i->second.getLevelOfDetail();
00102             }
00103         }
00104     }
00105 
00106     // Relative::WEST
00107     {
00108         family[StreamingTile::Relative::WEST].expected = tileId.x > 0 || wrapX;
00109         family[StreamingTile::Relative::WEST].elevLOD = -1;
00110         family[StreamingTile::Relative::WEST].imageLODs.clear();
00111         family[StreamingTile::Relative::WEST].tileID = osgTerrain::TileID( tileId.level, tileId.x > 0? tileId.x-1 : tileCountX-1, tileId.y );
00112         osg::ref_ptr<StreamingTile> west;
00113         getTile( family[StreamingTile::Relative::WEST].tileID, west, !tileTableLocked );
00114         if ( west.valid() )
00115         {
00116             family[StreamingTile::Relative::WEST].elevLOD = west->getElevationLOD();
00117 
00118             ColorLayersByUID relLayers;
00119             west->getCustomColorLayers( relLayers );
00120 
00121             for( ColorLayersByUID::const_iterator i = relLayers.begin(); i != relLayers.end(); ++i )
00122             {
00123                 family[StreamingTile::Relative::WEST].imageLODs[i->first] = i->second.getLevelOfDetail();
00124             }
00125         }
00126     }
00127 
00128     // Relative::NORTH
00129     {
00130         family[StreamingTile::Relative::NORTH].expected = tileId.y < (int)tileCountY-1;
00131         family[StreamingTile::Relative::NORTH].elevLOD = -1;
00132         family[StreamingTile::Relative::NORTH].imageLODs.clear();
00133         family[StreamingTile::Relative::NORTH].tileID = osgTerrain::TileID( tileId.level, tileId.x, tileId.y < (int)tileCountY-1 ? tileId.y+1 : 0 );
00134         osg::ref_ptr<StreamingTile> north;
00135         getTile( family[StreamingTile::Relative::NORTH].tileID, north, !tileTableLocked );
00136         if ( north.valid() )
00137         {
00138             family[StreamingTile::Relative::NORTH].elevLOD = north->getElevationLOD();
00139 
00140             ColorLayersByUID relLayers;
00141             north->getCustomColorLayers( relLayers );
00142 
00143             for( ColorLayersByUID::const_iterator i = relLayers.begin(); i != relLayers.end(); ++i )
00144             {
00145                 family[StreamingTile::Relative::NORTH].imageLODs[i->first] = i->second.getLevelOfDetail();
00146             }
00147         }
00148     }
00149 
00150     // Relative::EAST
00151     {
00152         family[StreamingTile::Relative::EAST].expected = tileId.x < (int)tileCountX-1 || wrapX;
00153         family[StreamingTile::Relative::EAST].elevLOD = -1;
00154         family[StreamingTile::Relative::EAST].imageLODs.clear();
00155         family[StreamingTile::Relative::EAST].tileID = osgTerrain::TileID( tileId.level, tileId.x < (int)tileCountX-1 ? tileId.x+1 : 0, tileId.y );
00156         osg::ref_ptr<StreamingTile> east;
00157         getTile( family[StreamingTile::Relative::EAST].tileID, east, !tileTableLocked );
00158         if ( east.valid() )
00159         {
00160             family[StreamingTile::Relative::EAST].elevLOD = east->getElevationLOD();
00161 
00162             ColorLayersByUID relLayers;
00163             east->getCustomColorLayers( relLayers );
00164 
00165             for( ColorLayersByUID::const_iterator i = relLayers.begin(); i != relLayers.end(); ++i )
00166             {
00167                 family[StreamingTile::Relative::EAST].imageLODs[i->first] = i->second.getLevelOfDetail();
00168             }
00169         }
00170     }
00171 
00172     // Relative::SOUTH
00173     {
00174         family[StreamingTile::Relative::SOUTH].expected = tileId.y > 0;
00175         family[StreamingTile::Relative::SOUTH].elevLOD = -1;
00176         family[StreamingTile::Relative::SOUTH].imageLODs.clear();
00177         family[StreamingTile::Relative::SOUTH].tileID = osgTerrain::TileID( tileId.level, tileId.x, tileId.y > 0 ? tileId.y-1 : tileCountY-1 );
00178         osg::ref_ptr<StreamingTile> south;
00179         getTile( family[StreamingTile::Relative::SOUTH].tileID, south, !tileTableLocked );
00180         if ( south.valid() )
00181         {
00182             family[StreamingTile::Relative::SOUTH].elevLOD = south->getElevationLOD();
00183 
00184             ColorLayersByUID relLayers;
00185             south->getCustomColorLayers( relLayers );
00186 
00187             for( ColorLayersByUID::const_iterator i = relLayers.begin(); i != relLayers.end(); ++i )
00188             {
00189                 family[StreamingTile::Relative::SOUTH].imageLODs[i->first] = i->second.getLevelOfDetail();
00190             }
00191         }
00192     }
00193 }
00194 
00195 unsigned
00196 StreamingTerrain::getNumActiveTasks() const
00197 {
00198     ScopedLock<Mutex> lock(const_cast<StreamingTerrain*>(this)->_taskServiceMutex );
00199 
00200     unsigned int total = 0;
00201     for (TaskServiceMap::const_iterator itr = _taskServices.begin(); itr != _taskServices.end(); ++itr)
00202     {
00203         total += itr->second->getNumRequests();
00204     }
00205     return total;
00206 }
00207 
00208 void
00209 StreamingTerrain::updateTraversal( osg::NodeVisitor& nv )
00210 {
00211     // this stamp keeps track of when requests are dispatched. If a request's stamp gets too
00212     // old, it is considered "expired" and subject to cancelation
00213     int stamp = nv.getFrameStamp()->getFrameNumber();
00214 
00215     // update the frame stamp on the task services. This is necessary to support 
00216     // automatic request cancelation for image requests.
00217     {
00218         ScopedLock<Mutex> lock( _taskServiceMutex );
00219         for (TaskServiceMap::iterator i = _taskServices.begin(); i != _taskServices.end(); ++i)
00220         {
00221             i->second->setStamp( stamp );
00222         }
00223     }
00224 
00225     // next, go through the live tiles and process update-traversal requests. This
00226     // requires a read-lock on the master tiles table.
00227     {
00228         Threading::ScopedReadLock tileTableReadLock( _tilesMutex );
00229 
00230         for( TileTable::const_iterator i = _tiles.begin(); i != _tiles.end(); ++i )
00231         {
00232             StreamingTile* tile = static_cast<StreamingTile*>( i->second.get() );
00233 
00234             // update the neighbor list for each tile.
00235             refreshFamily( _update_mapf.getMapInfo(), tile->getKey(), tile->getFamily(), true );
00236 
00237             tile->servicePendingElevationRequests( _update_mapf, stamp, true );                   
00238             tile->serviceCompletedRequests( _update_mapf, true );
00239         }
00240     }
00241 }
00242 
00243 TaskService*
00244 StreamingTerrain::createTaskService( const std::string& name, int id, int numThreads )
00245 {
00246     ScopedLock<Mutex> lock( _taskServiceMutex );
00247 
00248     // first, double-check that the service wasn't created during the locking process:
00249     TaskServiceMap::iterator itr = _taskServices.find(id);
00250     if (itr != _taskServices.end())
00251         return itr->second.get();
00252 
00253     // ok, make a new one
00254     TaskService* service =  new TaskService( name, numThreads );
00255     _taskServices[id] = service;
00256     return service;
00257 }
00258 
00259 TaskService*
00260 StreamingTerrain::getTaskService(int id)
00261 {
00262     ScopedLock<Mutex> lock( _taskServiceMutex );
00263     TaskServiceMap::iterator itr = _taskServices.find(id);
00264     if (itr != _taskServices.end())
00265     {
00266         return itr->second.get();
00267     }
00268     return NULL;
00269 }
00270 
00271 #define ELEVATION_TASK_SERVICE_ID 9999
00272 #define TILE_GENERATION_TASK_SERVICE_ID 10000
00273 
00274 TaskService*
00275 StreamingTerrain::getElevationTaskService()
00276 {
00277     TaskService* service = getTaskService( ELEVATION_TASK_SERVICE_ID );
00278     if (!service)
00279     {
00280         service = createTaskService( "elevation", ELEVATION_TASK_SERVICE_ID, 1 );
00281     }
00282     return service;
00283 }
00284 
00285 
00286 TaskService*
00287 StreamingTerrain::getImageryTaskService(int layerId)
00288 {
00289     TaskService* service = getTaskService( layerId );
00290     if (!service)
00291     {
00292         std::stringstream buf;
00293         buf << "layer " << layerId;
00294         std::string bufStr = buf.str();
00295         service = createTaskService( bufStr, layerId, 1 );
00296     }
00297     return service;
00298 }
00299 
00300 TaskService*
00301 StreamingTerrain::getTileGenerationTaskService()
00302 {
00303     TaskService* service = getTaskService( TILE_GENERATION_TASK_SERVICE_ID );
00304     if (!service)
00305     {
00306         int numCompileThreads = 
00307             _loadingPolicy.numCompileThreads().isSet() ? osg::maximum( 1, _loadingPolicy.numCompileThreads().value() ) :
00308             (int)osg::maximum( 1.0f, _loadingPolicy.numCompileThreadsPerCore().value() * (float)GetNumberOfProcessors() );
00309 
00310         service = createTaskService( "tilegen", TILE_GENERATION_TASK_SERVICE_ID, numCompileThreads );
00311     }
00312     return service;
00313 }
00314 
00315 void
00316 StreamingTerrain::updateTaskServiceThreads( const MapFrame& mapf )
00317 {
00318     //Get the maximum elevation weight
00319     float elevationWeight = 0.0f;
00320     for (ElevationLayerVector::const_iterator itr = mapf.elevationLayers().begin(); itr != mapf.elevationLayers().end(); ++itr)
00321     {
00322         ElevationLayer* layer = itr->get();
00323         float w = layer->getTerrainLayerOptions().loadingWeight().value();
00324         if (w > elevationWeight) elevationWeight = w;
00325     }
00326 
00327     float totalImageWeight = 0.0f;
00328     for (ImageLayerVector::const_iterator itr = mapf.imageLayers().begin(); itr != mapf.imageLayers().end(); ++itr)
00329     {
00330         totalImageWeight += itr->get()->getTerrainLayerOptions().loadingWeight().value();
00331     }
00332 
00333     float totalWeight = elevationWeight + totalImageWeight;
00334 
00335     if (elevationWeight > 0.0f)
00336     {
00337         //Determine how many threads each layer gets
00338         int numElevationThreads = (int)osg::round((float)_numLoadingThreads * (elevationWeight / totalWeight ));
00339         OE_INFO << LC << "Elevation Threads = " << numElevationThreads << std::endl;
00340         getElevationTaskService()->setNumThreads( numElevationThreads );
00341     }
00342 
00343     for (ImageLayerVector::const_iterator itr = mapf.imageLayers().begin(); itr != mapf.imageLayers().end(); ++itr)
00344     {
00345         const TerrainLayerOptions& opt = itr->get()->getTerrainLayerOptions();
00346         int imageThreads = (int)osg::round((float)_numLoadingThreads * (opt.loadingWeight().value() / totalWeight ));
00347         OE_INFO << LC << "Image Threads for " << itr->get()->getName() << " = " << imageThreads << std::endl;
00348         getImageryTaskService( itr->get()->getUID() )->setNumThreads( imageThreads );
00349     }
00350 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines