1
0
Fork 0

Make the tile-manager a well-behaved SGSubsystem

This commit is contained in:
James Turner 2010-10-01 19:09:19 +01:00
parent 6963a6c2e4
commit 0beab94cb5
7 changed files with 95 additions and 136 deletions

View file

@ -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;

View file

@ -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 );

View file

@ -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)

View file

@ -193,7 +193,6 @@ FGGlobals::~FGGlobals()
delete model_mgr;
delete channel_options_list;
delete initial_waypoints;
delete tile_mgr;
delete scenery;
delete fontcache;

View file

@ -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);

View file

@ -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();

View file

@ -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; }