diff --git a/src/Scenery/newcache.cxx b/src/Scenery/newcache.cxx index e55e2d655..033e11e8c 100644 --- a/src/Scenery/newcache.cxx +++ b/src/Scenery/newcache.cxx @@ -125,7 +125,8 @@ bool FGNewCache::make_space() { for ( ; current != end; ++current ) { long index = current->first; FGTileEntry *e = current->second; - if ( e->is_loaded() && (e->get_pending_models() == 0) ) { + // if ( e->is_loaded() && (e->get_pending_models() == 0) ) { + if ( e->is_loaded() ) { timestamp = e->get_timestamp(); if ( timestamp < min_time ) { diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index 6b132e7ee..153d49183 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -818,6 +818,7 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) FGDeferredModel *dm = new FGDeferredModel( custom_path.str(), tile_path.str(), + tile_bucket, this, obj_trans ); FGTileMgr::model_ready( dm ); diff --git a/src/Scenery/tileentry.hxx b/src/Scenery/tileentry.hxx index dfb16965a..d3476c061 100644 --- a/src/Scenery/tileentry.hxx +++ b/src/Scenery/tileentry.hxx @@ -70,21 +70,25 @@ private: string texture_path; FGTileEntry *tile; ssgTransform *obj_trans; + SGBucket bucket; + public: inline FGDeferredModel() { } - inline FGDeferredModel( const string mp, const string tp, + inline FGDeferredModel( const string mp, const string tp, SGBucket b, FGTileEntry *t, ssgTransform *ot ) { model_path = mp; texture_path = tp; + bucket = b; tile = t; obj_trans = ot; } inline ~FGDeferredModel() { } inline string get_model_path() const { return model_path; } inline string get_texture_path() const { return texture_path; } + inline SGBucket get_bucket() const { return bucket; } inline FGTileEntry *get_tile() const { return tile; } inline ssgTransform *get_obj_trans() const { return obj_trans; } }; diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 3cfe0471e..6730eaea2 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -279,36 +279,51 @@ void FGTileMgr::update_queues() { // load the next model in the load queue. Currently this must // happen in the render thread because model loading can trigger - // texture loading which involves use of the opengl api. + // texture loading which involves use of the opengl api. Skip any + // models belonging to not loaded tiles (i.e. the tile was removed + // before we were able to load some of the associated models.) if ( !model_queue.empty() ) { - // cout << "loading next model ..." << endl; - // load the next tile in the queue + bool processed_one = false; + + while ( model_queue.size() > 200 || processed_one == false ) { + processed_one = true; + + if ( model_queue.size() > 200 ) { + SG_LOG( SG_TERRAIN, SG_INFO, + "Alert: catching up on model load queue" ); + } + + // cout << "loading next model ..." << endl; + // load the next tile in the queue #if defined(ENABLE_THREADS) && ENABLE_THREADS - FGDeferredModel* dm = model_queue.pop(); + FGDeferredModel* dm = model_queue.pop(); #else - FGDeferredModel* dm = model_queue.front(); - model_queue.pop(); + FGDeferredModel* dm = model_queue.front(); + model_queue.pop(); #endif - ssgTexturePath( (char *)(dm->get_texture_path().c_str()) ); - try - { - ssgEntity *obj_model = - globals->get_model_lib()->load_model( ".", - dm->get_model_path(), - globals->get_props(), - globals->get_sim_time_sec() ); - if ( obj_model != NULL ) { - dm->get_obj_trans()->addKid( obj_model ); + // only load the model if the tile still exists in the + // tile cache + FGTileEntry *t = tile_cache.get_tile( dm->get_bucket() ); + if ( t != NULL ) { + ssgTexturePath( (char *)(dm->get_texture_path().c_str()) ); + try { + ssgEntity *obj_model = + globals->get_model_lib()->load_model( ".", + dm->get_model_path(), + globals->get_props(), + globals->get_sim_time_sec() ); + if ( obj_model != NULL ) { + dm->get_obj_trans()->addKid( obj_model ); + } + } catch (const sg_exception& exc) { + SG_LOG( SG_ALL, SG_ALERT, exc.getMessage() ); + } + + dm->get_tile()->dec_pending_models(); } + delete dm; } - catch (const sg_exception& exc) - { - SG_LOG( SG_ALL, SG_ALERT, exc.getMessage() ); - } - - dm->get_tile()->dec_pending_models(); - delete dm; } // cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl; @@ -333,26 +348,26 @@ void FGTileMgr::update_queues() if ( !delete_queue.empty() ) { // cout << "delete queue = " << delete_queue.size() << endl; + bool processed_one = false; - while ( delete_queue.size() > 30 ) { - // uh oh, delete queue is blowing up, we aren't clearing - // it fast enough. Let's just panic, well not panic, but - // get real serious and agressively free up some tiles so - // we don't explode our memory usage. + while ( delete_queue.size() > 30 || processed_one == false ) { + processed_one = true; - SG_LOG( SG_TERRAIN, SG_ALERT, - "Alert: catching up on tile delete queue" ); + if ( delete_queue.size() > 30 ) { + // uh oh, delete queue is blowing up, we aren't clearing + // it fast enough. Let's just panic, well not panic, but + // get real serious and agressively free up some tiles so + // we don't explode our memory usage. + + SG_LOG( SG_TERRAIN, SG_ALERT, + "Alert: catching up on tile delete queue" ); + } FGTileEntry* e = delete_queue.front(); - while ( !e->free_tile() ); - delete_queue.pop(); - delete e; - } - - FGTileEntry* e = delete_queue.front(); - if ( e->free_tile() ) { - delete_queue.pop(); - delete e; + if ( e->free_tile() ) { + delete_queue.pop(); + delete e; + } } } }