]> git.mxchange.org Git - flightgear.git/commitdiff
Mathias Fröhlich:
authorehofman <ehofman>
Sun, 14 Aug 2005 12:57:12 +0000 (12:57 +0000)
committerehofman <ehofman>
Sun, 14 Aug 2005 12:57:12 +0000 (12:57 +0000)
I have prepared a patch that:
- Introduces a FGTileMgr::scenery_available method which asks the tilemanager
  if scenery for a given range around a lat/lon pair is already loaded and make
  use of that method at some -9999 meter checks.
- Introduces a FGScenery::get_elevation_m method which queries the altitude at
  a given position. In constrast to the groundcache functions this is the best
  choice if you ask for one *single* altitude value. Make use of that thing in
  AI/ATC classes and for the current views ground level. At the current views
  part the groundcache is reused if possible.
- The computation of the 'current groundlevel' is no longer done on the
  tilemanagers update since the required functions are now better seperated.

Alltogether it eliminates somehow redundant terrain level computations which
are now superseeded by that more finegrained functions and the existence of
the groundcache. Additionally it introduces an api to commonly required
functions which was very complex to do prevously.

17 files changed:
src/AIModel/AIAircraft.cxx
src/ATC/AILocalTraffic.cxx
src/Cockpit/cockpit.cxx
src/FDM/ExternalNet/ExternalNet.cxx
src/FDM/ExternalPipe/ExternalPipe.cxx
src/FDM/SP/ADA.cxx
src/FDM/flight.cxx
src/Main/fg_init.cxx
src/Main/main.cxx
src/Main/renderer.cxx
src/Network/native_fdm.cxx
src/Network/native_gui.cxx
src/Scenery/scenery.cxx
src/Scenery/scenery.hxx
src/Scenery/tileentry.cxx
src/Scenery/tilemgr.cxx
src/Scenery/tilemgr.hxx

index efe563057f06e9b1ad57d2bbca2e8f1cdf23b267..08623551ba53d966b6a492ae40eaa49fa9c179e8 100644 (file)
@@ -907,56 +907,17 @@ void FGAIAircraft::getGroundElev(double dt) {
     return;
   }
     
-  
-  //globals->get_tile_mgr()->prep_ssg_nodes( acmodel_location,
-  globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(),        visibility_meters );
-  Point3D scenery_center = globals->get_scenery()->get_center();
-
-  globals->get_tile_mgr()->update( aip.getSGLocation(), 
-                                  visibility_meters, 
-                                  (aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
-  // save results of update in SGLocation for fdm...
-  
-  //if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-  //   acmodel_location->
-  //   set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-  //}
-  
-  // The need for this here means that at least 2 consecutive passes are needed :-(
-  aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
-    globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(),      visibility_meters );
-    //Point3D scenery_center = globals->get_scenery()->get_center();
-
-  globals->get_tile_mgr()->update( aip.getSGLocation(), 
-                                  visibility_meters, 
-                                  (aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
-  // save results of update in SGLocation for fdm...
-  
-  //if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-  //   acmodel_location->
-  //   set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-  //}
-  
-  // The need for this here means that at least 2 consecutive passes are needed :-(
-  aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
-  //cerr << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
-  tgt_altitude = (globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET) + groundOffset;
-}
-
-//globals->get_tile_mgr()->prep_ssg_nodes( _aip.getSGLocation(),       visibility_meters );
-//Point3D scenery_center = globals->get_scenery()->get_center();
-//globals->get_tile_mgr()->update(_aip.getSGLocation(), visibility_meters, (_aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
-// save results of update in SGLocation for fdm...
-
-//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-//     acmodel_location->
-//     set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-//}
-
-// The need for this here means that at least 2 consecutive passes are needed :-(
-//_aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
+  // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+  double range = 500.0;
+  if (!globals->get_tile_mgr()->scenery_available(pos.lat(), pos.lon(), range))
+  {
+    // Try to shedule tiles for that position.
+    globals->get_tile_mgr()->update( aip.getSGLocation(), range );
+  }
 
-//cout << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
-//_aip.getSGLocation()->set_cur_elev_m(globals->get_scenery()->get_cur_elev());
-//return(globals->get_scenery()->get_cur_elev());
-//}
+  // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+  double alt;
+  if (globals->get_scenery()->get_elevation_m(pos.lat(), pos.lon(),
+                                              20000.0, alt))
+      tgt_altitude = alt;
+}
index c96a4661f49af32c57a11fee9eb113e3a1ef6ee4..fe716d9043b9c7acfb758a068d72266e31a6572e 100644 (file)
@@ -1580,24 +1580,19 @@ void FGAILocalTraffic::DoGroundElev() {
                _aip.getSGLocation()->set_cur_elev_m(aptElev);
                return;
        }
-       
-       
-       //globals->get_tile_mgr()->prep_ssg_nodes( acmodel_location,
-       globals->get_tile_mgr()->prep_ssg_nodes( _aip.getSGLocation(),  visibility_meters );
-       Point3D scenery_center = globals->get_scenery()->get_center();
-       globals->get_tile_mgr()->update( _aip.getSGLocation(), visibility_meters, (_aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
-       // save results of update in SGLocation for fdm...
-       
-       //if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-       //      acmodel_location->
-       //      set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-       //}
-       
-       // The need for this here means that at least 2 consecutive passes are needed :-(
-       _aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
-       
-       //cout << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
-       _aip.getSGLocation()->set_cur_elev_m(globals->get_scenery()->get_cur_elev());
-       //return(globals->get_scenery()->get_cur_elev());
+
+        // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+        double range = 500.0;
+        double lat = _aip.getSGLocation()->getLatitude_deg();
+        double lon = _aip.getSGLocation()->getLongitude_deg();
+        if (!globals->get_tile_mgr()->scenery_available(lat, lon, range)) {
+          // Try to shedule tiles for that position.
+          globals->get_tile_mgr()->update( _aip.getSGLocation(), range );
+        }
+
+        // FIXME: make shure the pos.lat/pos.lon values are in degrees ...
+        double alt;
+        if (globals->get_scenery()->get_elevation_m(lat, lon, 20000.0, alt))
+          _aip.getSGLocation()->set_cur_elev_m(alt);
 }
 
index 8b49ca916485f4062b61c98e21a3372f6597e97d..ce8d5d897546c5779fc82061b25dc418a803d8bc 100644 (file)
@@ -207,10 +207,10 @@ float get_agl( void )
 
     if ( !strcmp(startup_units_node->getStringValue(), "feet") ) {
         agl = (current_aircraft.fdm_state->get_Altitude()
-               - globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET);
+               - current_aircraft.fdm_state->get_Runway_altitude());
     } else {
-        agl = (current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
-               - globals->get_scenery()->get_cur_elev());
+        agl = (current_aircraft.fdm_state->get_Altitude()
+               - current_aircraft.fdm_state->get_Runway_altitude()) * SG_FEET_TO_METER;
     }
 
     return agl;
index 72578bd79e34271b455618194ce5df4d0e5b1f7a..c00ce9d40e849a60b552d7019652efa8ca544827 100644 (file)
@@ -102,7 +102,7 @@ void FGExternalNet::init() {
     double lon = fgGetDouble( "/sim/presets/longitude-deg" );
     double lat = fgGetDouble( "/sim/presets/latitude-deg" );
     double alt = fgGetDouble( "/sim/presets/altitude-ft" );
-    double ground = fgGetDouble( "/environment/ground-elevation-m" );
+    double ground = get_Runway_altitude_m();
     double heading = fgGetDouble("/sim/presets/heading-deg");
     double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
 
index 4cd13bc81a9f13c0a0dd7a3b40295406f8df06f4..ddb044046a0018f29dc8b7b9a26a520b51b86cda 100644 (file)
@@ -230,7 +230,7 @@ void FGExternalPipe::init_binary() {
     double lon = fgGetDouble( "/sim/presets/longitude-deg" );
     double lat = fgGetDouble( "/sim/presets/latitude-deg" );
     double alt = fgGetDouble( "/sim/presets/altitude-ft" );
-    double ground = fgGetDouble( "/environment/ground-elevation-m" );
+    double ground = get_Runway_altitude_m();
     double heading = fgGetDouble("/sim/presets/heading-deg");
     double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
     double weight = fgGetDouble( "/sim/aircraft-weight-lbs" );
@@ -293,7 +293,7 @@ void FGExternalPipe::init_property() {
     double lon = fgGetDouble( "/sim/presets/longitude-deg" );
     double lat = fgGetDouble( "/sim/presets/latitude-deg" );
     double alt = fgGetDouble( "/sim/presets/altitude-ft" );
-    double ground = fgGetDouble( "/environment/ground-elevation-m" );
+    double ground = get_Runway_altitude_m();
     double heading = fgGetDouble("/sim/presets/heading-deg");
     double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
     double weight = fgGetDouble( "/sim/aircraft-weight-lbs" );
index 11728b7bf2940b7a091249849f1aace8629d6b16..4ef0ea6083a4356829a72682e81dd44b4d801f43 100644 (file)
@@ -235,7 +235,7 @@ void FGADA::update( double dt ) {
 
 // Convert from the FGInterface struct to the FGADA struct (output)
 bool FGADA::copy_to_FGADA () {
-    ground_elevation = globals->get_scenery()->get_cur_elev();
+    ground_elevation = get_Runway_altitude_m();
     return true;
 }
 
index cedeb29a760ee1da97fd0b68682813f1880464fa..9bda7929a94ccee04dc0a25c3bd01f27240f8466 100644 (file)
@@ -314,6 +314,8 @@ FGInterface::bind ()
   fgSetArchivable("/position/ground-elev-m");
   fgTie("/position/ground-elev-m", this,
         &FGInterface::get_Runway_altitude_m); // read-only
+  fgTie("/environment/ground-elevation-m", this,
+        &FGInterface::get_Runway_altitude_m); // read-only
   fgSetArchivable("/position/sea-level-radius-ft");
   fgTie("/position/sea-level-radius-ft", this,
         &FGInterface::get_Sea_level_radius); // read-only
@@ -452,6 +454,7 @@ FGInterface::unbind ()
   fgUntie("/position/altitude-agl-ft");
   fgUntie("/position/ground-elev-ft");
   fgUntie("/position/ground-elev-m");
+  fgUntie("/environment/ground-elevation-m");
   fgUntie("/position/sea-level-radius-ft");
   fgUntie("/orientation/roll-deg");
   fgUntie("/orientation/pitch-deg");
index 2e2f653ac3d839f4b460fa208610346b0d731845..66a0f327b38fb2a32301a844fee6607be096c2b7 100644 (file)
@@ -1607,10 +1607,6 @@ bool fgInitSubsystems() {
                                        &FGTileMgr::refresh_view_timestamps,
                                        15 );
 
-    SG_LOG( SG_GENERAL, SG_DEBUG,
-            "Current terrain elevation after tile mgr init " <<
-            globals->get_scenery()->get_cur_elev() );
-
 
     ////////////////////////////////////////////////////////////////////
     // Initialize the flight model subsystem.
index 7188ffa3770a48b6e4514885038d02b1b4f7bee0..e3b2f22f98e40c55c4db7bdc4c258f431f92254b 100644 (file)
@@ -139,15 +139,21 @@ void fgUpdateTimeDepCalcs() {
     // cout << "cur_fdm_state->get_inited() = " << cur_fdm_state->get_inited() 
     //      << " cur_elev = " << scenery.get_cur_elev() << endl;
 
-    if ( !cur_fdm_state->get_inited() &&
-         globals->get_scenery()->get_cur_elev() > -9990 )
-    {
-        SG_LOG(SG_FLIGHT,SG_INFO, "Finally initializing fdm");  
+    if (!cur_fdm_state->get_inited()) {
+      // Check for scenery around the aircraft.
+      double lon = fgGetDouble("/sim/presets/longitude-deg");
+      double lat = fgGetDouble("/sim/presets/latitude-deg");
+      // We require just to have 50 meter scenery availabe around
+      // the aircraft.
+      double range = 50.0;
+      if (globals->get_tile_mgr()->scenery_available(lat, lon, range)) {
+        SG_LOG(SG_FLIGHT,SG_INFO, "Finally initializing fdm");
         cur_fdm_state->init();
         if ( cur_fdm_state->get_bound() ) {
             cur_fdm_state->unbind();
         }
         cur_fdm_state->bind();
+      }
     }
 
     // conceptually, the following block could be done for each fdm
@@ -520,55 +526,39 @@ static void fgMainLoop( void ) {
       globals->get_scenery()->set_next_center( cntr );
     }
 
-    // get the location data for the primary FDM (now hardcoded to ac model)...
-    SGLocation *acmodel_loc = NULL;
-    acmodel_loc = (SGLocation *)globals->
-        get_aircraft_model()->get3DModel()->getSGLocation();
-
-    // update tile manager for FDM...
-    // ...only if location is different than the current-view location
-    // (to avoid duplicating effort)
-    if( !fgGetBool("/sim/current-view/config/from-model") ) {
-        if( acmodel_loc != NULL ) {
-            globals->get_tile_mgr()->prep_ssg_nodes( acmodel_loc,
-                                                     visibility_meters );
-            globals->get_tile_mgr()->
-                update( acmodel_loc, visibility_meters,
-                        acmodel_loc->
-                        get_absolute_view_pos(globals->
-                                              get_scenery()->get_center()) );
-            globals->get_scenery()->set_center( cntr );
-
-            // save results of update in SGLocation for fdm...
-            if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-                acmodel_loc->
-                    set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
-                fgSetDouble("/position/ground-elev-m",
-                            globals->get_scenery()->get_cur_elev());
-            }
-            acmodel_loc->
-                set_tile_center( globals->get_scenery()->get_next_center() );
-        }
-    }
-
     globals->get_tile_mgr()->prep_ssg_nodes( current_view->getSGLocation(),
                                              visibility_meters );
     // update tile manager for view...
-    // IMPORTANT!!! the tilemgr update for view location _must_ be
-    // done last after the FDM's until all of Flight Gear code
-    // references the viewer's location for elevation instead of the
-    // "scenery's" current elevation.
     SGLocation *view_location = globals->get_current_view()->getSGLocation();
-    globals->get_tile_mgr()->update( view_location, visibility_meters,
-                                     current_view->get_absolute_view_pos() );
+    globals->get_tile_mgr()->update( view_location, visibility_meters );
     globals->get_scenery()->set_center( cntr );
-    // save results of update in SGLocation for fdm...
-    if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-        current_view->getSGLocation()->
-            set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
+    {
+      double lon = view_location->getLongitude_deg();
+      double lat = view_location->getLatitude_deg();
+      double alt = view_location->getAltitudeASL_ft() * SG_FEET_TO_METER;
+
+      // check if we can reuse the groundcache for that purpose.
+      double ref_time, pt[3], r;
+      bool valid = cur_fdm_state->is_valid_m(&ref_time, pt, &r);
+      if (valid &&
+          cntr.distance3Dsquared(Point3D(pt[0], pt[1], pt[2])) < r*r) {
+        // Reuse the cache ...
+        double lev
+          = cur_fdm_state->get_groundlevel_m(lat*SGD_DEGREES_TO_RADIANS,
+                                             lon*SGD_DEGREES_TO_RADIANS,
+                                             alt + 2.0);
+        view_location->set_cur_elev_m( lev );
+      } else {
+        // Do full intersection test.
+        double lev;
+        if (globals->get_scenery()->get_elevation_m(lat, lon, alt+2, lev))
+          view_location->set_cur_elev_m( lev );
+        else
+          view_location->set_cur_elev_m( -9999.0 );
+      }
     }
-    current_view->getSGLocation()->
-        set_tile_center( globals->get_scenery()->get_next_center() );
+
+    view_location->set_tile_center( globals->get_scenery()->get_next_center() );
 
 #ifdef ENABLE_AUDIO_SUPPORT
     // Right now we make a simplifying assumption that the primary
@@ -577,6 +567,11 @@ static void fgMainLoop( void ) {
 
     static sgVec3 last_pos_offset;
 
+    // get the location data for the primary FDM (now hardcoded to ac model)...
+    SGLocation *acmodel_loc = NULL;
+    acmodel_loc = (SGLocation *)globals->
+        get_aircraft_model()->get3DModel()->getSGLocation();
+
     // set positional offset for sources
     sgVec3 source_pos_offset;
     sgSubVec3( source_pos_offset,
@@ -600,22 +595,6 @@ static void fgMainLoop( void ) {
     globals->get_soundmgr()->set_listener_pos( listener_pos );
 #endif
 
-    // If fdm location is same as viewer's then we didn't do the
-    // update for fdm location above so we need to save the viewer
-    // results in the fdm SGLocation as well...
-    if( fgGetBool("/sim/current-view/config/from-model") ) {
-        if( acmodel_loc != 0 ) {
-            if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
-                acmodel_loc->set_cur_elev_m( globals->get_scenery()->
-                                             get_cur_elev() );
-                fgSetDouble("/position/ground-elev-m",
-                            globals->get_scenery()->get_cur_elev());
-            }
-            acmodel_loc->set_tile_center( globals->get_scenery()->
-                                          get_next_center() );
-        }
-    }
-
     // END Tile Manager udpates
 
     if (!scenery_loaded && globals->get_tile_mgr()->all_queues_empty() && cur_fdm_state->get_inited()) {
index 05b85037b78deab076ebd3e8360f882fd6423835..cfa716fb499daa9424109e78d875e5b0a20b91e5 100644 (file)
@@ -489,9 +489,9 @@ FGRenderer::update( bool refresh_camera_settings ) {
 
     double agl =
         current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
-        - globals->get_scenery()->get_cur_elev();
+        - cur_fdm_state->get_Runway_altitude_m();
 
-    if ( agl > 50.0 ) {
+    if ( agl > 10.0 ) {
         scene_nearplane = 10.0f;
         scene_farplane = 120000.0f;
     } else {
index e2b6a69ae888fcb9df986ca9c3f766db7b888d71..88ac0ffa9cd9236f0a8c49da0d06017d8d064b05 100644 (file)
@@ -383,8 +383,8 @@ void FGNetFDM2Props( FGNetFDM *net, bool net_byte_order ) {
        if ( net->agl > -9000 ) {
            cur_fdm_state->_set_Altitude_AGL( net->agl * SG_METER_TO_FEET );
        } else {
-           double agl_m
-             = net->altitude - globals->get_scenery()->get_cur_elev();
+           double agl_m = net->altitude
+              - cur_fdm_state->get_Runway_altitude_m();
            cur_fdm_state->_set_Altitude_AGL( agl_m * SG_METER_TO_FEET );
        }
         cur_fdm_state->_set_Euler_Angles( net->phi,
index b9d3ce4896f7a8895d6c150b89043d69406ba2a9..2047a0aef3977b7158c37ef30043ba5f1955304e 100644 (file)
@@ -163,7 +163,7 @@ void FGProps2NetGUI( FGNetGUI *net ) {
     // Environment
     net->cur_time = globals->get_time_params()->get_cur_time();
     net->warp = globals->get_warp();
-    net->ground_elev = globals->get_scenery()->get_cur_elev();
+    net->ground_elev = cur_fdm_state->get_Runway_altitude_m();
 
     // Approach
     net->tuned_freq = nav_freq->getDoubleValue();
@@ -304,7 +304,6 @@ void FGNetGUI2Props( FGNetGUI *net ) {
        }
 
         globals->set_warp( net->warp );
-        globals->get_scenery()->set_cur_elev( net->ground_elev );
 
         // Approach
         fgSetDouble( "/instrumentation/nav[0]/frequencies/selected-mhz",
index 8e0f361c1b1f64dca4325a619561cd42355e189e..88badf93eea9498ce85dc92804f8071ef04a3526 100644 (file)
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
+#include <simgear/math/sg_geodesy.hxx>
 #include <simgear/scene/model/placementtrans.hxx>
 
 #include <Main/fg_props.hxx>
 
+#include "hitlist.hxx"
 #include "scenery.hxx"
 
 
@@ -42,7 +44,6 @@ FGScenery::FGScenery() {
     SG_LOG( SG_TERRAIN, SG_INFO, "Initializing scenery subsystem" );
 
     center = Point3D(0.0);
-    cur_elev = -9999;
 }
 
 
@@ -93,13 +94,10 @@ void FGScenery::update(double dt) {
 
 
 void FGScenery::bind() {
-    fgTie("/environment/ground-elevation-m", this,
-         &FGScenery::get_cur_elev, &FGScenery::set_cur_elev);
 }
 
 
 void FGScenery::unbind() {
-    fgUntie("/environment/ground-elevation-m");
 }
 
 void FGScenery::set_center( Point3D p ) {
@@ -131,3 +129,60 @@ void FGScenery::unregister_placement_transform(ssgPlacementTransform *trans) {
             ++it;
     }
 }
+
+bool
+FGScenery::get_elevation_m(double lat, double lon, double max_alt,
+                           double& alt, bool exact)
+{
+//   std::cout << __PRETTY_FUNCTION__ << " "
+//             << lat << " "
+//             << lon << " "
+//             << max_alt
+//             << std::endl;
+  sgdVec3 pos;
+  sgGeodToCart(lat*SG_DEGREES_TO_RADIANS, lon*SG_DEGREES_TO_RADIANS,
+               max_alt, pos);
+  return get_cart_elevation_m(pos, 0, alt, exact);
+}
+
+bool
+FGScenery::get_cart_elevation_m(const sgdVec3 pos, double max_altoff,
+                                double& alt, bool exact)
+{
+  Point3D saved_center = center;
+  bool replaced_center = false;
+  if (exact) {
+    Point3D ppos(pos[0], pos[1], pos[2]);
+    if (30.0*30.0 < ppos.distance3Dsquared(center)) {
+      set_center( ppos );
+      replaced_center = false;
+    }
+  }
+
+  // overridden with actual values if a terrain intersection is
+  // found
+  double hit_radius = 0.0;
+  sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
+  
+  bool hit = false;
+  if ( fabs(pos[0]) > 1.0 || fabs(pos[1]) > 1.0 || fabs(pos[2]) > 1.0 ) {
+    sgdVec3 sc;
+    sgdSetVec3(sc, center[0], center[1], center[2]);
+    
+    sgdVec3 ncpos;
+    sgdCopyVec3(ncpos, pos);
+    
+    FGHitList hit_list;
+    
+    // scenery center has been properly defined so any hit should
+    // be valid (and not just luck)
+    hit = fgCurrentElev(ncpos, max_altoff+sgdLengthVec3(pos),
+                        sc, (ssgTransform*)get_scene_graph(),
+                        &hit_list, &alt, &hit_radius, hit_normal);
+  }
+
+  if (replaced_center)
+    set_center( saved_center );
+  
+  return hit;
+}
index d96660ceec006e711508093d961c0c4c89553286..847f2e3a4da4c25bcd7ed33dba6e40a6a77fd9a0 100644 (file)
@@ -52,20 +52,10 @@ class FGScenery : public SGSubsystem {
     // next center of current scenery chunk
     Point3D next_center;
 
+    // FIXME this should be a views property
     // angle of sun relative to current local horizontal
     double sun_angle;
 
-    // elevation of terrain at our current lat/lon (based on the
-    // actual drawn polygons)
-    double cur_elev;
-
-    // the distance (radius) from the center of the earth to the
-    // current scenery elevation point
-    double cur_radius;
-
-    // unit normal at point used to determine current elevation
-    sgdVec3 cur_normal;
-
     // SSG scene graph
     ssgRoot *scene_graph;
     ssgBranch *terrain_branch;
@@ -91,8 +81,32 @@ public:
     void unbind ();
     void update (double dt);
 
-    inline double get_cur_elev() const { return cur_elev; }
-    inline void set_cur_elev( double e ) { cur_elev = e; }
+    /// Compute the elevation of the scenery at geodetic latitude lat,
+    /// geodetic longitude lon and not higher than max_alt.
+    /// If the exact flag is set to true, the scenery center is moved to
+    /// gain a higher accuracy of that query. The center is restored past
+    /// that to the original value.
+    /// The altitude hit is returned in the alt argument.
+    /// The method returns true if the scenery is available for the given
+    /// lat/lon pair. If there is no scenery for that point, the altitude
+    /// value is undefined. 
+    /// All values are meant to be in meters or degrees.
+    bool get_elevation_m(double lat, double lon, double max_alt,
+                         double& alt, bool exact = false);
+
+    /// Compute the elevation of the scenery beow the cartesian point pos.
+    /// you the returned scenery altitude is not higher than the position
+    /// pos plus an ofset given with max_altoff.
+    /// If the exact flag is set to true, the scenery center is moved to
+    /// gain a higher accuracy of that query. The center is restored past
+    /// that to the original value.
+    /// The altitude hit is returned in the alt argument.
+    /// The method returns true if the scenery is available for the given
+    /// lat/lon pair. If there is no scenery for that point, the altitude
+    /// value is undefined.
+    /// All values are meant to be in meters.
+    bool get_cart_elevation_m(const sgdVec3 pos, double max_altoff,
+                              double& radius, bool exact = false);
 
     inline Point3D get_center() const { return center; }
     void set_center( Point3D p );
@@ -100,9 +114,6 @@ public:
     inline Point3D get_next_center() const { return next_center; }
     inline void set_next_center( Point3D p ) { next_center = p; }
 
-    inline void set_cur_radius( double r ) { cur_radius = r; }
-    inline void set_cur_normal( sgdVec3 n ) { sgdCopyVec3( cur_normal, n ); }
-
     inline ssgRoot *get_scene_graph () const { return scene_graph; }
     inline void set_scene_graph (ssgRoot * s) { scene_graph = s; }
 
index d3b900071f1b5504270f992c153fd36cabe4f99e..b0639d5880745e6f3d3fad479940dc81f92acd16 100644 (file)
@@ -343,8 +343,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         sgCopyVec3( lift_vec, up );
 
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev();
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m();
 
         // Compute the distance of the scenery center from the view position.
         double dist = center.distance3D(p);
@@ -386,9 +386,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
@@ -421,9 +421,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
@@ -462,9 +462,9 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
         // we fudge agl by 30 meters so that the lifting function
         // doesn't phase in until we are > 30m agl.
         double agl;
-        agl = globals->get_current_view()->getAltitudeASL_ft()
-            * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev()
-            - 30.0;
+        agl = globals->get_current_view()->getAltitudeASL_ft()*SG_FEET_TO_METER
+          - globals->get_current_view()->getSGLocation()->get_cur_elev_m()
+          - 30.0;
         if ( agl < 0.0 ) {
             agl = 0.0;
         }
index 1cd496edddc276dc558f3a6f6daebf9276ef8080..9b28c8894939dd70f10612af69d84c166746be02 100644 (file)
@@ -333,8 +333,6 @@ void FGTileMgr::update_queues()
         }
     }
     
-    // cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl;
-
     // Notify the tile loader that it can load another tile
     loader.update();
 
@@ -386,15 +384,11 @@ void FGTileMgr::update_queues()
 int FGTileMgr::update( double visibility_meters )
 {
     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 );
+    return update( location, visibility_meters );
 }
 
 
-int FGTileMgr::update( SGLocation *location, double visibility_meters,
-                       sgdVec3 abs_pos_vector )
+int FGTileMgr::update( SGLocation *location, double visibility_meters )
 {
     SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update()" );
 
@@ -442,9 +436,6 @@ int FGTileMgr::update( SGLocation *location, double visibility_meters,
     // save bucket...
     previous_bucket = current_bucket;
 
-    updateCurrentElevAtPos( abs_pos_vector, altitude_m,
-                            location->get_tile_center() );
-
     return 1;
 }
 
@@ -461,52 +452,6 @@ void FGTileMgr::refresh_view_timestamps() {
     }
 }
 
-
-int FGTileMgr::updateCurrentElevAtPos( sgdVec3 abs_pos_vector,
-                                       double max_alt_m,
-                                       Point3D center)
-{
-    sgdVec3 sc;
-
-    sgdSetVec3( sc, center[0], center[1], center[2]);
-
-    // overridden with actual values if a terrain intersection is
-    // found
-    double hit_elev = -9999.0;
-    double hit_radius = 0.0;
-    sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
-    
-    bool hit = false;
-    if ( fabs(sc[0]) > 1.0 || fabs(sc[1]) > 1.0 || fabs(sc[2]) > 1.0 ) {
-        // 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,
-                            &hit_radius,
-                            hit_normal);
-    }
-
-    if ( hit ) {
-        // cout << "elev = " << hit_elev << " " << hit_radius << endl;
-        globals->get_scenery()->set_cur_elev( hit_elev );
-        globals->get_scenery()->set_cur_radius( hit_radius );
-        globals->get_scenery()->set_cur_normal( hit_normal );
-    } else {
-        globals->get_scenery()->set_cur_elev( -9999.0 );
-        globals->get_scenery()->set_cur_radius( 0.0 );
-        globals->get_scenery()->set_cur_normal( hit_normal );
-    }
-    return hit;
-}
-
-
 void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) {
 
     // traverse the potentially viewable tile list and update range
@@ -541,3 +486,38 @@ int FGTileMgr::tile_filter_cb( ssgEntity *, int )
 {
   return tile_filter ? 1 : 0;
 }
+
+bool FGTileMgr::scenery_available(double lat, double lon, double range_m)
+{
+  // sanity check (unfortunately needed!)
+  if ( lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0 )
+    return false;
+  
+  SGBucket bucket(lon, lat);
+  FGTileEntry *te = tile_cache.get_tile(bucket);
+  if (!te || !te->is_loaded())
+    return false;
+
+  // Traverse all tiles required to be there for the given visibility.
+  // This uses exactly the same algorithm like the tile scheduler.
+  double tile_width = bucket.get_width_m();
+  double tile_height = bucket.get_height_m();
+  
+  int xrange = (int)fabs(range_m / tile_width) + 1;
+  int yrange = (int)fabs(range_m / tile_height) + 1;
+  
+  for ( int x = -xrange; x <= xrange; ++x ) {
+    for ( int y = -yrange; y <= yrange; ++y ) {
+      // We have already checked for the center tile.
+      if ( x != 0 || y != 0 ) {
+        SGBucket b = sgBucketOffset( lon, lat, x, y );
+        FGTileEntry *te = tile_cache.get_tile(b);
+        if (!te || !te->is_loaded())
+          return false;
+      }
+    }
+  }
+
+  // Survived all tests.
+  return true;
+}
index 6e4b30f34e73a74abaeadcb0da13559db2585b59..a487264dadf67d7b75e2fd574c65b254caafcf62 100644 (file)
@@ -166,22 +166,7 @@ public:
     // local chunks.  If the chunk isn't already in the cache, then
     // read it from disk.
     int update( double visibility_meters );
-    int update( SGLocation *location, double visibility_meters,
-                sgdVec3 abs_pos_vector );
-
-    int updateCurrentElevAtPos( sgdVec3 abs_pos_vector, double altitude_m,
-                                Point3D center );
-
-    // Determine scenery altitude.  Normally this just happens when we
-    // render the scene, but we'd also like to be able to do this
-    // explicitely.  lat & lon are in radians.  abs_view_pos in
-    // meters.  Returns result in meters.
-    void my_ssg_los( string s, ssgBranch *branch, sgdMat4 m, 
-                    const sgdVec3 p, const sgdVec3 dir, sgdVec3 normal );
-       
-    void my_ssg_los( ssgBranch *branch, sgdMat4 m, 
-                    const sgdVec3 p, const sgdVec3 dir,
-                    FGHitList *list );
+    int update( SGLocation *location, double visibility_meters);
 
     // Prepare the ssg nodes corresponding to each tile.  For each
     // tile, set the ssg transform and update it's range selector
@@ -198,6 +183,11 @@ public:
 
     static bool set_tile_filter( bool f );
     static int tile_filter_cb( ssgEntity *, int );
+
+    /// Returns true if scenery is avaliable for the given lat, lon position
+    /// within a range of range_m.
+    /// lat and lon are expected to be in degrees.
+    bool scenery_available(double lat, double lon, double range_m);
 };