]> git.mxchange.org Git - flightgear.git/blobdiff - src/Scenery/tilemgr.cxx
Currently, when the sim pauses, all IO is also halted. To me it generally
[flightgear.git] / src / Scenery / tilemgr.cxx
index c1e760609e65879c26e3f97b256ceb87c775973c..2b16af01838cb629a7c5d9c1744931f5a14e9730 100644 (file)
 #  include <config.h>
 #endif
 
-#ifdef HAVE_WINDOWS_H
-#  include <windows.h>
-#endif
-
-#include <GL/glut.h>
-
 #include <plib/ssg.h>
 
 #include <simgear/constants.h>
 #include <simgear/math/polar3d.hxx>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/math/vector.hxx>
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/scene/model/modellib.hxx>
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/viewer.hxx>
-#include <Model/loader.hxx>
-#include <Objects/obj.hxx>
 
 #include "newcache.hxx"
 #include "scenery.hxx"
 
 #define TEST_LAST_HIT_CACHE
 
-// the tile manager
-FGTileMgr global_tile_mgr;
-
-
 #ifdef ENABLE_THREADS
 SGLockedQueue<FGTileEntry *> FGTileMgr::attach_queue;
 SGLockedQueue<FGDeferredModel *> FGTileMgr::model_queue;
@@ -101,7 +90,7 @@ int FGTileMgr::init() {
 
     while ( ! model_queue.empty() ) {
 #ifdef ENABLE_THREADS
-       FGDeferredModel* dm = model_queue.pop();
+        FGDeferredModel* dm = model_queue.pop();
 #else
         FGDeferredModel* dm = model_queue.front();
         model_queue.pop();
@@ -120,7 +109,7 @@ int FGTileMgr::init() {
 
     longitude = latitude = -1000.0;
     last_longitude = last_latitude = -1000.0;
-       
+
     return 1;
 }
 
@@ -149,14 +138,14 @@ void FGTileMgr::sched_tile( const SGBucket& b ) {
         FGTileEntry *e = new FGTileEntry( b );
 
         // insert the tile into the cache
-       if ( tile_cache.insert_tile( e ) ) {
-         // Schedule tile for loading
-         loader.add( e );
-       } else {
-         // insert failed (cache full with no available entries to
-         // delete.)  Try again later
-         delete e;
-       }
+        if ( tile_cache.insert_tile( e ) ) {
+            // Schedule tile for loading
+            loader.add( e );
+        } else {
+            // insert failed (cache full with no available entries to
+            // delete.)  Try again later
+            delete e;
+        }
     }
 }
 
@@ -168,9 +157,10 @@ void FGTileMgr::schedule_needed( double vis, SGBucket curr_bucket) {
          || latitude < -90.0 || latitude > 90.0 )
     {
         SG_LOG( SG_TERRAIN, SG_ALERT,
-                "Attempting to schedule tiles for bogus latitude and" );
+                "Attempting to schedule tiles for bogus lon and lat  = ("
+                << longitude << "," << latitude << ")" );
         SG_LOG( SG_TERRAIN, SG_ALERT,
-                "longitude.  This is a FATAL error.  Exiting!" );
+                "This is a FATAL error.  Exiting!" );
         exit(-1);        
     }
 
@@ -208,22 +198,22 @@ void FGTileMgr::schedule_needed( double vis, SGBucket curr_bucket) {
 
     // schedule next ring of 8 tiles
     for ( x = -1; x <= 1; ++x ) {
-       for ( y = -1; y <= 1; ++y ) {
-           if ( x != 0 || y != 0 ) {
-               b = sgBucketOffset( longitude, latitude, x, y );
-               sched_tile( b );
-           }
-       }
+        for ( y = -1; y <= 1; ++y ) {
+            if ( x != 0 || y != 0 ) {
+                b = sgBucketOffset( longitude, latitude, x, y );
+                sched_tile( b );
+            }
+        }
     }
-    
+
     // schedule remaining tiles
     for ( x = -xrange; x <= xrange; ++x ) {
-       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 );
-           }
-       }
+        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 );
+            }
+        }
     }
 }
 
@@ -277,31 +267,34 @@ void FGTileMgr::update_queues()
     // 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
+        // cout << "loading next model ..." << endl;
+        // load the next tile in the queue
 #ifdef ENABLE_THREADS
-       FGDeferredModel* dm = model_queue.pop();
+        FGDeferredModel* dm = model_queue.pop();
 #else
         FGDeferredModel* dm = model_queue.front();
         model_queue.pop();
 #endif
-       
-       ssgTexturePath( (char *)(dm->get_texture_path().c_str()) );
-       try
-       {
-           ssgEntity *obj_model =
-               globals->get_model_loader()->load_model(dm->get_model_path());
-           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;
+
+        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;
     }
     
     // cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl;
@@ -316,16 +309,17 @@ void FGTileMgr::update_queues()
 
     if ( !attach_queue.empty() ) {
 #ifdef ENABLE_THREADS
-       FGTileEntry* e = attach_queue.pop();
+        FGTileEntry* e = attach_queue.pop();
 #else
-       FGTileEntry* e = attach_queue.front();
-       attach_queue.pop();
+        FGTileEntry* e = attach_queue.front();
+        attach_queue.pop();
 #endif
-       e->add_ssg_nodes( globals->get_scenery()->get_terrain_branch(),
-                         globals->get_scenery()->get_gnd_lights_root(),
-                         globals->get_scenery()->get_rwy_lights_root(),
-                         globals->get_scenery()->get_taxi_lights_root() );
-       // cout << "Adding ssg nodes for "
+        e->add_ssg_nodes( globals->get_scenery()->get_terrain_branch(),
+                          globals->get_scenery()->get_gnd_lights_root(),
+                          globals->get_scenery()->get_taxi_lights_root(),
+                          globals->get_scenery()->get_rwy_lights_root(),
+                          globals->get_scenery()->get_taxi_lights_root() );
+        // cout << "Adding ssg nodes for "
     }
 
     if ( !delete_queue.empty() ) {
@@ -360,52 +354,62 @@ void FGTileMgr::update_queues()
 // disk.
 int FGTileMgr::update( double visibility_meters )
 {
-    FGLocation *location = globals->get_current_view()->getFGLocation();
+    SGLocation *location = globals->get_current_view()->getSGLocation();
     sgdVec3 abs_pos_vector;
     sgdCopyVec3( abs_pos_vector,
                  globals->get_current_view()->get_absolute_view_pos() );
-    return update( location, visibility_meters, abs_pos_vector,
-                   current_bucket, previous_bucket,
-                   globals->get_scenery()->get_center() );
+    return update( location, visibility_meters, abs_pos_vector );
 }
 
 
-int FGTileMgr::update( FGLocation *location, double visibility_meters,
-                       sgdVec3 abs_pos_vector, SGBucket p_current,
-                       SGBucket p_previous, Point3D center )
+int FGTileMgr::update( SGLocation *location, double visibility_meters,
+                       sgdVec3 abs_pos_vector )
 {
-    // SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for "
-    //         << lon << " " << lat );
-
     longitude = location->getLongitude_deg();
     latitude = location->getLatitude_deg();
-    current_bucket = p_current;
-    previous_bucket = p_previous;
-
-    // SG_LOG( SG_TERRAIN, SG_DEBUG, "lon "<< lonlat[LON] <<
-    //      " lat " << lonlat[LAT] );
+    // add 1.0m to the max altitude to give a little leeway to the
+    // ground reaction code.
+    altitude_m = location->getAltitudeASL_ft() * SG_FEET_TO_METER + 1.0;
+
+    // if current altitude is apparently not initialized, set max
+    // altitude to something big.
+    if ( altitude_m < -1000 ) {
+        altitude_m = 10000;
+    }
+    // SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for "
+    //         << longitude << " " << latatitude );
 
-    // SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket );
+    current_bucket.set_bucket( longitude, latitude );
+    // SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating tile list for "
+    //         << current_bucket );
+    fgSetInt( "/environment/current-tile-id", current_bucket.gen_index() );
 
-    setCurrentTile( longitude, latitude);
+    // set global scenery center from current tile center
+    current_tile = tile_cache.get_tile( current_bucket );
+    if ( current_tile != NULL ) {
+        globals->get_scenery()->set_next_center( current_tile->center );
+    } else {
+        SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
+        globals->get_scenery()->set_next_center( Point3D(0.0) );
+    }
 
     // do tile load scheduling. 
     // Note that we need keep track of both viewer buckets and fdm buckets.
     if ( state == Running ) {
-       SG_LOG( SG_TERRAIN, SG_DEBUG, "State == Running" );
-       if (!(current_bucket == previous_bucket )) {
-        // We've moved to a new bucket, we need to schedule any
-        // needed tiles for loading.
-        schedule_needed(visibility_meters, current_bucket);
-       }
+        SG_LOG( SG_TERRAIN, SG_DEBUG, "State == Running" );
+        if (!(current_bucket == previous_bucket )) {
+            // We've moved to a new bucket, we need to schedule any
+            // needed tiles for loading.
+            schedule_needed(visibility_meters, current_bucket);
+        }
     } else if ( state == Start || state == Inited ) {
-       SG_LOG( SG_TERRAIN, SG_INFO, "State == Start || Inited" );
-       initialize_queue();
-       state = Running;
+        SG_LOG( SG_TERRAIN, SG_INFO, "State == Start || Inited" );
+        initialize_queue();
+        state = Running;
 
-       // 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 tile in the load queue (or authorize the next
+        // load in the case of the threaded tile pager)
+        loader.update();
     }
 
     update_queues();
@@ -416,7 +420,9 @@ int FGTileMgr::update( FGLocation *location, double visibility_meters,
     // no reason to update this if we haven't moved...
     if ( longitude != last_longitude || latitude != last_latitude ) {
         // update current elevation... 
-        if ( updateCurrentElevAtPos( abs_pos_vector, center ) ) {
+        if ( updateCurrentElevAtPos( abs_pos_vector, altitude_m,
+                                     location->get_tile_center() ) )
+        {
             last_longitude = longitude;
             last_latitude = latitude;
         }
@@ -425,38 +431,23 @@ int FGTileMgr::update( FGLocation *location, double visibility_meters,
     return 1;
 }
 
+
 // timer event driven call to scheduler for the purpose of refreshing the tile timestamps
 void FGTileMgr::refresh_view_timestamps() {
     SG_LOG( SG_TERRAIN, SG_INFO,
-        "Refreshing timestamps for " << current_bucket.get_center_lon()
-        << " " << current_bucket.get_center_lat() );
+            "Refreshing timestamps for " << current_bucket.get_center_lon()
+            << " " << current_bucket.get_center_lat() );
     schedule_needed(fgGetDouble("/environment/visibility-m"), current_bucket);
 }
 
 
-// check and set current tile and scenery center...
-void FGTileMgr::setCurrentTile(double longitude, double latitude) {
-
-    // check tile cache entry...
-    current_bucket.set_bucket( longitude, latitude );
-    if ( tile_cache.exists( current_bucket ) ) {
-        current_tile = tile_cache.get_tile( current_bucket );
-        globals->get_scenery()->set_next_center( current_tile->center );
-    } else {
-        SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
-        globals->get_scenery()->set_next_center( Point3D(0.0) );
-    }
-}
-
-
-int FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector, Point3D center) {
-
-  sgdVec3 sc;
+int FGTileMgr::updateCurrentElevAtPos( sgdVec3 abs_pos_vector,
+                                       double max_alt_m,
+                                       Point3D center)
+{
+    sgdVec3 sc;
 
-  sgdSetVec3( sc,
-    center[0],
-    center[1],
-    center[2]);
+    sgdSetVec3( sc, center[0], center[1], center[2]);
 
     // overridden with actual values if a terrain intersection is
     // found
@@ -469,7 +460,11 @@ int FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector, Point3D center) {
         // scenery center has been properly defined so any hit should
         // be valid (and not just luck)
         hit = fgCurrentElev(abs_pos_vector,
+                            max_alt_m,
                             sc,
+               // uncomment next paramater to fly under
+               // bridges and a slightly faster algorithm
+               // but you won't be able to land on aircraft carriers
                             // current_tile->get_terra_transform(),
                             &hit_list,
                             &hit_elev,
@@ -491,7 +486,7 @@ int FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector, Point3D center) {
 }
 
 
-void FGTileMgr::prep_ssg_nodes( FGLocation *location, float vis ) {
+void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) {
 
     // traverse the potentially viewable tile list and update range
     // selector and transform
@@ -504,12 +499,12 @@ void FGTileMgr::prep_ssg_nodes( FGLocation *location, float vis ) {
 
     while ( ! tile_cache.at_end() ) {
         // cout << "processing a tile" << endl;
-       if ( (e = tile_cache.get_current()) ) {
-           e->prep_ssg_node( center, up, vis);
+        if ( (e = tile_cache.get_current()) ) {
+            e->prep_ssg_node( center, up, vis);
         } else {
-           SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache");
+            SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache");
         }
-       tile_cache.next();
-   }
+        tile_cache.next();
+    }
 }