extern ssgRoot *scene;
extern ssgBranch *terrain;
+extern ssgBranch *ground;
// the tile manager
FGTileMgr global_tile_mgr;
return Point3D(a.x()+b[0], a.y()+b[1], a.z()+b[2]);
}
+#ifdef ENABLE_THREADS
+SGLockedQueue<FGTileEntry *> FGTileMgr::attach_queue;
+SGLockedQueue<FGDeferredModel *> FGTileMgr::model_queue;
+#else
+queue<FGTileEntry *> FGTileMgr::attach_queue;
+queue<FGDeferredModel *> FGTileMgr::model_queue;
+#endif // ENABLE_THREADS
+
// Constructor
FGTileMgr::FGTileMgr():
state( Start ),
- vis( 16000 )
+ vis( 16000 ),
+ counter_hack(0)
{
}
int FGTileMgr::init() {
SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." );
- if ( state != Start ) {
- SG_LOG( SG_TERRAIN, SG_INFO,
- "... Reinitializing." );
- destroy_queue();
- } else {
- SG_LOG( SG_TERRAIN, SG_INFO,
- "... First time through." );
- global_tile_cache.init();
+ tile_cache.init();
+
+#if 0
+
+ // instead it's just a lot easier to let any pending work flush
+ // through, rather than trying to arrest the queue and nuke all
+ // the various work at all the various stages and get everything
+ // cleaned up properly.
+
+ while ( ! attach_queue.empty() ) {
+ attach_queue.pop();
+ }
+
+ while ( ! model_queue.empty() ) {
+#ifdef ENABLE_THREADS
+ FGDeferredModel* dm = model_queue.pop();
+#else
+ FGDeferredModel* dm = model_queue.front();
+ model_queue.pop();
+#endif
+ delete dm;
}
+ loader.reinit();
+#endif
hit_list.clear();
// schedule a tile for loading
void FGTileMgr::sched_tile( const SGBucket& b ) {
// see if tile already exists in the cache
- FGTileEntry *t = global_tile_cache.get_tile( b );
+ FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) {
- // register a load request
- load_queue.push_back( b );
- }
-}
+ // create a new entry
+ FGTileEntry *e = new FGTileEntry( b );
+ // insert the tile into the cache
+ tile_cache.insert_tile( e );
-// load a tile
-void FGTileMgr::load_tile( const SGBucket& b ) {
- // see if tile already exists in the cache
- FGTileEntry *t = global_tile_cache.get_tile( b );
-
- if ( t == NULL ) {
- SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << b );
- global_tile_cache.fill_in( b );
- t = global_tile_cache.get_tile( b );
- t->prep_ssg_node( scenery.center, vis);
- } else {
- SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile already in cache " << b );
+ // Schedule tile for loading
+ loader.add( e );
}
}
sgSetVec3(tmp, hit_list.get_normal(this_hit));
// cout << "cur_normal: " << tmp[0] << " " << tmp[1] << " "
// << tmp[2] << endl;
- ssgState *IntersectedLeafState =
- ((ssgLeaf*)hit_list.get_entity(this_hit))->getState();
+ /* ssgState *IntersectedLeafState =
+ ((ssgLeaf*)hit_list.get_entity(this_hit))->getState(); */
CurrentNormalInLocalPlane(tmp, tmp);
sgdSetVec3( scenery.cur_normal, tmp );
// cout << "NED: " << tmp[0] << " " << tmp[1] << " " << tmp[2] << endl;
#else
vis = current_weather.get_visibility();
#endif
- cout << "visibility = " << vis << endl;
+ // cout << "visibility = " << vis << endl;
double tile_width = current_bucket.get_width_m();
double tile_height = current_bucket.get_height_m();
- cout << "tile width = " << tile_width << " tile_height = " << tile_height
- << endl;
+ // cout << "tile width = " << tile_width << " tile_height = "
+ // << tile_height !<< endl;
xrange = (int)(vis / tile_width) + 1;
yrange = (int)(vis / tile_height) + 1;
if ( xrange < 1 ) { xrange = 1; }
if ( yrange < 1 ) { yrange = 1; }
- cout << "xrange = " << xrange << " yrange = " << yrange << endl;
+ // cout << "xrange = " << xrange << " yrange = " << yrange << endl;
- global_tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
+ tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
SGBucket b;
for ( y = -1; y <= 1; ++y ) {
if ( x != 0 || y != 0 ) {
b = sgBucketOffset( longitude, latitude, x, y );
- if ( ! global_tile_cache.exists( b ) ) {
- sched_tile( b );
- }
+ sched_tile( b );
}
}
}
for ( y = -yrange; y <= yrange; ++y ) {
if ( x < -1 || x > 1 || y < -1 || y > 1 ) {
SGBucket b = sgBucketOffset( longitude, latitude, x, y );
- if ( ! global_tile_cache.exists( b ) ) {
- sched_tile( b );
- }
+ sched_tile( b );
}
}
}
// system and load all relavant tiles
SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
- cout << "tile cache size = " << global_tile_cache.get_size() << endl;
-
- int i;
+ // cout << "tile cache size = " << tile_cache.get_size() << endl;
// wipe/initialize tile cache
- // global_tile_cache.init();
+ // tile_cache.init();
previous_bucket.make_bad();
// build the local area list and schedule tiles for loading
schedule_needed();
+ // do we really want to lose this? CLO
+#if 0
// Now force a load of the center tile and inner ring so we
// have something to see in our first frame.
+ int i;
for ( i = 0; i < 9; ++i ) {
if ( load_queue.size() ) {
SG_LOG( SG_TERRAIN, SG_DEBUG,
load_tile( pending );
}
}
-}
-
-
-// forced emptying of the queue
-// This is necessay to keep bookeeping straight for the
-// tile_cache -- which actually handles all the
-// (de)allocations
-void FGTileMgr::destroy_queue() {
- load_queue.clear();
+#endif
}
current_bucket.set_bucket( longitude, latitude );
// SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket );
- if ( global_tile_cache.exists( current_bucket ) ) {
- current_tile = global_tile_cache.get_tile( current_bucket );
+ if ( tile_cache.exists( current_bucket ) ) {
+ current_tile = tile_cache.get_tile( current_bucket );
scenery.next_center = current_tile->center;
} else {
SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
state = Running;
}
- if ( load_queue.size() ) {
- SG_LOG( SG_TERRAIN, SG_INFO, "Load queue size = " << load_queue.size()
- << " loading a tile" );
+ // load the next tile in the load queue (or authorize the next
+ // load in the case of the threaded tile pager)
+ loader.update();
+
+ // 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.
+ if ( !model_queue.empty() ) {
+ cout << "loading next model ..." << endl;
+ // load the next tile in the queue
+#ifdef ENABLE_THREADS
+ FGDeferredModel* dm = model_queue.pop();
+#else
+ FGDeferredModel* dm = model_queue.front();
+ model_queue.pop();
+#endif
+
+ ssgTexturePath( (char *)(dm->get_texture_path().c_str()) );
+ ssgEntity *obj_model
+ = ssgLoad( (char *)(dm->get_model_path().c_str()) );
+ if ( obj_model != NULL ) {
+ dm->get_obj_trans()->addKid( obj_model );
+ }
+ dm->get_tile()->dec_pending_models();
- SGBucket pending = load_queue.front();
- load_queue.pop_front();
- load_tile( pending );
+ delete dm;
}
if ( scenery.center == Point3D(0.0) ) {
last_longitude = longitude;
last_latitude = latitude;
+ // activate loader thread one out of every 5 frames
+ counter_hack = (counter_hack + 1) % 5;
+ if ( !counter_hack ) {
+ // Notify the tile loader that it can load another tile
+ // loader.update();
+
+ if ( !attach_queue.empty() ) {
+#ifdef ENABLE_THREADS
+ FGTileEntry* e = attach_queue.pop();
+#else
+ FGTileEntry* e = attach_queue.front();
+ attach_queue.pop();
+#endif
+ e->add_ssg_nodes( terrain, ground );
+ // cout << "Adding ssg nodes for "
+ }
+ }
+
return 1;
}
// selector and transform
FGTileEntry *e;
- global_tile_cache.reset_traversal();
+ tile_cache.reset_traversal();
- while ( ! global_tile_cache.at_end() ) {
+ while ( ! tile_cache.at_end() ) {
// cout << "processing a tile" << endl;
- if ( (e = global_tile_cache.get_current()) ) {
+ if ( (e = tile_cache.get_current()) ) {
e->prep_ssg_node( scenery.center, vis);
} else {
cout << "warning ... empty tile in cache" << endl;
}
- global_tile_cache.next();
+ tile_cache.next();
}
}