From 0beab94cb5fec7c58015271658a6233260c25d02 Mon Sep 17 00:00:00 2001 From: James Turner <zakalawe@mac.com> Date: Fri, 1 Oct 2010 19:09:19 +0100 Subject: [PATCH 1/3] Make the tile-manager a well-behaved SGSubsystem --- src/AIModel/AIAircraft.cxx | 2 +- src/Main/fg_commands.cxx | 14 +--- src/Main/fg_init.cxx | 14 +--- src/Main/globals.cxx | 1 - src/Main/main.cxx | 13 ---- src/Scenery/tilemgr.cxx | 147 +++++++++++++++++-------------------- src/Scenery/tilemgr.hxx | 40 +++++----- 7 files changed, 95 insertions(+), 136 deletions(-) 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<osg::Object> 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 ); - - // 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()); - } else { - t->set_inner_ring( is_inner_ring ); + 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<osg::Object> 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 ); + + // 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()); } // 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 ) -{ - SGVec3d viewPos = globals->get_current_view()->get_view_pos(); - return update(SGGeod::fromCart(viewPos), visibility_meters); -} - -int FGTileMgr::update( const SGGeod& location, double visibility_meters) +void FGTileMgr::update(double) { SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update()" ); + SGVec3d viewPos = globals->get_current_view()->get_view_pos(); + prep_ssg_nodes(); + double vis = _visibilityMeters->getDoubleValue(); + schedule_tiles_at(SGGeod::fromCart(viewPos), vis); +} +int FGTileMgr::schedule_tiles_at(const SGGeod& location, double rangeM) +{ 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 <simgear/compiler.h> +#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/bucket/newbucket.hxx> #include <simgear/scene/tgdb/TileEntry.hxx> #include <simgear/scene/tgdb/TileCache.hxx> @@ -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; } From e7b58d48e32e017a3d5ceddeb60ec04f6166d81f Mon Sep 17 00:00:00 2001 From: Thorsten Brehm <brehm@patagonia.southamerica> Date: Sat, 2 Oct 2010 00:40:24 +0200 Subject: [PATCH 2/3] Fix wxradar to use path resolution make it work with the new "multiple aircraft dir" feature --- src/Instrumentation/wxradar.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Instrumentation/wxradar.cxx b/src/Instrumentation/wxradar.cxx index f32e12605..e8619dec6 100644 --- a/src/Instrumentation/wxradar.cxx +++ b/src/Instrumentation/wxradar.cxx @@ -122,10 +122,9 @@ wxRadarBg::init () "Aircraft/Instruments/Textures/od_wxradar.rgb"); _resultTexture = FGTextureManager::createTexture(_texture_path.c_str(), false); - SGPath tpath(globals->get_fg_root()); string path = _Instrument->getStringValue("echo-texture-path", "Aircraft/Instruments/Textures/wxecho.rgb"); - tpath.append(path); + SGPath tpath = globals->resolve_aircraft_path(path); // no mipmap or else alpha will mix with pixels on the border of shapes, ruining the effect _wxEcho = SGLoadTexture2D(tpath, false, false); From dba471519f653b92cb10af871f0d215b0ada3042 Mon Sep 17 00:00:00 2001 From: Tim Moore <timoore33@gmail.com> Date: Sat, 2 Oct 2010 23:03:27 +0200 Subject: [PATCH 3/3] Thorsten Brem's patches for bug 122 Fixes teleporting problems and disappearing tiles. --- src/Scenery/tilemgr.cxx | 32 ++++++++++++++++++++++---------- src/Scenery/tilemgr.hxx | 2 +- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 5abcf791d..6e9c43812 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -103,17 +103,19 @@ void FGTileMgr::reinit() } // schedule a tile for loading -void FGTileMgr::sched_tile( const SGBucket& b, const bool is_inner_ring ) { +void FGTileMgr::sched_tile( const SGBucket& b, const bool is_inner_ring, const bool is_cache_locked ) { // see if tile already exists in the cache TileEntry *t = tile_cache.get_tile( b ); if (t) { - t->set_inner_ring( is_inner_ring ); + t->set_timestamp(tile_cache.get_current_time()); + t->set_inner_ring( is_inner_ring ); + t->set_cache_lock( is_cache_locked ); return; } // make space in the cache SceneryPager* pager = FGScenery::getPagerSingleton(); - while ( (int)tile_cache.get_size() > tile_cache.get_max_cache_size() ) { + 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 ); @@ -132,20 +134,21 @@ void FGTileMgr::sched_tile( const SGBucket& b, const bool is_inner_ring ) { // create a new entry TileEntry *e = new TileEntry( b ); - + // insert the tile into the cache if ( tile_cache.insert_tile( e ) ) { + e->set_inner_ring( is_inner_ring ); + e->set_cache_lock( is_cache_locked ); // update_queues will generate load request + // Attach to scene graph + e->addToSceneGraph(globals->get_scenery()->get_terrain_branch()); } 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()); } - // schedule a needed buckets for loading void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis) { @@ -188,11 +191,20 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis) { // location. tile_cache.clear_inner_ring_flags(); + // clear the cache lock flags which prevented tiles of the previous position to be dropped + // from the cache. + tile_cache.clear_cache_lock_flags(); + + // update timestamps, so all tiles scheduled now are *newer* than any tile previously loaded + osg::FrameStamp* framestamp + = globals->get_renderer()->getViewer()->getFrameStamp(); + tile_cache.set_current_time(framestamp->getReferenceTime()); + SGBucket b; // schedule center tile first so it can be loaded first b = sgBucketOffset( longitude, latitude, 0, 0 ); - sched_tile( b, true ); + sched_tile( b, true, true ); int x, y; @@ -201,7 +213,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis) { for ( y = -1; y <= 1; ++y ) { if ( x != 0 || y != 0 ) { b = sgBucketOffset( longitude, latitude, x, y ); - sched_tile( b, true ); + sched_tile( b, true, true); } } } @@ -211,7 +223,7 @@ void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis) { for ( y = -yrange; y <= yrange; ++y ) { if ( x < -1 || x > 1 || y < -1 || y > 1 ) { SGBucket b = sgBucketOffset( longitude, latitude, x, y ); - sched_tile( b, false ); + sched_tile( b, false, true); } } } diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index 13588342b..98dcc3d18 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -52,7 +52,7 @@ private: load_state state; // schedule a tile for loading - void sched_tile( const SGBucket& b, const bool is_inner_ring ); + void sched_tile( const SGBucket& b, const bool is_inner_ring, const bool is_cache_locked ); // schedule a needed buckets for loading void schedule_needed(const SGBucket& curr_bucket, double rangeM);