From 7b824755ee96b8db4240ca9999570f3c7bacdad7 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 14 Aug 2005 12:57:12 +0000 Subject: [PATCH] =?UTF-8?q?Mathias=20Fr=F6hlich:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/AIModel/AIAircraft.cxx | 63 +++------------- src/ATC/AILocalTraffic.cxx | 33 ++++---- src/Cockpit/cockpit.cxx | 6 +- src/FDM/ExternalNet/ExternalNet.cxx | 2 +- src/FDM/ExternalPipe/ExternalPipe.cxx | 4 +- src/FDM/SP/ADA.cxx | 2 +- src/FDM/flight.cxx | 3 + src/Main/fg_init.cxx | 4 - src/Main/main.cxx | 105 +++++++++++--------------- src/Main/renderer.cxx | 4 +- src/Network/native_fdm.cxx | 4 +- src/Network/native_gui.cxx | 3 +- src/Scenery/scenery.cxx | 63 +++++++++++++++- src/Scenery/scenery.hxx | 43 +++++++---- src/Scenery/tileentry.cxx | 22 +++--- src/Scenery/tilemgr.cxx | 94 +++++++++-------------- src/Scenery/tilemgr.hxx | 22 ++---- 17 files changed, 223 insertions(+), 254 deletions(-) diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index efe563057..08623551b 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -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(); + // 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 ); + } - 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; + // 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; } - -//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()); -//} diff --git a/src/ATC/AILocalTraffic.cxx b/src/ATC/AILocalTraffic.cxx index c96a4661f..fe716d904 100644 --- a/src/ATC/AILocalTraffic.cxx +++ b/src/ATC/AILocalTraffic.cxx @@ -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); } diff --git a/src/Cockpit/cockpit.cxx b/src/Cockpit/cockpit.cxx index 8b49ca916..ce8d5d897 100644 --- a/src/Cockpit/cockpit.cxx +++ b/src/Cockpit/cockpit.cxx @@ -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; diff --git a/src/FDM/ExternalNet/ExternalNet.cxx b/src/FDM/ExternalNet/ExternalNet.cxx index 72578bd79..c00ce9d40 100644 --- a/src/FDM/ExternalNet/ExternalNet.cxx +++ b/src/FDM/ExternalNet/ExternalNet.cxx @@ -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" ); diff --git a/src/FDM/ExternalPipe/ExternalPipe.cxx b/src/FDM/ExternalPipe/ExternalPipe.cxx index 4cd13bc81..ddb044046 100644 --- a/src/FDM/ExternalPipe/ExternalPipe.cxx +++ b/src/FDM/ExternalPipe/ExternalPipe.cxx @@ -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" ); diff --git a/src/FDM/SP/ADA.cxx b/src/FDM/SP/ADA.cxx index 11728b7bf..4ef0ea608 100644 --- a/src/FDM/SP/ADA.cxx +++ b/src/FDM/SP/ADA.cxx @@ -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; } diff --git a/src/FDM/flight.cxx b/src/FDM/flight.cxx index cedeb29a7..9bda7929a 100644 --- a/src/FDM/flight.cxx +++ b/src/FDM/flight.cxx @@ -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"); diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 2e2f653ac..66a0f327b 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -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. diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 7188ffa37..e3b2f22f9 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -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()) { diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 05b85037b..cfa716fb4 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -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 { diff --git a/src/Network/native_fdm.cxx b/src/Network/native_fdm.cxx index e2b6a69ae..88ac0ffa9 100644 --- a/src/Network/native_fdm.cxx +++ b/src/Network/native_fdm.cxx @@ -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, diff --git a/src/Network/native_gui.cxx b/src/Network/native_gui.cxx index b9d3ce489..2047a0aef 100644 --- a/src/Network/native_gui.cxx +++ b/src/Network/native_gui.cxx @@ -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", diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 8e0f361c1..88badf93e 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -30,10 +30,12 @@ #include #include +#include #include #include
+#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; +} diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx index d96660cee..847f2e3a4 100644 --- a/src/Scenery/scenery.hxx +++ b/src/Scenery/scenery.hxx @@ -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; } diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index d3b900071..b0639d588 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -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; } diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 1cd496edd..9b28c8894 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -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; +} diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index 6e4b30f34..a487264da 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -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); };