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." );
- 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();
FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) {
- // register a load request
- tile_cache.load_tile( b );
- }
-}
-
+ // create a new entry
+ FGTileEntry *e = new FGTileEntry( b );
-// depricated for threading
-#if 0
-// load a tile
-void FGTileMgr::load_tile( const SGBucket& b ) {
- // see if tile already exists in the cache
- FGTileEntry *t = tile_cache.get_tile( b );
+ // insert the tile into the cache
+ tile_cache.insert_tile( e );
- if ( t == NULL ) {
- SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << b );
- tile_cache.fill_in( b );
- t = 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 );
}
}
-#endif
static void CurrentNormalInLocalPlane(sgVec3 dst, sgVec3 src) {
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;
SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
// cout << "tile cache size = " << tile_cache.get_size() << endl;
- int i;
-
// wipe/initialize tile cache
// tile_cache.init();
previous_bucket.make_bad();
#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,
}
-// 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();
-}
-
-
// 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.
state = Running;
}
- // now handled by threaded tile pager
-#if 0
- 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;
}
-#endif
if ( scenery.center == Point3D(0.0) ) {
// initializing
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;
}