osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/engine_osgterrain/StreamingTile.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 "StreamingTile"
00020 #include "StreamingTerrain"
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 using namespace osgEarth;
00038 using namespace OpenThreads;
00039 
00040 #define LC "[StreamingTile] "
00041 
00042 //----------------------------------------------------------------------------
00043 
00044 namespace
00045 {
00046     // this progress callback checks to see whether the request being serviced is 
00047     // out of date with respect to the task service that is running it. It checks
00048     // for a disparity in frame stamps, and reports that the request should be
00049     // canceled if it appears the request has been abandoned by the Tile that
00050     // originally scheduled it.
00051     struct StampedProgressCallback : ProgressCallback
00052     {
00053     public:
00054         StampedProgressCallback(TaskRequest* request, TaskService* service):
00055           _request(request),
00056           _service(service)
00057         {
00058         }
00059 
00060         //todo: maybe we should pass TaskRequest in as an argument 
00061         bool reportProgress(double current, double total)
00062         {
00063             //Check to see if we were marked cancelled on a previous check
00064             if (_canceled) return _canceled;
00065 
00066             _canceled = (_service->getStamp() - _request->getStamp() > 2);
00067             return _canceled;
00068         }
00069 
00070         TaskRequest* _request;
00071         TaskService* _service;
00072     };
00073 
00074 
00075     // NOTE: Task requests run in background threads. So we pass in a map frame and
00076     // make a clone of it to use in that thread. Each Task must have its own MapFrame
00077     // so it's operating in its own sandbox.
00078 
00079     struct TileLayerRequest : public TaskRequest
00080     {
00081         TileLayerRequest( const TileKey& key, const MapFrame& mapf, OSGTileFactory* tileFactory )
00082             : _key( key ), 
00083               _mapf(mapf, "osgterrain.TileLayerRequest"), 
00084               _tileFactory(tileFactory), 
00085               _numTries(0), 
00086               _maxTries(3) { }
00087 
00088         TileKey _key;
00089         MapFrame _mapf;
00090         //osg::ref_ptr<Map> _map;
00091         osg::ref_ptr<OSGTileFactory> _tileFactory;
00092             unsigned int _numTries;
00093             unsigned int _maxTries;
00094     };
00095 
00096     struct TileColorLayerRequest : public TileLayerRequest
00097     {
00098         TileColorLayerRequest( const TileKey& key, const MapFrame& mapf, OSGTileFactory* tileFactory, UID layerUID )
00099             : TileLayerRequest( key, mapf, tileFactory ), _layerUID(layerUID) { }
00100 
00101         void operator()( ProgressCallback* progress )
00102         {
00103             osg::ref_ptr<ImageLayer> imageLayer = _mapf.getImageLayerByUID( _layerUID );
00104             if ( imageLayer.valid() )
00105             {
00106                 _result = _tileFactory->createImageLayer( _mapf.getMapInfo(), imageLayer.get(), _key, progress );
00107                             if (!wasCanceled())
00108                             {
00109                               _numTries++;
00110                             }
00111             }
00112         }
00113         UID _layerUID;
00114     };
00115 
00116     struct TileElevationLayerRequest : public TileLayerRequest
00117     {
00118         TileElevationLayerRequest( const TileKey& key, const MapFrame& mapf, OSGTileFactory* tileFactory )
00119             : TileLayerRequest( key, mapf, tileFactory )
00120         {
00121             //nop
00122         }
00123 
00124         void operator()( ProgressCallback* progress )
00125         {
00126             _result = _tileFactory->createHeightFieldLayer( _mapf, _key, true ); //exactOnly=true
00127                     _numTries++;
00128         }
00129     };
00130 
00131     struct TileElevationPlaceholderLayerRequest : public TileLayerRequest
00132     {
00133         TileElevationPlaceholderLayerRequest( const TileKey& key, const MapFrame& mapf, OSGTileFactory* tileFactory, GeoLocator* keyLocator )
00134             : TileLayerRequest( key, mapf, tileFactory ),
00135               _parentKey( key.createParentKey() ),
00136               _keyLocator(keyLocator)
00137         {
00138             //nop
00139         }
00140 
00141         void setParentHF( osg::HeightField* parentHF )
00142         {
00143             _parentHF = parentHF; 
00144         }
00145 
00146         void setNextLOD( int nextLOD )
00147         {
00148             _nextLOD = nextLOD;
00149         }
00150 
00151         void operator()( ProgressCallback* progress )
00152         {
00153             if ( !progress->isCanceled() )
00154             {
00155                 _result = _tileFactory->createPlaceholderHeightfieldLayer(
00156                     _parentHF.get(),
00157                     _parentKey,
00158                     _key,
00159                     _keyLocator.get() );
00160             }
00161         }
00162 
00163         osg::ref_ptr<osg::HeightField> _parentHF;
00164         TileKey _parentKey;
00165         osg::ref_ptr<GeoLocator>    _keyLocator;
00166         int _nextLOD;
00167     };
00168 
00169     // A task request that rebuilds a tile's terrain technique in the background. It
00170     // re-compiles the geometry but does NOT apply the updates (since this constitutes
00171     // altering the scene graph and must therefore be done in the update traversal).
00172     struct TileGenRequest : public TaskRequest
00173     {
00174         TileGenRequest( StreamingTile* tile, const TileUpdate& update ) :
00175             _tile( tile ), _update(update) { }
00176 
00177         void operator()( ProgressCallback* progress )
00178         {
00179             if (_tile.valid())
00180             {
00181                 CustomTerrainTechnique* tech = dynamic_cast<CustomTerrainTechnique*>( _tile->getTerrainTechnique() );
00182                 if (tech)
00183                 {
00184                     tech->compile( _update, progress );
00185                 }
00186             }
00187 
00188             //We don't need the tile anymore
00189             _tile = NULL;
00190         }
00191 
00192         osg::ref_ptr< StreamingTile > _tile;
00193         TileUpdate _update;
00194     };
00195 }
00196 
00197 //------------------------------------------------------------------------
00198 
00199 StreamingTile::StreamingTile(const TileKey& key,
00200                              GeoLocator*    keyLocator, 
00201                              bool           quickReleaseGLObjects ) :
00202 
00203 Tile( key, keyLocator, quickReleaseGLObjects ),
00204 
00205 _requestsInstalled     ( false ),
00206 _elevationLayerDirty   ( false ),
00207 _colorLayersDirty      ( false ),
00208 _elevationLayerUpToDate( true ),
00209 _elevationLOD          ( key.getLevelOfDetail() ),
00210 _useTileGenRequest     ( true )
00211 {
00212     // because the lowest LOD (1) is always loaded fully:
00213     _elevationLayerUpToDate = _key.getLevelOfDetail() <= 1;
00214 }
00215 
00216 StreamingTile::~StreamingTile()
00217 {
00218     //nop
00219 }
00220 
00221 bool
00222 StreamingTile::cancelActiveTasks()
00223 {
00224     // This method ensures that all requests owned by this object are stopped and released
00225     // by the corresponding task service prior to destructing the tile. Called by
00226     // CustomTerrain::updateTileTable().
00227 
00228     bool done = true;
00229 
00230     // Cancel all active requests
00231     if ( _requestsInstalled )
00232     {
00233         for( TaskRequestList::iterator i = _requests.begin(); i != _requests.end(); ++i )
00234         {
00235             i->get()->cancel();
00236         }
00237 
00238         if ( _elevRequest.valid() )
00239         {
00240             _elevRequest->cancel();
00241         }
00242 
00243         if (_elevPlaceholderRequest.valid())
00244         {
00245             _elevPlaceholderRequest->cancel();
00246         }
00247 
00248         if (_tileGenRequest.valid())
00249         {
00250             _tileGenRequest->cancel();
00251         }
00252     }
00253 
00254     return done;
00255 }
00256 
00257 void
00258 StreamingTile::setElevationLOD( int lod )
00259 {
00260     _elevationLOD = lod;
00261     _elevationLayerUpToDate = _elevationLOD == (int)_key.getLevelOfDetail();
00262 }
00263 
00264 StreamingTerrain*
00265 StreamingTile::getStreamingTerrain()
00266 {
00267     return static_cast<StreamingTerrain*>( getTerrain() );
00268 }
00269 
00270 const StreamingTerrain*
00271 StreamingTile::getStreamingTerrain() const
00272 {
00273     return const_cast<StreamingTile*>(this)->getStreamingTerrain();
00274 }
00275 
00276 void
00277 StreamingTile::setHasElevationHint( bool hint ) 
00278 {
00279     _hasElevation = hint;
00280 }
00281 
00282 // returns TRUE if it's safe for this tile to load its next elevation data layer.
00283 bool
00284 StreamingTile::readyForNewElevation()
00285 {
00286     bool ready = true;
00287 
00288     if ( _elevationLOD == (int)_key.getLevelOfDetail() )
00289     {
00290         ready = false;
00291     }
00292     else if ( _family[Relative::PARENT].elevLOD < 0 )
00293     {
00294         ready = false;
00295     }
00296     else
00297     {
00298         for( int i=Relative::PARENT; i<=Relative::SOUTH; i++) 
00299         {
00300             if ( _family[i].expected && _family[i].elevLOD >= 0 && _family[i].elevLOD < _elevationLOD )
00301             {
00302                 ready = false;
00303                 break;
00304             }
00305         }
00306 
00307         // if the next LOD is not the final, but our placeholder is up to date, we're not ready.
00308         if ( ready && _elevationLOD+1 < (int)_key.getLevelOfDetail() && _elevationLOD == _family[Relative::PARENT].elevLOD )
00309         {
00310             ready = false;
00311         }
00312     }
00313 
00314 #ifdef PREEMPTIVE_DEBUG
00315     OE_NOTICE
00316         << "Tile (" << _key.str() << ") at (" << _elevationLOD << "), parent at ("
00317         << _family[PARENT].elevLOD << "), sibs at (";
00318     if ( _family[WEST].expected ) osg::notify( osg::NOTICE ) << "W=" << _family[WEST].elevLOD << " ";
00319     if ( _family[NORTH].expected ) osg::notify( osg::NOTICE ) << "N=" << _family[NORTH].elevLOD << " ";
00320     if ( _family[EAST].expected ) osg::notify( osg::NOTICE ) << "E=" << _family[EAST].elevLOD << " ";
00321     if ( _family[SOUTH].expected ) osg::notify( osg::NOTICE ) << "S=" << _family[SOUTH].elevLOD << " ";
00322     OE_NOTICE << "), ready = " << (ready? "YES" : "no") << std::endl;
00323 #endif
00324 
00325     return ready;
00326 }
00327 
00328 
00329 
00330 // returns TRUE if it's safe for this tile to load its next elevation data layer.
00331 bool
00332 StreamingTile::readyForNewImagery(ImageLayer* layer, int currentLOD)
00333 {
00334     bool ready = true;
00335 
00336     if ( currentLOD == (int)_key.getLevelOfDetail() )
00337     {
00338         ready = false;
00339     }
00340     else if ( _family[Relative::PARENT].getImageLOD( layer->getUID() ) < 0 )
00341     {
00342         ready = false;
00343     }
00344     else
00345     {
00346         for( int i=Relative::PARENT; i<=Relative::SOUTH; i++) 
00347         {
00348             if (_family[i].expected && 
00349                 _family[i].getImageLOD( layer->getUID() ) >= 0 && 
00350                 _family[i].getImageLOD( layer->getUID() ) < currentLOD )
00351             {
00352                 ready = false;
00353                 break;
00354             }
00355         }
00356 
00357         // if the next LOD is not the final, but our placeholder is up to date, we're not ready.
00358         if (ready &&
00359             currentLOD + 1 < (int)_key.getLevelOfDetail() && 
00360             currentLOD == _family[Relative::PARENT].getImageLOD( layer->getUID() ) )
00361         {
00362             ready = false;
00363         }
00364     }
00365 
00366     return ready;
00367 }
00368 
00369 
00370 #define PRI_IMAGE_OFFSET 0.1f // priority offset of imagery relative to elevation
00371 #define PRI_LAYER_OFFSET 0.1f // priority offset of image layer(x) vs. image layer(x+1)
00372 
00373 void
00374 StreamingTile::installRequests( const MapFrame& mapf, int stamp )
00375 {
00376     StreamingTerrain* terrain     = getStreamingTerrain();
00377     OSGTileFactory*   tileFactory = terrain->getTileFactory();
00378 
00379     bool hasElevationLayer;
00380     {
00381         Threading::ScopedReadLock sharedLock( _tileLayersMutex );
00382         hasElevationLayer = this->getElevationLayer() != NULL;
00383     }
00384 
00385     if ( hasElevationLayer )
00386     {
00387         resetElevationRequests( mapf );     
00388     }
00389 
00390     // safely loop through the map layers and schedule imagery updates for each:
00391     for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i )
00392     {
00393         updateImagery( i->get(), mapf, tileFactory );
00394     }
00395 
00396     _requestsInstalled = true;
00397 }
00398 
00399 void
00400 StreamingTile::resetElevationRequests( const MapFrame& mapf )
00401 {
00402     if (_elevRequest.valid() && _elevRequest->isRunning()) _elevRequest->cancel();
00403     if (_elevPlaceholderRequest.valid() && _elevPlaceholderRequest->isRunning()) _elevPlaceholderRequest->cancel();
00404 
00405     StreamingTerrain* terrain = getStreamingTerrain();
00406 
00407     // this request will load real elevation data for the tile:
00408     _elevRequest = new TileElevationLayerRequest(_key, mapf, terrain->getTileFactory());
00409     float priority = (float)_key.getLevelOfDetail();
00410     _elevRequest->setPriority( priority );
00411     std::stringstream ss;
00412     ss << "TileElevationLayerRequest " << _key.str() << std::endl;
00413         std::string ssStr;
00414         ssStr = ss.str();
00415     _elevRequest->setName( ssStr );
00416 
00417     // this request will load placeholder elevation data for the tile:
00418     _elevPlaceholderRequest = new TileElevationPlaceholderLayerRequest(
00419         _key, mapf, terrain->getTileFactory(), _locator.get() );
00420 
00421     _elevPlaceholderRequest->setPriority( priority );
00422     ss.str("");
00423     ss << "TileElevationPlaceholderLayerRequest " << _key.str() << std::endl;
00424         ssStr = ss.str();
00425     _elevPlaceholderRequest->setName( ssStr );
00426 }
00427 
00428 
00429 // called from installRequests (cull traversal) or terrainengine (main thread) ... so be careful!
00430 //
00431 // this method queues up a new tile imagery request, superceding any existing request that
00432 // might be in the queue.
00433 void
00434 StreamingTile::updateImagery( ImageLayer* imageLayer, const MapFrame& mapf, OSGTileFactory* tileFactory)
00435 {
00436     StreamingTerrain* terrain = getStreamingTerrain();
00437 
00438     // imagery is slighty higher priority than elevation data
00439     TaskRequest* r = new TileColorLayerRequest( _key, mapf, tileFactory, imageLayer->getUID() );
00440     std::stringstream ss;
00441     ss << "TileColorLayerRequest " << _key.str() << std::endl;
00442     std::string ssStr;
00443     ssStr = ss.str();
00444     r->setName( ssStr );
00445     r->setState( osgEarth::TaskRequest::STATE_IDLE );
00446 
00447     // in image-sequential mode, we want to prioritize lower-LOD imagery since it
00448     // needs to come in before higher-resolution stuff. 
00449     if ( terrain->getLoadingPolicy().mode() == LoadingPolicy::MODE_SEQUENTIAL )
00450     {
00451         r->setPriority( -(float)_key.getLevelOfDetail() + PRI_IMAGE_OFFSET );
00452     }
00453 
00454     // in image-preemptive mode, the highest LOD should get higher load priority:
00455     else // MODE_PREEMPTIVE
00456     {
00457         r->setPriority( PRI_IMAGE_OFFSET + (float)_key.getLevelOfDetail());
00458     }
00459 
00460     r->setProgressCallback( new StampedProgressCallback( 
00461         r,
00462         terrain->getImageryTaskService( imageLayer->getUID() ) ) );
00463 
00464     //If we already have a request for this layer, remove it from the list and use the new one
00465     for( TaskRequestList::iterator i = _requests.begin(); i != _requests.end(); )
00466     {
00467         TileColorLayerRequest* r2 = static_cast<TileColorLayerRequest*>( i->get() );
00468         if ( r2->_layerUID == imageLayer->getUID() )
00469             i = _requests.erase( i );
00470         else
00471             ++i;
00472     }
00473 
00474     //Add the new imagery request
00475     _requests.push_back( r );
00476 }
00477 
00478 // This method is called during the UPDATE TRAVERSAL in StreamingTerrain.
00479 void
00480 StreamingTile::servicePendingImageRequests( const MapFrame& mapf, int stamp )
00481 {       
00482     // Don't do anything until we have been added to the scene graph
00483     if ( !_hasBeenTraversed ) return;
00484 
00485     // install our requests if they are not already installed:
00486     if ( !_requestsInstalled )
00487     {
00488         // since we're in the CULL thread, use the cull thread map frame:
00489         installRequests( mapf, stamp );
00490     }
00491 
00492     for( TaskRequestList::iterator i = _requests.begin(); i != _requests.end(); ++i )
00493     {
00494         TileColorLayerRequest* r = static_cast<TileColorLayerRequest*>( i->get() );
00495 
00496         //If a request has been marked as IDLE, the TaskService has tried to service it
00497         //and it was either deemed out of date or was cancelled, so we need to add it again.
00498         if ( r->isIdle() )
00499         {
00500             //OE_NOTICE << "Queuing IR (" << _key.str() << ")" << std::endl;
00501             r->setStamp( stamp );
00502             getStreamingTerrain()->getImageryTaskService( r->_layerUID )->add( r );
00503         }
00504         else if ( !r->isCompleted() )
00505         {
00506             r->setStamp( stamp );
00507         }
00508     }    
00509 }
00510 
00511 // This method is called from the UPDATE TRAVERSAL, from CustomTerrain::traverse.
00512 void
00513 StreamingTile::servicePendingElevationRequests( const MapFrame& mapf, int stamp, bool tileTableLocked )
00514 {
00515     //Don't do anything until we have been added to the scene graph
00516     if ( !_hasBeenTraversed ) return;
00517 
00518     // install our requests if they are not already installed:
00519     if ( !_requestsInstalled )
00520     {
00521         installRequests( mapf, stamp );
00522     }
00523 
00524     if ( _hasElevation && !_elevationLayerUpToDate && _elevRequest.valid() && _elevPlaceholderRequest.valid() )
00525     {  
00526         StreamingTerrain* terrain = getStreamingTerrain();
00527 
00528         // update the main elevation request if it's running:
00529         if ( !_elevRequest->isIdle() )
00530         {
00531 #ifdef PREEMPTIVE_DEBUG
00532             OE_NOTICE << "Tile (" << _key.str() << ") .. ER not idle" << std::endl;
00533 #endif
00534             
00535             if ( !_elevRequest->isCompleted() )
00536             {
00537                 _elevRequest->setStamp( stamp );
00538             }
00539         }
00540 
00541         // update the placeholder request if it's running:
00542         else if ( !_elevPlaceholderRequest->isIdle() )
00543         {
00544 #ifdef PREEMPTIVE_DEBUG
00545             OE_NOTICE << "Tile (" << _key.str() << ") .. PR not idle" << std::endl;
00546 #endif
00547             if ( !_elevPlaceholderRequest->isCompleted() )
00548             {
00549                _elevPlaceholderRequest->setStamp( stamp );
00550             }
00551         }
00552 
00553         // otherwise, see if it is legal yet to start a new request:
00554         else if ( readyForNewElevation() )
00555         {
00556             if ( _elevationLOD + 1 == _key.getLevelOfDetail() )
00557             {
00558                 _elevRequest->setStamp( stamp );
00559                 _elevRequest->setProgressCallback( new ProgressCallback() );
00560                 terrain->getElevationTaskService()->add( _elevRequest.get() );
00561 #ifdef PREEMPTIVE_DEBUG
00562                 OE_NOTICE << "..queued FE req for (" << _key.str() << ")" << std::endl;
00563 #endif
00564             }
00565             
00566             else if ( _family[Relative::PARENT].elevLOD > _elevationLOD )
00567             {
00568                 osg::ref_ptr<StreamingTile> parentTile;
00569                 terrain->getTile( _family[Relative::PARENT].tileID, parentTile, !tileTableLocked );
00570 
00571                 if ( _elevationLOD < _family[Relative::PARENT].elevLOD && parentTile.valid() )
00572                 {
00573                     TileElevationPlaceholderLayerRequest* er = static_cast<TileElevationPlaceholderLayerRequest*>(_elevPlaceholderRequest.get());
00574 
00575                     er->setStamp( stamp );
00576                     er->setProgressCallback( new ProgressCallback() );
00577                     float priority = (float)_key.getLevelOfDetail();
00578                     er->setPriority( priority );
00579                     //TODO: should there be a read lock here when accessing the parent tile's elevation layer? GW
00580                     osgTerrain::HeightFieldLayer* hfLayer = static_cast<osgTerrain::HeightFieldLayer*>(parentTile->getElevationLayer());
00581                     er->setParentHF( hfLayer->getHeightField() );
00582                     er->setNextLOD( _family[Relative::PARENT].elevLOD );
00583                     terrain->getElevationTaskService()->add( er );
00584 #ifdef PREEMPTIVE_DEBUG
00585                     OE_NOTICE << "..queued PH req for (" << _key.str() << ")" << std::endl;
00586 #endif
00587                 }
00588 
00589                 else 
00590                 {
00591 #ifdef PREEMPTIVE_DEBUG
00592                     OE_NOTICE << "...tile (" << _key.str() << ") ready, but nothing to do." << std::endl;
00593 #endif
00594                 }
00595             }
00596         }
00597     }
00598 }
00599 
00600 void
00601 StreamingTile::queueTileUpdate( TileUpdate::Action action, int value )
00602 {
00603     if ( _useTileGenRequest )
00604     {
00605         _tileUpdates.push( TileUpdate(action, value) );
00606     }
00607     else
00608     {
00609         Tile::queueTileUpdate( action, value );
00610     }
00611 }
00612 
00613 // called from the UPDATE TRAVERSAL, because this method can potentially alter
00614 // the scene graph.
00615 bool
00616 StreamingTile::serviceCompletedRequests( const MapFrame& mapf, bool tileTableLocked )
00617 {
00618     //Don't do anything until we have been added to the scene graph
00619     if (!_hasBeenTraversed) return false;
00620 
00621     bool tileModified = false;
00622 
00623     if ( !_requestsInstalled )
00624         return false;
00625 
00626     // First service the tile generator:
00627     if ( _tileGenRequest.valid() && _tileGenRequest->isCompleted() )
00628     {
00629         CustomTerrainTechnique* tech = dynamic_cast<CustomTerrainTechnique*>( getTerrainTechnique() );
00630         if ( tech )
00631         {
00632             //TODO: consider waiting to apply if there are still more tile updates in the queue.
00633             if ( _tileUpdates.size() == 0 )
00634             {
00635                 tileModified = tech->applyTileUpdates();
00636             }
00637         }
00638         _tileGenRequest = 0L;
00639     }
00640 
00641 
00642     // now deal with imagery.
00643     const LoadingPolicy& lp = getStreamingTerrain()->getLoadingPolicy();
00644 
00645     StreamingTerrain* terrain = getStreamingTerrain();
00646 
00647     //Check each layer independently.
00648     for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); ++i )
00649     {
00650         ImageLayer* imageLayer = i->get();
00651 
00652         bool checkForFinalImagery = false;
00653 
00654         CustomColorLayer colorLayer;
00655         if ( getCustomColorLayer( imageLayer->getUID(), colorLayer ) )
00656         {
00657             if ( lp.mode() == LoadingPolicy::MODE_PREEMPTIVE )
00658             {
00659                 // in preemptive mode, always check for the final imagery - there are no intermediate
00660                 // placeholders.
00661                 checkForFinalImagery = true;
00662             }
00663             else if (lp.mode() == LoadingPolicy::MODE_SEQUENTIAL && 
00664                      readyForNewImagery(imageLayer, colorLayer.getLevelOfDetail()) )
00665             {
00666                 // in sequential mode, we have to incrementally increase imagery resolution by
00667                 // creating placeholders based of parent tiles, one LOD at a time.
00668                 if ( colorLayer.getLevelOfDetail() + 1 < (int)_key.getLevelOfDetail() )
00669                 {
00670                     // if the parent's image LOD is higher than ours, replace ours with the parent's
00671                     // since it is a higher-resolution placeholder:
00672                     if ( _family[Relative::PARENT].getImageLOD(colorLayer.getUID()) > colorLayer.getLevelOfDetail() )
00673                     {
00674                         osg::ref_ptr<Tile> parentTile;
00675                         getStreamingTerrain()->getTile( _family[Relative::PARENT].tileID, parentTile, !tileTableLocked );
00676 
00677                         // Set the color layer to the parent color layer as a placeholder.
00678                         CustomColorLayer parentColorLayer;
00679                         if ( parentTile->getCustomColorLayer( colorLayer.getUID(), parentColorLayer ) )
00680                         {
00681                             this->setCustomColorLayer( parentColorLayer );
00682                         }
00683 
00684                         // ... and queue up an update request.
00685                         queueTileUpdate( TileUpdate::UPDATE_IMAGE_LAYER, colorLayer.getUID() );
00686                     }
00687                 }
00688                 else
00689                 {
00690                     // we've gone as far as we can with placeholders; time to check for the
00691                     // final imagery tile.
00692                     checkForFinalImagery = true;
00693                 }
00694             }
00695         }
00696 
00697         if ( checkForFinalImagery )
00698         {
00699             // Then the image requests:
00700             for( TaskRequestList::iterator itr = _requests.begin(); itr != _requests.end(); )
00701             {
00702                 bool increment = true;
00703                 TileColorLayerRequest* r = static_cast<TileColorLayerRequest*>( itr->get() );
00704                 //We only care about the current layer we are checking
00705                 if ( r->_layerUID == imageLayer->getUID() )
00706                 {
00707                     if ( itr->get()->isCompleted() )
00708                     {
00709                         if ( r->wasCanceled() )
00710                         {
00711                             //Reset the cancelled task to IDLE and give it a new progress callback.
00712                             r->setState( TaskRequest::STATE_IDLE );
00713                             r->setProgressCallback( new StampedProgressCallback(
00714                                 r, terrain->getImageryTaskService( r->_layerUID )));
00715                             r->reset();
00716                         }
00717                         else // success..
00718                         {
00719                             //See if we even care about the request
00720                             if ( !mapf.getImageLayerByUID( r->_layerUID ) )
00721                             {
00722                                 //The maplayer was probably deleted
00723                                 OE_DEBUG << "Layer uid=" << r->_layerUID << " no longer exists, ignoring TileColorLayerRequest " << std::endl;
00724                                 itr = _requests.erase(itr);
00725                                 increment = false;
00726                             }
00727                             else
00728                             {
00729                                 CustomColorLayerRef* result = static_cast<CustomColorLayerRef*>( r->getResult() );
00730                                 if ( result )
00731                                 {
00732                                     this->setCustomColorLayer( result->_layer );
00733 
00734                                     queueTileUpdate( TileUpdate::UPDATE_IMAGE_LAYER, r->_layerUID );
00735 
00736                                     //OE_NOTICE << "Complete IR (" << _key.str() << ") layer=" << r->_layerId << std::endl;
00737 
00738                                     // remove from the list (don't reference "r" after this!)
00739                                     itr = _requests.erase( itr );
00740                                     increment = false;
00741                                 }
00742                                 else
00743                                 {  
00744                                     if (r->_numTries > r->_maxTries)
00745                                     {
00746                                         CustomColorLayer oldLayer;
00747                                         if ( this->getCustomColorLayer( r->_layerUID, oldLayer ) )
00748                                         {
00749                                             // apply the old color layer but with a new LOD.
00750                                             this->setCustomColorLayer( CustomColorLayer(
00751                                                 oldLayer.getMapLayer(),
00752                                                 oldLayer.getImage(),
00753                                                 oldLayer.getLocator(),
00754                                                 _key.getLevelOfDetail(),
00755                                                 _key ));
00756 
00757                                             itr = _requests.erase( itr );
00758                                             increment = false;
00759                                             OE_DEBUG << "Tried (" << _key.str() << ") (layer uid=" << r->_layerUID << "), too many times, moving on...." << std::endl;
00760                                         }
00761                                     }
00762                                     else
00763                                     {
00764                                         OE_DEBUG << "IReq error (" << _key.str() << ") (layer uid=" << r->_layerUID << "), retrying" << std::endl;
00765 
00766                                         //The color layer request failed, probably due to a server error. Reset it.
00767                                         r->setState( TaskRequest::STATE_IDLE );
00768                                         r->reset();
00769                                     }
00770                                 }
00771                             }
00772                         }
00773                     }
00774                 }
00775 
00776                 if ( increment )
00777                     ++itr;
00778             }
00779         }
00780     }
00781 
00782     // Finally, the elevation requests:
00783     if ( _hasElevation && !_elevationLayerUpToDate && _elevRequest.valid() && _elevPlaceholderRequest.valid() )
00784     {
00785         // First, check is the Main elevation request is done. If so, we will now have the final HF data
00786         // and can shut down the elevation requests for this tile.
00787         if ( _elevRequest->isCompleted() )
00788         {
00789             if ( _elevRequest->wasCanceled() )
00790             {
00791                 // If the request was canceled, reset it to IDLE and reset the callback. On the next
00792                 _elevRequest->setState( TaskRequest::STATE_IDLE );
00793                 _elevRequest->setProgressCallback( new ProgressCallback() );            
00794                 _elevRequest->reset();
00795             }
00796             else // success:
00797             {
00798                 // if the elevation request succeeded, install the new elevation layer!
00799                 TileElevationLayerRequest* r = static_cast<TileElevationLayerRequest*>( _elevRequest.get() );
00800                 osg::ref_ptr<osgTerrain::HeightFieldLayer> newHFLayer = static_cast<osgTerrain::HeightFieldLayer*>( r->getResult() );
00801                 if ( newHFLayer.valid() && newHFLayer->getHeightField() != NULL )
00802                 {
00803                     newHFLayer->getHeightField()->setSkirtHeight( 
00804                         terrain->getTileFactory()->getTerrainOptions().heightFieldSkirtRatio().get() *
00805                         this->getBound().radius() );
00806 
00807                     // need to write-lock the layer data since we'll be changing it:
00808                     {
00809                         Threading::ScopedWriteLock lock( _tileLayersMutex );
00810                         this->setElevationLayer( newHFLayer.get() );
00811                         this->dirtyBound();
00812                     }
00813 
00814                     // the tile needs rebuilding. This will kick off a TileGenRequest.
00815                     queueTileUpdate( TileUpdate::UPDATE_ELEVATION );
00816 
00817                     // finalize the LOD marker for this tile, so other tiles can see where we are.
00818                     _elevationLOD = _key.getLevelOfDetail();
00819 
00820     #ifdef PREEMPTIVE_DEBUG
00821                     OE_NOTICE << "Tile (" << _key.str() << ") final HF, LOD (" << _elevationLOD << ")" << std::endl;
00822     #endif
00823                     // this was the final elev request, so mark elevation as DONE.
00824                     _elevationLayerUpToDate = true;
00825 
00826                     // GW- just reset these and leave them alone and let cancelRequests() take care of cleanup later.
00827                     // done with our Elevation requests!
00828                     //_elevRequest = 0L;
00829                     //_elevPlaceholderRequest = 0L;
00830                 }
00831                 else
00832                 {
00833                     //We've tried to get the tile's elevation but couldn't.  Just mark the elevation layer as up to date and move on.
00834                     _elevationLOD = _key.getLevelOfDetail();
00835                     _elevationLayerUpToDate = true;
00836 
00837                     //This code will retry indefinitely.  We need to have a way to limit the number of retries since
00838                     //it will block neighbor tiles from loading.
00839                     //_elevRequest->setState( TaskRequest::STATE_IDLE );
00840                     //_elevRequest->reset();
00841                 }
00842             }
00843         }
00844 
00845         else if ( _elevPlaceholderRequest->isCompleted() )
00846         {
00847             TileElevationPlaceholderLayerRequest* r = 
00848                 static_cast<TileElevationPlaceholderLayerRequest*>(_elevPlaceholderRequest.get());
00849 
00850             if ( r->wasCanceled() )
00851             {
00852                 r->setState( TaskRequest::STATE_IDLE );
00853                 r->setProgressCallback( new ProgressCallback() );
00854                 r->reset();
00855             }
00856             else // success:
00857             {
00858                 osg::ref_ptr<osgTerrain::HeightFieldLayer> newPhLayer = static_cast<osgTerrain::HeightFieldLayer*>( r->getResult() );
00859                 if ( newPhLayer.valid() && newPhLayer->getHeightField() != NULL )
00860                 {
00861                     // install the new elevation layer.
00862                     {
00863                         Threading::ScopedWriteLock lock( _tileLayersMutex );
00864                         this->setElevationLayer( newPhLayer.get() );
00865                         this->dirtyBound();
00866                     }
00867 
00868                     // tile needs to be recompiled.
00869                     queueTileUpdate( TileUpdate::UPDATE_ELEVATION );
00870 
00871                     // update the elevation LOD for this tile, now that the new HF data is installed. This will
00872                     // allow other tiles to see where this tile's HF data is.
00873                     _elevationLOD = r->_nextLOD;
00874 
00875     #ifdef PREEMPTIVE_DEBUG
00876                     OE_NOTICE << "..tile (" << _key.str() << ") is now at (" << _elevationLOD << ")" << std::endl;
00877     #endif
00878                 }
00879                 _elevPlaceholderRequest->setState( TaskRequest::STATE_IDLE );
00880                 _elevPlaceholderRequest->reset();
00881             }
00882         }
00883     }
00884 
00885     // if we have a new TileGenRequest, queue it up now.
00886     if ( _tileUpdates.size() > 0 && !_tileGenRequest.valid() ) // _tileGenNeeded && !_tileGenRequest.valid())
00887     {
00888         _tileGenRequest = new TileGenRequest( this, _tileUpdates.front() );
00889         _tileUpdates.pop();
00890         //OE_NOTICE << "tile (" << _key.str() << ") queuing new tile gen" << std::endl;
00891         getStreamingTerrain()->getTileGenerationTaskService()->add( _tileGenRequest.get() );
00892     }
00893 
00894     return tileModified;
00895 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines