From: James Turner Date: Fri, 1 Oct 2010 18:09:19 +0000 (+0100) Subject: Make the tile-manager a well-behaved SGSubsystem X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=0beab94cb5fec7c58015271658a6233260c25d02;p=flightgear.git Make the tile-manager a well-behaved SGSubsystem --- diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 58db48478..f117810c1 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -421,7 +421,7 @@ void FGAIAircraft::getGroundElev(double dt) { double range = 500.0; if (!globals->get_tile_mgr()->scenery_available(pos, range)) { // Try to shedule tiles for that position. - globals->get_tile_mgr()->update( pos, range ); + globals->get_tile_mgr()->schedule_tiles_at( pos, range ); } double alt; diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 1fe2c4ce4..74551bc91 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -556,15 +556,9 @@ do_tile_cache_reload (const SGPropertyNode * arg) if ( !freeze ) { fgSetBool("/sim/freeze/master", true); } - if ( globals->get_tile_mgr()->init() ) { - // Load the local scenery data - double visibility_meters = fgGetDouble("/environment/visibility-m"); - globals->get_tile_mgr()->update( visibility_meters ); - } else { - SG_LOG( SG_GENERAL, SG_ALERT, - "Error in Tile Manager initialization!" ); - exit(-1); - } + + globals->get_subsystem("tile-manager")->reinit(); + if ( !freeze ) { fgSetBool("/sim/freeze/master", false); } @@ -1241,8 +1235,6 @@ do_presets_commit (const SGPropertyNode * arg) fgReInitSubsystems(); - globals->get_tile_mgr()->update( fgGetDouble("/environment/visibility-m") ); - #if 0 if ( ! fgGetBool("/sim/presets/onground") ) { fgSetBool( "/sim/freeze/master", true ); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 38c4d8ee5..c62e96eaf 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -1321,14 +1321,8 @@ bool fgInitSubsystems() { // Initialize the scenery management subsystem. //////////////////////////////////////////////////////////////////// - if ( globals->get_tile_mgr()->init() ) { - // Load the local scenery data - double visibility_meters = fgGetDouble("/environment/visibility-m"); - globals->get_tile_mgr()->update( visibility_meters ); - } else { - SG_LOG( SG_GENERAL, SG_ALERT, "Error in Tile Manager initialization!" ); - exit(-1); - } + globals->add_subsystem("tile-manager", globals->get_tile_mgr(), + SGSubsystemMgr::DISPLAY); globals->get_scenery()->get_scene_graph() ->addChild(simgear::Particles::getCommonRoot()); @@ -1553,7 +1547,8 @@ void fgReInitSubsystems() globals->get_controls()->reset_all(); globals->get_subsystem("time")->reinit(); - + globals->get_subsystem("tile-manager")->reinit(); + if ( !freeze ) { fgSetBool("/sim/freeze/master", false); } @@ -1580,7 +1575,6 @@ void doSimulatorReset(void) // from gui_local.cxx -- TODO merge with fgReInitSu fgReInitSubsystems(); - globals->get_tile_mgr()->update(fgGetDouble("/environment/visibility-m")); fgSetBool("/sim/signals/reinit", false); if (!freeze) diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 0bd14a3bc..c52c5e182 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -193,7 +193,6 @@ FGGlobals::~FGGlobals() delete model_mgr; delete channel_options_list; delete initial_waypoints; - delete tile_mgr; delete scenery; delete fontcache; diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 2522e69dd..294c39c92 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -159,19 +159,6 @@ static void fgMainLoop( void ) { globals->get_subsystem_mgr()->update(sim_dt); globals->get_aircraft_model()->update(sim_dt); - - // - // Tile Manager updates - see if we need to load any new scenery tiles. - // this code ties together the fdm, viewer and scenery classes... - // we may want to move this to its own class at some point - // - double visibility_meters = fgGetDouble("/environment/visibility-m"); - globals->get_tile_mgr()->prep_ssg_nodes( visibility_meters ); - - // update tile manager for view... - SGVec3d viewPos = globals->get_current_view()->get_view_pos(); - SGGeod geodViewPos = SGGeod::fromCart(viewPos); - globals->get_tile_mgr()->update(geodViewPos, visibility_meters); // run Nasal's settimer() loops right before the view manager globals->get_event_mgr()->update(sim_dt); diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index e5cd08bbb..5abcf791d 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -67,7 +67,7 @@ FGTileMgr::~FGTileMgr() { // Initialize the Tile Manager subsystem -int FGTileMgr::init() { +void FGTileMgr::init() { SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." ); _options = new SGReaderWriterBTGOptions; @@ -80,65 +80,75 @@ int FGTileMgr::init() { std::copy(sc.begin(), sc.end(), back_inserter(fp)); TileEntry::setModelLoadHelper(this); + + _visibilityMeters = fgGetNode("/environment/visibility-m", true); + - tile_cache.init(); + reinit(); +} - state = Inited; - previous_bucket.make_bad(); - current_bucket.make_bad(); +void FGTileMgr::reinit() +{ + tile_cache.init(); + + state = Inited; - longitude = latitude = -1000.0; + previous_bucket.make_bad(); + current_bucket.make_bad(); + longitude = latitude = -1000.0; - return 1; + // force an update now + update(0.0); } // schedule a tile for loading void FGTileMgr::sched_tile( const SGBucket& b, const bool is_inner_ring ) { // see if tile already exists in the cache TileEntry *t = tile_cache.get_tile( b ); - - if ( !t ) { - // make space in the cache - SceneryPager* pager = FGScenery::getPagerSingleton(); - while ( (int)tile_cache.get_size() > tile_cache.get_max_cache_size() ) { - long index = tile_cache.get_oldest_tile(); - if ( index >= 0 ) { - TileEntry *old = tile_cache.get_tile( index ); - tile_cache.clear_entry( index ); - osg::ref_ptr subgraph = old->getNode(); - old->removeFromSceneGraph(); - delete old; - // zeros out subgraph ref_ptr, so subgraph is owned by - // the pager and will be deleted in the pager thread. - pager->queueDeleteRequest(subgraph); - } else { - // nothing to free ?!? forge ahead - break; - } + if (t) { + t->set_inner_ring( is_inner_ring ); + return; + } + + // make space in the cache + SceneryPager* pager = FGScenery::getPagerSingleton(); + while ( (int)tile_cache.get_size() > tile_cache.get_max_cache_size() ) { + long index = tile_cache.get_oldest_tile(); + if ( index >= 0 ) { + TileEntry *old = tile_cache.get_tile( index ); + tile_cache.clear_entry( index ); + osg::ref_ptr subgraph = old->getNode(); + old->removeFromSceneGraph(); + delete old; + // zeros out subgraph ref_ptr, so subgraph is owned by + // the pager and will be deleted in the pager thread. + pager->queueDeleteRequest(subgraph); + } else { + // nothing to free ?!? forge ahead + break; } + } - // create a new entry - TileEntry *e = new TileEntry( b ); + // create a new entry + TileEntry *e = new TileEntry( b ); - // insert the tile into the cache - if ( tile_cache.insert_tile( e ) ) { - // update_queues will generate load request - } else { - // insert failed (cache full with no available entries to - // delete.) Try again later - delete e; - } - // Attach to scene graph - e->addToSceneGraph(globals->get_scenery()->get_terrain_branch()); + // insert the tile into the cache + if ( tile_cache.insert_tile( e ) ) { + // update_queues will generate load request } else { - t->set_inner_ring( is_inner_ring ); + // insert failed (cache full with no available entries to + // delete.) Try again later + delete e; } + // Attach to scene graph + e->addToSceneGraph(globals->get_scenery()->get_terrain_branch()); } // schedule a needed buckets for loading -void FGTileMgr::schedule_needed( double vis, const SGBucket& curr_bucket) { +void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis) { + // sanity check (unfortunately needed!) if ( longitude < -180.0 || longitude > 180.0 || latitude < -90.0 || latitude > 90.0 ) @@ -155,8 +165,6 @@ void FGTileMgr::schedule_needed( double vis, const SGBucket& curr_bucket) { SG_LOG( SG_TERRAIN, SG_INFO, "scheduling needed tiles for " << longitude << " " << latitude ); - // vis = fgGetDouble("/environment/visibility-m"); - double tile_width = curr_bucket.get_width_m(); double tile_height = curr_bucket.get_height_m(); // cout << "tile width = " << tile_width << " tile_height = " @@ -209,29 +217,6 @@ void FGTileMgr::schedule_needed( double vis, const SGBucket& curr_bucket) { } } - -void FGTileMgr::initialize_queue() -{ - // First time through or we have teleported, initialize the - // system and load all relavant tiles - - SG_LOG( SG_TERRAIN, SG_INFO, "Initialize_queue(): Updating Tile list for " - << current_bucket ); - // cout << "tile cache size = " << tile_cache.get_size() << endl; - - // wipe/initialize tile cache - // tile_cache.init(); - previous_bucket.make_bad(); - - // build the local area list and schedule tiles for loading - - // start with the center tile and work out in concentric - // "rings" - - double visibility_meters = fgGetDouble("/environment/visibility-m"); - schedule_needed(visibility_meters, current_bucket); -} - osg::Node* FGTileMgr::loadTileModel(const string& modelPath, bool cacheModel) { @@ -322,16 +307,17 @@ void FGTileMgr::update_queues() // given the current lon/lat (in degrees), fill in the array of local // chunks. If the chunk isn't already in the cache, then read it from // disk. -int FGTileMgr::update( double visibility_meters ) +void FGTileMgr::update(double) { + SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update()" ); SGVec3d viewPos = globals->get_current_view()->get_view_pos(); - return update(SGGeod::fromCart(viewPos), visibility_meters); + prep_ssg_nodes(); + double vis = _visibilityMeters->getDoubleValue(); + schedule_tiles_at(SGGeod::fromCart(viewPos), vis); } -int FGTileMgr::update( const SGGeod& location, double visibility_meters) +int FGTileMgr::schedule_tiles_at(const SGGeod& location, double rangeM) { - SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update()" ); - longitude = location.getLongitudeDeg(); latitude = location.getLatitudeDeg(); @@ -351,16 +337,16 @@ int FGTileMgr::update( const SGGeod& location, double visibility_meters) // We've moved to a new bucket, we need to schedule any // needed tiles for loading. SG_LOG( SG_TERRAIN, SG_INFO, "FGTileMgr::update()" ); - schedule_needed(visibility_meters, current_bucket); + schedule_needed(current_bucket, rangeM); } } else if ( state == Start || state == Inited ) { SG_LOG( SG_TERRAIN, SG_INFO, "State == Start || Inited" ); -// initialize_queue(); + state = Running; if (current_bucket != previous_bucket && current_bucket.get_chunk_lon() != -1000) { SG_LOG( SG_TERRAIN, SG_INFO, "FGTileMgr::update()" ); - schedule_needed(visibility_meters, current_bucket); + schedule_needed(current_bucket, rangeM); } } @@ -372,11 +358,12 @@ int FGTileMgr::update( const SGGeod& location, double visibility_meters) return 1; } -void FGTileMgr::prep_ssg_nodes(float vis) { +void FGTileMgr::prep_ssg_nodes() { // traverse the potentially viewable tile list and update range // selector and transform + double vis = _visibilityMeters->getDoubleValue(); TileEntry *e; tile_cache.reset_traversal(); diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index 6b415e53b..13588342b 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -26,6 +26,7 @@ #include +#include #include #include #include @@ -37,7 +38,7 @@ namespace osg class Node; } -class FGTileMgr : public simgear::ModelLoadHelper { +class FGTileMgr : public SGSubsystem, public simgear::ModelLoadHelper { private: @@ -49,15 +50,12 @@ private: }; load_state state; - - // initialize the cache - void initialize_queue(); - + // schedule a tile for loading void sched_tile( const SGBucket& b, const bool is_inner_ring ); // schedule a needed buckets for loading - void schedule_needed(double visibility_meters, const SGBucket& curr_bucket); + void schedule_needed(const SGBucket& curr_bucket, double rangeM); SGBucket previous_bucket; SGBucket current_bucket; @@ -77,29 +75,31 @@ private: */ simgear::TileCache tile_cache; + // Update the various queues maintained by the tilemagr (private + // internal function, do not call directly.) + void update_queues(); + + // Prepare the ssg nodes corresponding to each tile. For each + // tile, set the ssg transform and update it's range selector + // based on current visibilty void prep_ssg_nodes( float + // visibility_meters ); + void prep_ssg_nodes(); + + SGPropertyNode* _visibilityMeters; + public: FGTileMgr(); ~FGTileMgr(); // Initialize the Tile Manager - int init(); + virtual void init(); + virtual void reinit(); - // Update the various queues maintained by the tilemagr (private - // internal function, do not call directly.) - void update_queues(); + virtual void update(double dt); - // given the current lon/lat (in degrees), fill in the array of - // local chunks. If the chunk isn't already in the cache, then - // read it from disk. - int update( double visibility_meters ); - int update( const SGGeod& location, double visibility_meters); + int schedule_tiles_at(const SGGeod& location, double rangeM); - // Prepare the ssg nodes corresponding to each tile. For each - // tile, set the ssg transform and update it's range selector - // based on current visibilty void prep_ssg_nodes( float - // visibility_meters ); - void prep_ssg_nodes(float visibility_meters ); const SGBucket& get_current_bucket () const { return current_bucket; }