osgEarth 2.1.1
|
Classes | |
struct | Job |
struct | SourceRepo |
Public Member Functions | |
TileBuilder (const Map *map, const OSGTerrainOptions &terrainOptions, TaskService *service) | |
void | createTile (const TileKey &key, bool parallelize, osg::ref_ptr< Tile > &out_tile, bool &out_hasRealData, bool &out_hasLodBlendedLayers) |
Job * | createJob (const TileKey &key, Threading::MultiEvent &semaphore) |
void | runJob (Job *job) |
void | finalizeJob (Job *job, osg::ref_ptr< Tile > &out_tile, bool &out_hasRealData, bool &out_hasLodBlending) |
TaskService * | getTaskService () const |
Private Attributes | |
const Map * | _map |
TaskService * | _service |
const OSGTerrainOptions & | _terrainOptions |
Definition at line 30 of file TileBuilder.
TileBuilder::TileBuilder | ( | const Map * | map, |
const OSGTerrainOptions & | terrainOptions, | ||
TaskService * | service | ||
) |
Definition at line 182 of file TileBuilder.cpp.
: _map( map ), _terrainOptions( terrainOptions ), _service( service ) { //nop }
TileBuilder::Job * TileBuilder::createJob | ( | const TileKey & | key, |
Threading::MultiEvent & | semaphore | ||
) |
Definition at line 191 of file TileBuilder.cpp.
{ Job* job = new Job( key, _map ); // create the image layer tasks: for( ImageLayerVector::const_iterator i = job->_mapf.imageLayers().begin(); i != job->_mapf.imageLayers().end(); ++i ) { ImageLayer* layer = i->get(); if ( layer->isKeyValid(key) ) { ParallelTask<BuildColorLayer>* j = new ParallelTask<BuildColorLayer>( &semaphore ); j->init( key, layer, job->_mapf.getMapInfo(), _terrainOptions, job->_repo ); j->setPriority( -(float)key.getLevelOfDetail() ); job->_tasks.push_back( j ); } } // If we have elevation layers, start an elevation job as well. Otherwise just create an // empty one while we're waiting for the images to load. if ( job->_mapf.elevationLayers().size() > 0 ) { ParallelTask<BuildElevLayer>* ej = new ParallelTask<BuildElevLayer>( &semaphore ); ej->init( key, job->_mapf, _terrainOptions, job->_repo ); ej->setPriority( -(float)key.getLevelOfDetail() ); job->_tasks.push_back( ej ); } return job; }
void TileBuilder::createTile | ( | const TileKey & | key, |
bool | parallelize, | ||
osg::ref_ptr< Tile > & | out_tile, | ||
bool & | out_hasRealData, | ||
bool & | out_hasLodBlendedLayers | ||
) |
Definition at line 304 of file TileBuilder.cpp.
{ MapFrame mapf( _map, Map::MASKED_TERRAIN_LAYERS ); SourceRepo repo; // init this to false, then search for real data. "Real data" is data corresponding // directly to the key, as opposed to fallback data, which is derived from a lower // LOD key. out_hasRealData = false; out_hasLodBlendedLayers = false; const MapInfo& mapInfo = mapf.getMapInfo(); // If we need more than one layer, fetch them in parallel. // TODO: change the test based on isKeyValid total. if ( parallelize && (mapf.imageLayers().size() + mapf.elevationLayers().size() > 1) ) { // count the valid layers. int jobCount = 0; for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i ) { if ( i->get()->isKeyValid( key ) ) ++jobCount; if ( i->get()->getImageLayerOptions().lodBlending() == true ) out_hasLodBlendedLayers = true; } if ( mapf.elevationLayers().size() > 0 ) ++jobCount; // A thread job monitoring event: Threading::MultiEvent semaphore( jobCount ); // Start the image layer jobs: for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i ) { ImageLayer* layer = i->get(); if ( layer->isKeyValid(key) ) { ParallelTask<BuildColorLayer>* j = new ParallelTask<BuildColorLayer>( &semaphore ); j->init( key, layer, mapInfo, _terrainOptions, repo ); j->setPriority( -(float)key.getLevelOfDetail() ); _service->add( j ); } } // If we have elevation layers, start an elevation job as well. Otherwise just create an // empty one while we're waiting for the images to load. if ( mapf.elevationLayers().size() > 0 ) { ParallelTask<BuildElevLayer>* ej = new ParallelTask<BuildElevLayer>( &semaphore ); ej->init( key, mapf, _terrainOptions, repo ); ej->setPriority( -(float)key.getLevelOfDetail() ); _service->add( ej ); } else { BuildElevLayer build; build.init( key, mapf, _terrainOptions, repo ); build.execute(); } // Wait for all the jobs to finish. semaphore.wait(); } // Fetch the image data serially: else { // gather all the image layers serially. for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i ) { ImageLayer* layer = i->get(); if ( layer->isKeyValid(key) ) { BuildColorLayer build; build.init( key, layer, mapInfo, _terrainOptions, repo ); build.execute(); } if ( layer->getImageLayerOptions().lodBlending() == true ) out_hasLodBlendedLayers = true; } // make an elevation layer. BuildElevLayer build; build.init( key, mapf, _terrainOptions, repo ); build.execute(); } // Bail out now if there's no data to be had. if ( repo._colorLayers.size() == 0 && !repo._elevLayer.getHFLayer() ) { return; } // OK we are making a tile, so if there's no heightfield yet, make an empty one. if ( !repo._elevLayer.getHFLayer() ) { osg::HeightField* hf = key.getProfile()->getVerticalSRS()->createReferenceHeightField( key.getExtent(), 8, 8 ); osgTerrain::HeightFieldLayer* hfLayer = new osgTerrain::HeightFieldLayer( hf ); hfLayer->setLocator( GeoLocator::createForKey(key, mapInfo) ); repo._elevLayer = CustomElevLayer( hfLayer, true ); } // Now, if there are any color layers that did not get built, create them with an empty // image so the shaders have something to draw. osg::ref_ptr<osg::Image> emptyImage; osgTerrain::Locator* locator = repo._elevLayer.getHFLayer()->getLocator(); for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i ) { if ( !i->get()->isKeyValid(key) ) { if ( !emptyImage.valid() ) emptyImage = ImageUtils::createEmptyImage(); repo.add( CustomColorLayer( i->get(), emptyImage.get(), locator, key.getLevelOfDetail(), key, true ) ); } } //osg::Vec3dArray* maskBounds = 0L; //osgEarth::MaskLayer* mask = mapf.getTerrainMaskLayer(); //if (mask) // maskBounds = mask->getOrCreateBoundary(); // Ready to create the actual tile. AssembleTile assemble; assemble.init( key, mapInfo, _terrainOptions, repo, mapf.terrainMaskLayers() ); assemble.execute(); if (!out_hasRealData) { // Check the results and see if we have any real data. for( ColorLayersByUID::const_iterator i = repo._colorLayers.begin(); i != repo._colorLayers.end(); ++i ) { if ( !i->second.isFallbackData() ) { out_hasRealData = true; break; } } } if ( !out_hasRealData && !repo._elevLayer.isFallbackData() ) { out_hasRealData = true; } out_tile = assemble._tile; }
void TileBuilder::finalizeJob | ( | TileBuilder::Job * | job, |
osg::ref_ptr< Tile > & | out_tile, | ||
bool & | out_hasRealData, | ||
bool & | out_hasLodBlending | ||
) |
Definition at line 229 of file TileBuilder.cpp.
{ SourceRepo& repo = job->_repo; out_hasRealData = false; out_hasLodBlending = false; // Bail out now if there's no data to be had. if ( repo._colorLayers.size() == 0 && !repo._elevLayer.getHFLayer() ) { return; } const TileKey& key = job->_key; const MapInfo& mapInfo = job->_mapf.getMapInfo(); // OK we are making a tile, so if there's no heightfield yet, make an empty one. if ( !repo._elevLayer.getHFLayer() ) { osg::HeightField* hf = key.getProfile()->getVerticalSRS()->createReferenceHeightField( key.getExtent(), 8, 8 ); osgTerrain::HeightFieldLayer* hfLayer = new osgTerrain::HeightFieldLayer( hf ); hfLayer->setLocator( GeoLocator::createForKey(key, mapInfo) ); repo._elevLayer = CustomElevLayer( hfLayer, true ); } // Now, if there are any color layers that did not get built, create them with an empty // image so the shaders have something to draw. osg::ref_ptr<osg::Image> emptyImage; osgTerrain::Locator* locator = repo._elevLayer.getHFLayer()->getLocator(); for( ImageLayerVector::const_iterator i = job->_mapf.imageLayers().begin(); i != job->_mapf.imageLayers().end(); ++i ) { if ( !i->get()->isKeyValid(key) ) { if ( !emptyImage.valid() ) emptyImage = ImageUtils::createEmptyImage(); repo.add( CustomColorLayer( i->get(), emptyImage.get(), locator, key.getLevelOfDetail(), key, true ) ); } if ( i->get()->getImageLayerOptions().lodBlending() == true ) out_hasLodBlending = true; } // Ready to create the actual tile. AssembleTile assemble; assemble.init( key, mapInfo, _terrainOptions, repo ); assemble.execute(); // Check the results and see if we have any real data. for( ColorLayersByUID::const_iterator i = repo._colorLayers.begin(); i != repo._colorLayers.end(); ++i ) { if ( !i->second.isFallbackData() ) { out_hasRealData = true; break; } } if ( !out_hasRealData && !repo._elevLayer.isFallbackData() ) { out_hasRealData = true; } out_tile = assemble._tile; }
TaskService* TileBuilder::getTaskService | ( | ) | const [inline] |
Definition at line 87 of file TileBuilder.
{ return _service; }
void TileBuilder::runJob | ( | TileBuilder::Job * | job | ) |
const Map* TileBuilder::_map [private] |
Definition at line 90 of file TileBuilder.
TaskService* TileBuilder::_service [private] |
Definition at line 91 of file TileBuilder.
const OSGTerrainOptions& TileBuilder::_terrainOptions [private] |
Definition at line 92 of file TileBuilder.