diff --git a/src/FDM/JSBSim/JSBSim.cxx b/src/FDM/JSBSim/JSBSim.cxx index 0cc28f7dd..d2d9f5c74 100644 --- a/src/FDM/JSBSim/JSBSim.cxx +++ b/src/FDM/JSBSim/JSBSim.cxx @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include @@ -291,9 +291,8 @@ FGJSBsim::update( double dt ) { if ( startup_trim->getBoolValue() ) { SG_LOG(SG_FLIGHT, SG_INFO, "Ready to trim, terrain altitude is: " - << globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET ); - fgic->SetTerrainAltitudeFtIC( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET ); + fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() ); do_trim(); } else { fdmex->RunIC(fgic); //apply any changes made through the set_ functions @@ -370,8 +369,7 @@ bool FGJSBsim::copy_to_JSBsim() { eng->SetStarter( globals->get_controls()->get_starter(i) ); } - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() ); Position->SetSeaLevelRadius( get_Sea_level_radius() ); Position->SetRunwayRadius( get_Runway_altitude() + get_Sea_level_radius() ); @@ -588,10 +586,8 @@ void FGJSBsim::set_Latitude(double lat) { &sea_level_radius_meters, &lat_geoc ); _set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); - fgic->SetTerrainAltitudeFtIC( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() ); + fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() ); fgic->SetLatitudeRadIC( lat_geoc ); needTrim=true; } @@ -601,10 +597,8 @@ void FGJSBsim::set_Longitude(double lon) { SG_LOG(SG_FLIGHT,SG_INFO,"FGJSBsim::set_Longitude: " << lon ); update_ic(); fgic->SetLongitudeRadIC( lon ); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); - fgic->SetTerrainAltitudeFtIC( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() ); + fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() ); needTrim=true; } @@ -621,13 +615,10 @@ void FGJSBsim::set_Altitude(double alt) { &sea_level_radius_meters, &lat_geoc); _set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET ); fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET ); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); - fgic->SetTerrainAltitudeFtIC( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( cur_fdm_state->get_Runway_altitude() ); + fgic->SetTerrainAltitudeFtIC( cur_fdm_state->get_ground_elev_ft() ); SG_LOG(SG_FLIGHT, SG_INFO, - "Terrain altitude: " << globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + "Terrain altitude: " << cur_fdm_state->get_Runway_altitude() * SG_METER_TO_FEET ); fgic->SetLatitudeRadIC( lat_geoc ); fgic->SetAltitudeFtIC(alt); needTrim=true; diff --git a/src/FDM/LaRCsim.cxx b/src/FDM/LaRCsim.cxx index 78840a805..43223bf4c 100644 --- a/src/FDM/LaRCsim.cxx +++ b/src/FDM/LaRCsim.cxx @@ -25,8 +25,6 @@ #include #include -#include - #include
#include #include @@ -188,8 +186,7 @@ void FGLaRCsim::update( double dt ) { // Inform LaRCsim of the local terrain altitude // Runway_altitude = get_Runway_altitude(); - Runway_altitude = globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET; - + Runway_altitude = getACModel()->get3DModel()->getFGLocation()->get_cur_elev_m() * SG_METER_TO_FEET; // Weather /* V_north_airmass = get_V_north_airmass(); V_east_airmass = get_V_east_airmass(); @@ -616,8 +613,6 @@ void FGLaRCsim::snap_shot(void) { void FGLaRCsim::set_Latitude(double lat) { SG_LOG( SG_FLIGHT, SG_INFO, "FGLaRCsim::set_Latitude: " << lat ); snap_shot(); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); lsic->SetLatitudeGDRadIC(lat); set_ls(); copy_from_LaRCsim(); //update the bus @@ -626,9 +621,6 @@ void FGLaRCsim::set_Latitude(double lat) { void FGLaRCsim::set_Longitude(double lon) { SG_LOG( SG_FLIGHT, SG_INFO, "FGLaRCsim::set_Longitude: " << lon ); snap_shot(); - - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); lsic->SetLongitudeRadIC(lon); set_ls(); copy_from_LaRCsim(); //update the bus @@ -637,8 +629,6 @@ void FGLaRCsim::set_Longitude(double lon) { void FGLaRCsim::set_Altitude(double alt) { SG_LOG( SG_FLIGHT, SG_INFO, "FGLaRCsim::set_Altitude: " << alt ); snap_shot(); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); lsic->SetAltitudeFtIC(alt); set_ls(); copy_from_LaRCsim(); //update the bus @@ -717,6 +707,7 @@ void FGLaRCsim::set_AltitudeAGL(double altagl) { copy_from_LaRCsim(); } +/* getting a namespace conflict... void FGLaRCsim::set_Velocities_Local_Airmass (double wnorth, double weast, double wdown ) { @@ -727,6 +718,7 @@ void FGLaRCsim::set_Velocities_Local_Airmass (double wnorth, set_ls(); copy_from_LaRCsim(); } +*/ void FGLaRCsim::set_Static_pressure(double p) { SG_LOG( SG_FLIGHT, SG_INFO, diff --git a/src/FDM/LaRCsim.hxx b/src/FDM/LaRCsim.hxx index df2b5389c..7ce2ddc80 100644 --- a/src/FDM/LaRCsim.hxx +++ b/src/FDM/LaRCsim.hxx @@ -84,9 +84,11 @@ public: void set_Static_temperature(double T); void set_Density(double rho); +/* void set_Velocities_Local_Airmass (double wnorth, double weast, double wdown ); +*/ }; diff --git a/src/FDM/YASim/YASim.cxx b/src/FDM/YASim/YASim.cxx index 2c87d1baf..aa3ed775c 100644 --- a/src/FDM/YASim/YASim.cxx +++ b/src/FDM/YASim/YASim.cxx @@ -3,7 +3,6 @@ #include #include
#include
-#include #include "FGFDM.hpp" #include "Atmosphere.hpp" @@ -161,8 +160,7 @@ void YASim::init() // Are we at ground level? If so, lift the plane up so the gear // clear the ground. - double runway_altitude = - fgGetDouble("/environment/ground-elevation-m") * SG_METER_TO_FEET; + double runway_altitude = get_Runway_altitude(); fgSetBool("/controls/gear-down", false); if(get_Altitude() - runway_altitude < 50) { float minGearZ = 1e18; @@ -232,10 +230,9 @@ void YASim::copyToYASim(bool copyState) wind[1] = get_V_east_airmass() * FT2M * -1.0; wind[2] = get_V_down_airmass() * FT2M * -1.0; - // The ground elevation doesn't come from FGInterface; query it - // from the scenery and set it for others to find. - double ground = globals->get_scenery()->get_cur_elev(); - _set_Runway_altitude(ground * FT2M); + // Get ground elevation from the FGinterface's FGlocation data + double ground = getACModel()->get3DModel()->getFGLocation()->get_cur_elev_m(); + // cout << "YASIM: ground = " << ground << endl; float pressure = fgGetDouble("/environment/pressure-inhg") * INHG2PA; float temp = fgGetDouble("/environment/temperature-degC") + 273.15; diff --git a/src/FDM/flight.cxx b/src/FDM/flight.cxx index 2845c8e3b..2694fa7f4 100644 --- a/src/FDM/flight.cxx +++ b/src/FDM/flight.cxx @@ -159,6 +159,7 @@ FGInterface::_setup () sin_latitude=cos_latitude=0; sin_longitude=cos_longitude=0; altitude_agl=0; + _acmodel = 0; } void @@ -182,6 +183,12 @@ FGInterface::common_init () // stamp(); // set_remainder( 0 ); + // linking in FGAircraft instance... + // FIXME: when using multiple instances, then there will be more than + // one model so get_aircraft_model will have to be indexed to the correct + // model. + _acmodel = globals->get_aircraft_model(); + // Set initial position SG_LOG( SG_FLIGHT, SG_INFO, "...initializing position..." ); set_Longitude( fgGetDouble("/position/longitude-deg") @@ -190,6 +197,8 @@ FGInterface::common_init () * SGD_DEGREES_TO_RADIANS ); double ground_elev_m = globals->get_scenery()->get_cur_elev(); double ground_elev_ft = ground_elev_m * SG_METER_TO_FEET; + _acmodel->get3DModel()->getFGLocation()->set_cur_elev_m( ground_elev_m ); + _set_Runway_altitude ( ground_elev_ft ); if ( fgGetBool("/sim/startup/onground") || fgGetDouble("/position/altitude-ft") < ground_elev_ft ) { fgSetDouble("/position/altitude-ft", ground_elev_ft); @@ -448,8 +457,7 @@ void FGInterface::_updateGeodeticPosition( double lat, double lon, double alt ) _set_Geodetic_Position( lat, lon, alt ); _set_Sea_level_radius( sl_radius * SG_METER_TO_FEET ); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( getACModel()->get3DModel()->getFGLocation()->get_cur_elev_m() * SG_METER_TO_FEET ); _set_sin_lat_geocentric( lat_geoc ); _set_cos_lat_geocentric( lat_geoc ); @@ -505,8 +513,7 @@ void FGInterface::_updateGeocentricPosition( double lat_geoc, double lon, _set_Geodetic_Position( lat_geod, lon, alt ); _set_Sea_level_radius( sl_radius2 * SG_METER_TO_FEET ); - _set_Runway_altitude( globals->get_scenery()->get_cur_elev() - * SG_METER_TO_FEET ); + _set_Runway_altitude( getACModel()->get3DModel()->getFGLocation()->get_cur_elev_m() * SG_METER_TO_FEET ); _set_sin_lat_geocentric( lat_geoc ); _set_cos_lat_geocentric( lat_geoc ); diff --git a/src/FDM/flight.hxx b/src/FDM/flight.hxx index afc4ded02..8dc1aaebb 100644 --- a/src/FDM/flight.hxx +++ b/src/FDM/flight.hxx @@ -93,6 +93,9 @@ // #include #include
+#include +#include +#include
SG_USING_STD(list); SG_USING_STD(vector); @@ -224,6 +227,9 @@ private: // SGTimeStamp valid_stamp; // time this record is valid // SGTimeStamp next_stamp; // time this record is valid + // Model tied to FDM + FGAircraftModel * _acmodel; + protected: int _calc_multiloop (double dt); @@ -1071,6 +1077,12 @@ public: inline float get_faux( int n ) const { return faux[n]; } inline int get_iaux( int n ) const { return iaux[n]; } + // Model tied to FDM + FGAircraftModel * getACModel() const { return _acmodel; } + + // Note that currently this is the "same" value runway altitude... + inline double get_ground_elev_ft() const { return runway_altitude; } + }; diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 5eb89321f..dae961c61 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -740,6 +740,17 @@ bool fgInitSubsystems( void ) { exit(-1); } + //////////////////////////////////////////////////////////////////// + // Initialize the event manager subsystem. + //////////////////////////////////////////////////////////////////// + + global_events.init(); + + // Output event stats every 60 seconds + global_events.Register( "FGEventMgr::print_stats()", + &global_events, &FGEventMgr::print_stats, + 60000 ); + //////////////////////////////////////////////////////////////////// // Initialize the scenery management subsystem. @@ -757,6 +768,11 @@ bool fgInitSubsystems( void ) { exit(-1); } + // cause refresh of viewer scenery timestamps every 15 seconds... + global_events.Register( "FGTileMgr::refresh_view_timestamps()", + &global_tile_mgr, &FGTileMgr::refresh_view_timestamps, + 15000 ); + SG_LOG( SG_GENERAL, SG_DEBUG, "Current terrain elevation after tile mgr init " << globals->get_scenery()->get_cur_elev() ); @@ -781,19 +797,7 @@ bool fgInitSubsystems( void ) { //////////////////////////////////////////////////////////////////// - // Initialize the event manager subsystem. - //////////////////////////////////////////////////////////////////// - - global_events.init(); - - // Output event stats every 60 seconds - global_events.Register( "FGEventMgr::print_stats()", - &global_events, &FGEventMgr::print_stats, - 60000 ); - - - //////////////////////////////////////////////////////////////////// - // Initialize the lightingsubsystem. + // Initialize the lighting subsystem. //////////////////////////////////////////////////////////////////// // fgUpdateSunPos() needs a few position and view parameters set diff --git a/src/Main/location.hxx b/src/Main/location.hxx index 44b2f1235..ad7647a27 100644 --- a/src/Main/location.hxx +++ b/src/Main/location.hxx @@ -31,6 +31,7 @@ #include #include +#include #include // plib include @@ -106,6 +107,14 @@ public: virtual float *get_surface_east() { return _surface_east; } // Get surface south vector virtual float *get_surface_south() { return _surface_south; } + // Elevation of ground under location (based on scenery output)... + void set_cur_elev_m ( double elev ) { _cur_elev_m = elev; } + inline double get_cur_elev_m () { return _cur_elev_m; } + // Interface to current buckets for use with tilemgr... + void set_current_bucket ( SGBucket current_bucket ) { _current_bucket = current_bucket; } + inline SGBucket get_current_bucket () { return _current_bucket; } + void set_previous_bucket ( SGBucket previous_bucket ) { _previous_bucket = previous_bucket; } + inline SGBucket get_previous_bucket () { return _previous_bucket; } // Matrices... virtual const sgVec4 * getTransformMatrix() { if ( _dirty ) { recalc(); } return TRANS; } @@ -135,6 +144,13 @@ private: double _pitch_deg; double _heading_deg; + // elevation of ground under this location... + double _cur_elev_m; + // current and previous scenery buckets to be saved for use in + // getting current elevation from tilemgr. + SGBucket _previous_bucket; + SGBucket _current_bucket; + // surface vector heading south sgVec3 _surface_south; @@ -163,17 +179,3 @@ private: #endif // _LOCATION_HXX - - - - - - - - - - - - - - diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 49aa6ca96..478ea8bba 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -100,6 +100,8 @@ SG_USING_STD(endl); #include #include #include +#include +#include
#ifdef FG_NETWORK_OLK #include #endif @@ -534,11 +536,11 @@ void fgRenderFrame() { thesky->reposition( current__view->get_view_pos(), current__view->get_zero_elev(), current__view->get_world_up(), - longitude->getDoubleValue() + current__view->getLongitude_deg() * SGD_DEGREES_TO_RADIANS, - latitude->getDoubleValue() + current__view->getLatitude_deg() * SGD_DEGREES_TO_RADIANS, - altitude->getDoubleValue() * SG_FEET_TO_METER, + current__view->getAltitudeASL_ft() * SG_FEET_TO_METER, cur_light_params.sun_rotation, globals->get_time_params()->getGst(), globals->get_ephem()->getSunRightAscension(), @@ -860,6 +862,11 @@ static void fgMainLoop( void ) { SGTime *t = globals->get_time_params(); + FGLocation * acmodel_location = 0; + if(cur_fdm_state->getACModel() != 0) { + acmodel_location = (FGLocation *) cur_fdm_state->getACModel()->get3DModel()->getFGLocation(); + } + SG_LOG( SG_ALL, SG_DEBUG, "Running Main Loop"); SG_LOG( SG_ALL, SG_DEBUG, "======= ==== ===="); @@ -897,25 +904,26 @@ static void fgMainLoop( void ) { cur_fdm_state->get_Runway_altitude() * SG_FEET_TO_METER, cur_fdm_state->get_Altitude() * SG_FEET_TO_METER); */ - if ( globals->get_scenery()->get_cur_elev() > -9990 - && cur_fdm_state->get_inited() ) - { - if ( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER < - (globals->get_scenery()->get_cur_elev() + alt_adjust_m - 3.0) ) { +// Curt is this code used? I don't see any problems when I comment it out. + if ( acmodel_location != 0 ) { + if ( acmodel_location->get_cur_elev_m() > -9990 && cur_fdm_state->get_inited() ) { + if ( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER < + (acmodel_location->get_cur_elev_m() + alt_adjust_m - 3.0) ) { // now set aircraft altitude above ground printf("(*) Current Altitude = %.2f < %.2f forcing to %.2f\n", cur_fdm_state->get_Altitude() * SG_FEET_TO_METER, - globals->get_scenery()->get_cur_elev() + alt_adjust_m - 3.0, - globals->get_scenery()->get_cur_elev() + alt_adjust_m ); - cur_fdm_state->set_Altitude( globals->get_scenery()->get_cur_elev() - + alt_adjust_m ); - + acmodel_location->get_cur_elev_m() + alt_adjust_m - 3.0, + acmodel_location->get_cur_elev_m() + alt_adjust_m ); + cur_fdm_state->set_Altitude( (acmodel_location->get_cur_elev_m() + + alt_adjust_m) * SG_METER_TO_FEET ); SG_LOG( SG_ALL, SG_DEBUG, "<*> resetting altitude to " << cur_fdm_state->get_Altitude() * SG_FEET_TO_METER << " meters" ); } + } } +// End of code in question. (see Curt is this code used? above) /* printf("Adjustment - ground = %.2f runway = %.2f alt = %.2f\n", scenery.get_cur_elev(), @@ -1057,10 +1065,67 @@ static void fgMainLoop( void ) { // redraw display fgRenderFrame(); - // see if we need to load any new scenery tiles + + // + // Tile Manager updates - see if we need to load any new scenery tiles. + // this code ties together the fdm, viewer and scenery classes... + // we may want to move this to it's own class at some point + // double visibility_meters = fgGetDouble("/environment/visibility-m"); - global_tile_mgr.update( longitude->getDoubleValue(), - latitude->getDoubleValue(), visibility_meters ); + FGViewer *current_view = globals->get_current_view(); + + // update tile manager for FDM... + // ...only if location is different than the viewer (to avoid duplicating effort) + if( acmodel_location != current_view->getFGLocation() ) { + if( acmodel_location != 0 ) { + global_tile_mgr.update( acmodel_location->getLongitude_deg(), + acmodel_location->getLatitude_deg(), + visibility_meters, + acmodel_location->get_absolute_view_pos(), + acmodel_location->get_current_bucket(), + acmodel_location->get_previous_bucket() + ); + // save results of update in FGLocation for fdm... + if ( globals->get_scenery()->get_cur_elev() > -9990 ) { + acmodel_location->set_cur_elev_m( globals->get_scenery()->get_cur_elev() ); + } + acmodel_location->set_current_bucket( global_tile_mgr.get_current_bucket() ); + acmodel_location->set_previous_bucket( global_tile_mgr.get_previous_bucket() ); + } + } + + // 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. + global_tile_mgr.update( current_view->getLongitude_deg(), + current_view->getLatitude_deg(), + visibility_meters, + current_view->get_absolute_view_pos(), + current_view->getFGLocation()->get_current_bucket(), + current_view->getFGLocation()->get_previous_bucket() + ); + // save results of update in FGLocation for fdm... + if ( globals->get_scenery()->get_cur_elev() > -9990 ) { + current_view->getFGLocation()->set_cur_elev_m( globals->get_scenery()->get_cur_elev() ); + } + current_view->getFGLocation()->set_current_bucket( global_tile_mgr.get_current_bucket() ); + current_view->getFGLocation()->set_previous_bucket( global_tile_mgr.get_previous_bucket() ); + + // 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 FGLocation as well... + if( acmodel_location == current_view->getFGLocation() ) { + if( acmodel_location != 0 ) { + if ( globals->get_scenery()->get_cur_elev() > -9990 ) { + acmodel_location->set_cur_elev_m( globals->get_scenery()->get_cur_elev() ); + } + acmodel_location->set_current_bucket( global_tile_mgr.get_current_bucket() ); + acmodel_location->set_previous_bucket( global_tile_mgr.get_previous_bucket() ); + } + } + + // END Tile Manager udpates + SG_LOG( SG_ALL, SG_DEBUG, "" ); } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index e9adb43c0..12e660753 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -886,8 +886,7 @@ parse_option (const string& arg) } FGViewer *pilot_view = (FGViewer *)globals->get_viewmgr()->get_view( 0 ); - pilot_view->setHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES ); - pilot_view->setGoalHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES ); + // this will work without calls to the viewer... fgSetDouble( "/sim/current-view/heading-offset-deg", default_view_offset * SGD_RADIANS_TO_DEGREES ); // $$$ end - added VS Renganathan, 14 Oct 2K diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index 8efc1e0d7..1f6194826 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -39,7 +39,6 @@ #include #include -//#include
#include #include
@@ -446,36 +445,16 @@ void FGViewer::updateFromModelLocation (FGLocation * location) { sgCopyMat4(LOCAL, location->getCachedTransformMatrix()); - _lon_deg = location->getLongitude_deg(); - _lat_deg = location->getLatitude_deg(); - _alt_ft = location->getAltitudeASL_ft(); - _roll_deg = location->getRoll_deg(); - _pitch_deg = location->getPitch_deg(); - _heading_deg = location->getHeading_deg(); - sgCopyVec3(_zero_elev_view_pos, location->get_zero_elev()); - sgCopyVec3(_relative_view_pos, location->get_view_pos()); - sgdCopyVec3(_absolute_view_pos, location->get_absolute_view_pos()); - sgCopyMat4(UP, location->getCachedUpMatrix()); - sgCopyVec3(_world_up, location->get_world_up()); - // these are the vectors that the sun and moon code like to get... - sgCopyVec3(_surface_east, location->get_surface_east()); - sgCopyVec3(_surface_south, location->get_surface_south()); } void -FGViewer::recalcOurOwnLocation (double lon_deg, double lat_deg, double alt_ft, +FGViewer::recalcOurOwnLocation (FGLocation * location, double lon_deg, double lat_deg, double alt_ft, double roll_deg, double pitch_deg, double heading_deg) { // update from our own data... - _location->setPosition( lon_deg, lat_deg, alt_ft ); - _location->setOrientation( roll_deg, pitch_deg, heading_deg ); - sgCopyMat4(LOCAL, _location->getTransformMatrix()); - sgCopyVec3(_zero_elev_view_pos, _location->get_zero_elev()); - sgCopyVec3(_relative_view_pos, _location->get_view_pos()); - sgdCopyVec3(_absolute_view_pos, _location->get_absolute_view_pos()); - // these are the vectors that the sun and moon code like to get... - sgCopyVec3(_surface_east, _location->get_surface_east()); - sgCopyVec3(_surface_south, _location->get_surface_south()); + location->setPosition( lon_deg, lat_deg, alt_ft ); + location->setOrientation( roll_deg, pitch_deg, heading_deg ); + sgCopyMat4(LOCAL, location->getTransformMatrix()); } // recalc() is done every time one of the setters is called (making the @@ -484,198 +463,185 @@ FGViewer::recalcOurOwnLocation (double lon_deg, double lat_deg, double alt_ft, void FGViewer::recalc () { + if (_type == FG_LOOKFROM) { + recalcLookFrom(); + } else { + recalcLookAt(); + } + + set_clean(); +} + +// recalculate for LookFrom view type... +void +FGViewer::recalcLookFrom () +{ + sgVec3 right, forward; - sgMat4 tmpROT; // temp rotation work matrices - sgVec3 eye_pos, at_pos; + sgVec3 eye_pos; sgVec3 position_offset; // eye position offsets (xyz) - // The position vectors originate from the view point or target location - // depending on the type of view. - - if (_type == FG_LOOKFROM) { - // LOOKFROM mode... - if ( _from_model ) { - // update or data from model location - updateFromModelLocation(_location); - } else { - // update from our own data... - recalcOurOwnLocation( _lon_deg, _lat_deg, _alt_ft, - _roll_deg, _pitch_deg, _heading_deg ); - // get world up data from just recalced location - sgCopyMat4(UP, _location->getUpMatrix()); - sgCopyVec3(_world_up, _location->get_world_up()); - } + // LOOKFROM mode... + // Update location data... + if ( _from_model ) { + // update or data from model location + updateFromModelLocation(_location); } else { - - // LOOKAT mode... - if ( _from_model ) { - // update or data from model location - updateFromModelLocation(_location); - } else { - // update from our own data, just the rotation here... - recalcOurOwnLocation( _lon_deg, _lat_deg, _alt_ft, - _roll_deg, _pitch_deg, _heading_deg ); - // get world up data from just recalced location - sgCopyMat4(UP, _location->getUpMatrix()); - sgCopyVec3(_world_up, _location->get_world_up()); - } - // save they eye positon... - sgCopyVec3(eye_pos, _location->get_view_pos()); - // save the eye rotation before getting target values!!! - sgCopyMat4(tmpROT, LOCAL); - - if ( _at_model ) { - // update or data from model location - updateFromModelLocation(_target_location); - } else { - // if not model then calculate our own target position... - recalcOurOwnLocation( _target_lon_deg, _target_lat_deg, _target_alt_ft, - _target_roll_deg, _target_pitch_deg, _target_heading_deg ); - } - // restore the eye rotation (the from position rotation) - sgCopyMat4(LOCAL, tmpROT); - + // update from our own data... + recalcOurOwnLocation( _location, _lon_deg, _lat_deg, _alt_ft, + _roll_deg, _pitch_deg, _heading_deg ); } - // the coordinates generated by the above "recalcPositionVectors" - sgCopyVec3(_zero_elev, _zero_elev_view_pos); - sgCopyVec3(_view_pos, _relative_view_pos); - - // FIXME: - // Doing this last recalc here for published values...where the airplane is - // This should be per aircraft or model (for published values) before - // multiple FDM can be done. - // This info should come directly from the model (not through viewer), - // because in some cases there is no model directly assigned as a lookfrom - // position. The problem that arises is related to the FDM interface looking - // indirectly to the viewer to find the altitude of the aircraft on the runway. - // - // Note that recalcPositionVectors can be removed from viewer when this - // issue is addressed. - // - if (!_from_model) { - recalcPositionVectors(fgGetDouble("/position/longitude-deg"), - fgGetDouble("/position/latitude-deg"), - fgGetDouble("/position/altitude-ft")); - } + // copy data from location class to local items... + copyLocationData(); // make sg vectors view up, right and forward vectors from LOCAL sgSetVec3( _view_up, LOCAL[2][0], LOCAL[2][1], LOCAL[2][2] ); sgSetVec3( right, LOCAL[1][0], LOCAL[1][1], LOCAL[1][2] ); sgSetVec3( forward, -LOCAL[0][0], -LOCAL[0][1], -LOCAL[0][2] ); - if (_type == FG_LOOKAT) { - // Note that when in "lookat" view the "world up" vector is always applied - // to the viewer. World up is based on verticle at a given lon/lat (see - // matrix "UP" above). + // Note that when in "lookfrom" view the "view up" vector is always applied + // to the viewer. View up is based on verticle of the aircraft itself. (see + // "LOCAL" matrix above) - // Orientation Offsets matrix - MakeVIEW_OFFSET( VIEW_OFFSET, - (_heading_offset_deg -_heading_deg) * SG_DEGREES_TO_RADIANS, _world_up, - _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); - - // add in the Orientation Offsets here - sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m ); - sgXformVec3( position_offset, position_offset, UP); + // Orientation Offsets matrix + MakeVIEW_OFFSET( VIEW_OFFSET, + _heading_offset_deg * SG_DEGREES_TO_RADIANS, _view_up, + _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); - sgXformVec3( position_offset, position_offset, VIEW_OFFSET ); + // Make the VIEW matrix. + sgSetVec4(VIEW[0], right[0], right[1], right[2],SG_ZERO); + sgSetVec4(VIEW[1], forward[0], forward[1], forward[2],SG_ZERO); + sgSetVec4(VIEW[2], _view_up[0], _view_up[1], _view_up[2],SG_ZERO); + sgSetVec4(VIEW[3], SG_ZERO, SG_ZERO, SG_ZERO,SG_ONE); - // add the Position offsets from object to the eye position - sgAddVec3( eye_pos, eye_pos, position_offset ); + // rotate matrix to get a matrix to apply Eye Position Offsets + sgMat4 VIEW_UP; // L0 forward L1 right L2 up + sgCopyVec4(VIEW_UP[0], LOCAL[1]); + sgCopyVec4(VIEW_UP[1], LOCAL[2]); + sgCopyVec4(VIEW_UP[2], LOCAL[0]); + sgZeroVec4(VIEW_UP[3]); - // at position (what we are looking at) - sgCopyVec3( at_pos, _view_pos ); + // Eye Position Offsets to vector + sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m ); + sgXformVec3( position_offset, position_offset, VIEW_UP); - // Make the VIEW matrix for a "LOOKAT". - sgMakeLookAtMat4( VIEW, eye_pos, at_pos, _view_up ); - } + // add the offsets including rotations to the translation vector + sgAddVec3( _view_pos, position_offset ); - if (_type == FG_LOOKFROM) { + // multiply the OFFSETS (for heading and pitch) into the VIEW + sgPostMultMat4(VIEW, VIEW_OFFSET); - // Note that when in "lookfrom" view the "view up" vector is always applied - // to the viewer. View up is based on verticle of the aircraft itself. (see - // "LOCAL" matrix above) + // add the position data to the matrix + sgSetVec4(VIEW[3], _view_pos[0], _view_pos[1], _view_pos[2],SG_ONE); - // Orientation Offsets matrix - MakeVIEW_OFFSET( VIEW_OFFSET, - _heading_offset_deg * SG_DEGREES_TO_RADIANS, _view_up, - _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); - - // Make the VIEW matrix. - sgSetVec4(VIEW[0], right[0], right[1], right[2],SG_ZERO); - sgSetVec4(VIEW[1], forward[0], forward[1], forward[2],SG_ZERO); - sgSetVec4(VIEW[2], _view_up[0], _view_up[1], _view_up[2],SG_ZERO); - sgSetVec4(VIEW[3], SG_ZERO, SG_ZERO, SG_ZERO,SG_ONE); - - // rotate matrix to get a matrix to apply Eye Position Offsets - sgMat4 VIEW_UP; // L0 forward L1 right L2 up - sgCopyVec4(VIEW_UP[0], LOCAL[1]); - sgCopyVec4(VIEW_UP[1], LOCAL[2]); - sgCopyVec4(VIEW_UP[2], LOCAL[0]); - sgZeroVec4(VIEW_UP[3]); - - // Eye Position Offsets to vector - sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m ); - sgXformVec3( position_offset, position_offset, VIEW_UP); - - // add the offsets including rotations to the translation vector - sgAddVec3( _view_pos, position_offset ); - - // multiply the OFFSETS (for heading and pitch) into the VIEW - sgPostMultMat4(VIEW, VIEW_OFFSET); - - // add the position data to the matrix - sgSetVec4(VIEW[3], _view_pos[0], _view_pos[1], _view_pos[2],SG_ONE); - - } - - set_clean(); } void -FGViewer::recalcPositionVectors (double lon_deg, double lat_deg, double alt_ft) const +FGViewer::recalcLookAt () { - double sea_level_radius_m; - double lat_geoc_rad; + sgVec3 right; + sgVec3 eye_pos, at_pos; + sgVec3 position_offset; // eye position offsets (xyz) - // Convert from geodetic to geocentric - // coordinates. - sgGeodToGeoc(lat_deg * SGD_DEGREES_TO_RADIANS, - alt_ft * SG_FEET_TO_METER, - &sea_level_radius_m, - &lat_geoc_rad); + // The position vectors originate from the view point or target location + // depending on the type of view. - // Calculate the cartesian coordinates - // of point directly below at sea level. - // aka Zero Elevation Position - Point3D p = Point3D(lon_deg * SG_DEGREES_TO_RADIANS, - lat_geoc_rad, - sea_level_radius_m); - Point3D tmp = sgPolarToCart3d(p) - globals->get_scenery()->get_next_center(); - sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]); + // LOOKAT mode... - // Calculate the absolute view position - // in fgfs coordinates. - // aka Absolute View Position - p.setz(p.radius() + alt_ft * SG_FEET_TO_METER); - tmp = sgPolarToCart3d(p); - sgdSetVec3(_absolute_view_pos, tmp[0], tmp[1], tmp[2]); + // Update location data for target... + if ( _at_model ) { + // update or data from model location + updateFromModelLocation(_target_location); + } else { + // if not model then calculate our own target position... + recalcOurOwnLocation( _target_location, _target_lon_deg, _target_lat_deg, _target_alt_ft, + _target_roll_deg, _target_pitch_deg, _target_heading_deg ); + } + // save the "at" target object positon... + sgCopyVec3(at_pos, _target_location->get_view_pos()); - // Calculate the relative view position - // from the scenery center. - // aka Relative View Position - sgdVec3 scenery_center; - sgdSetVec3(scenery_center, - globals->get_scenery()->get_next_center().x(), - globals->get_scenery()->get_next_center().y(), - globals->get_scenery()->get_next_center().z()); - sgdVec3 view_pos; - sgdSubVec3(view_pos, _absolute_view_pos, scenery_center); - sgSetVec3(_relative_view_pos, view_pos); + // Update location data for eye... + if ( _from_model ) { + // update or data from model location + updateFromModelLocation(_location); + } else { + // update from our own data, just the rotation here... + recalcOurOwnLocation( _location, _lon_deg, _lat_deg, _alt_ft, + _roll_deg, _pitch_deg, _heading_deg ); + } + // save the eye positon... + sgCopyVec3(eye_pos, _location->get_view_pos()); + // copy data from location class to local items... + copyLocationData(); + + // make sg vectors view up, right and forward vectors from LOCAL + sgSetVec3( _view_up, LOCAL[2][0], LOCAL[2][1], LOCAL[2][2] ); + sgSetVec3( right, LOCAL[1][0], LOCAL[1][1], LOCAL[1][2] ); + + // Note that when in "lookat" view the "world up" vector is always applied + // to the viewer. World up is based on verticle at a given lon/lat (see + // matrix "UP" above). + + // Orientation Offsets matrix + MakeVIEW_OFFSET( VIEW_OFFSET, + (_heading_offset_deg -_heading_deg) * SG_DEGREES_TO_RADIANS, _world_up, + _pitch_offset_deg * SG_DEGREES_TO_RADIANS, right ); + + // add in the Orientation Offsets here + sgSetVec3( position_offset, _x_offset_m, _y_offset_m, _z_offset_m ); + sgXformVec3( position_offset, position_offset, UP); + + sgXformVec3( position_offset, position_offset, VIEW_OFFSET ); + + // add the Position offsets from object to the eye position + sgAddVec3( eye_pos, eye_pos, position_offset ); + + // Make the VIEW matrix for a "LOOKAT". + sgMakeLookAtMat4( VIEW, eye_pos, at_pos, _view_up ); + +} + +// copy results from location class to viewer... +// FIXME: some of these should be changed to reference directly to FGLocation... +void +FGViewer::copyLocationData() +{ + // Get our friendly vectors from the eye location... + sgCopyVec3(_zero_elev_view_pos, _location->get_zero_elev()); + sgCopyVec3(_relative_view_pos, _location->get_view_pos()); + sgdCopyVec3(_absolute_view_pos, _location->get_absolute_view_pos()); + sgCopyMat4(UP, _location->getCachedUpMatrix()); + sgCopyVec3(_world_up, _location->get_world_up()); + // these are the vectors that the sun and moon code like to get... + sgCopyVec3(_surface_east, _location->get_surface_east()); + sgCopyVec3(_surface_south, _location->get_surface_south()); + + // Update viewer's postion data for the eye location... + _lon_deg = _location->getLongitude_deg(); + _lat_deg = _location->getLatitude_deg(); + _alt_ft = _location->getAltitudeASL_ft(); + _roll_deg = _location->getRoll_deg(); + _pitch_deg = _location->getPitch_deg(); + _heading_deg = _location->getHeading_deg(); + + // Update viewer's postion data for the target (at object) location + if (_type == FG_LOOKAT) { + _target_lon_deg = _target_location->getLongitude_deg(); + _target_lat_deg = _target_location->getLatitude_deg(); + _target_alt_ft = _target_location->getAltitudeASL_ft(); + _target_roll_deg = _target_location->getRoll_deg(); + _target_pitch_deg = _target_location->getPitch_deg(); + _target_heading_deg = _target_location->getHeading_deg(); + } + + // copy coordinates to outputs for viewer... + sgCopyVec3(_zero_elev, _zero_elev_view_pos); + sgCopyVec3(_view_pos, _relative_view_pos); } double @@ -699,6 +665,8 @@ FGViewer::get_h_fov() return 0.0; } + + double FGViewer::get_v_fov() { diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index bb0eae4ef..6e5d54906 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -244,6 +244,9 @@ public: inline void set_dirty() { _dirty = true; } inline void set_clean() { _dirty = false; } + + // return eye location... + virtual FGLocation * getFGLocation () const { return _location; } private: @@ -349,9 +352,11 @@ private: ////////////////////////////////////////////////////////////////// void recalc (); - void recalcPositionVectors (double lon_deg, double lat_deg, double alt_ft) const; + void recalcLookFrom(); + void recalcLookAt(); + void copyLocationData(); void updateFromModelLocation (FGLocation * location); - void recalcOurOwnLocation (double lon_deg, double lat_deg, double alt_ft, + void recalcOurOwnLocation (FGLocation * location, double lon_deg, double lat_deg, double alt_ft, double roll_deg, double pitch_deg, double heading_deg); // add to _heading_offset_deg diff --git a/src/Scenery/newcache.cxx b/src/Scenery/newcache.cxx index 93f9d5eb2..31caaeeec 100644 --- a/src/Scenery/newcache.cxx +++ b/src/Scenery/newcache.cxx @@ -51,7 +51,7 @@ SG_USING_NAMESPACE(std); // Constructor FGNewCache::FGNewCache( void ) : - max_cache_size(50) + max_cache_size(100) { tile_cache.clear(); } @@ -105,6 +105,116 @@ bool FGNewCache::exists( const SGBucket& b ) const { } +// Ensure at least one entry is free in the cache +bool FGNewCache::make_space() { + SG_LOG( SG_TERRAIN, SG_DEBUG, "Make space in cache" ); + SG_LOG( SG_TERRAIN, SG_DEBUG, "cache entries = " << tile_cache.size() ); + SG_LOG( SG_TERRAIN, SG_DEBUG, "max size = " << max_cache_size ); + + if ( (int)tile_cache.size() < max_cache_size ) { + // space in the cache, return + return true; + } + + while ( (int)tile_cache.size() >= max_cache_size ) { + sgdVec3 abs_view_pos; + float dist; + double timestamp = 0.0; + int max_index = -1; + double min_time = 2419200000.0f; // one month should be enough + double max_time = 0; + + // we need to free the furthest entry + tile_map_iterator current = tile_cache.begin(); + tile_map_iterator end = tile_cache.end(); + + for ( ; current != end; ++current ) { + long index = current->first; + FGTileEntry *e = current->second; + if ( e->is_loaded() && (e->get_pending_models() == 0) ) { + + timestamp = e->get_timestamp(); + if ( timestamp < min_time ) { + max_index = index; + min_time = timestamp; + } + if ( timestamp > max_time ) { + max_time = timestamp; + } + + } else { + SG_LOG( SG_TERRAIN, SG_INFO, "loaded = " << e->is_loaded() + << " pending models = " << e->get_pending_models() + << " time stamp = " << e->get_timestamp() ); + } + } + + // If we made it this far, then there were no open cache entries. + // We will instead free the oldest cache entry and return true + + SG_LOG( SG_TERRAIN, SG_INFO, " min_time = " << min_time ); + SG_LOG( SG_TERRAIN, SG_INFO, " index = " << max_index ); + SG_LOG( SG_TERRAIN, SG_INFO, " max_time = " << max_time ); + if ( max_index >= 0 ) { + entry_free( max_index ); + return true; + } else { + SG_LOG( SG_TERRAIN, SG_ALERT, "WHOOPS!!! can't make_space(), tile " + "cache is full, but no entries available for removal." ); + return false; + } + } + + SG_LOG( SG_TERRAIN, SG_ALERT, "WHOOPS!!! Hit an unhandled condition in " + "FGNewCache::make_space()." ); + return false; +} + + +// Clear all completely loaded tiles (ignores partially loaded tiles) +void FGNewCache::clear_cache() { + + tile_map_iterator current = tile_cache.begin(); + tile_map_iterator end = tile_cache.end(); + + for ( ; current != end; ++current ) { + long index = current->first; + SG_LOG( SG_TERRAIN, SG_DEBUG, "clearing " << index ); + FGTileEntry *e = current->second; + if ( e->is_loaded() && (e->get_pending_models() == 0) ) { + e->tile_bucket.make_bad(); + entry_free(index); + } + } + + // and ... just in case we missed something ... + globals->get_scenery()->get_terrain_branch()->removeAllKids(); +} + + +/** + * Create a new tile and schedule it for loading. + */ +bool FGNewCache::insert_tile( FGTileEntry *e ) { + // set time of insertion for tracking age of tiles... + e->set_timestamp(globals->get_sim_time_sec()); + // clear out a distant entry in the cache if needed. + if ( make_space() ) { + // register it in the cache + long tile_index = e->get_tile_bucket().gen_index(); + tile_cache[tile_index] = e; + + return true; + } else { + // failed to find cache space + + return false; + } +} + +// Note this is the old version of FGNewCache::make_space(), currently disabled +// It uses distance from a center point to determine tiles to be discarded... +#ifdef 0 // Ensure at least one entry is free in the cache bool FGNewCache::make_space() { SG_LOG( SG_TERRAIN, SG_DEBUG, "Make space in cache" ); @@ -178,44 +288,6 @@ bool FGNewCache::make_space() { "FGNewCache::make_space()." ); return false; } +#endif -// Clear all completely loaded tiles (ignores partially loaded tiles) -void FGNewCache::clear_cache() { - - tile_map_iterator current = tile_cache.begin(); - tile_map_iterator end = tile_cache.end(); - - for ( ; current != end; ++current ) { - long index = current->first; - SG_LOG( SG_TERRAIN, SG_DEBUG, "clearing " << index ); - FGTileEntry *e = current->second; - if ( e->is_loaded() && (e->get_pending_models() == 0) ) { - e->tile_bucket.make_bad(); - entry_free(index); - } - } - - // and ... just in case we missed something ... - globals->get_scenery()->get_terrain_branch()->removeAllKids(); -} - - -/** - * Create a new tile and schedule it for loading. - */ -bool FGNewCache::insert_tile( FGTileEntry *e ) { - // clear out a distant entry in the cache if needed. - if ( make_space() ) { - // register it in the cache - long tile_index = e->get_tile_bucket().gen_index(); - tile_cache[tile_index] = e; - - return true; - } else { - // failed to find cache space - - return false; - } -} - diff --git a/src/Scenery/newcache.hxx b/src/Scenery/newcache.hxx index 0afbb9b39..4a10884bd 100644 --- a/src/Scenery/newcache.hxx +++ b/src/Scenery/newcache.hxx @@ -95,6 +95,7 @@ public: inline FGTileEntry *get_tile( const long tile_index ) { tile_map_iterator it = tile_cache.find( tile_index ); if ( it != tile_cache.end() ) { + it->second->set_timestamp(globals->get_sim_time_sec()); return it->second; } else { return NULL; diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index 94636db1f..c571293c5 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -797,12 +797,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgCopyVec3( lift_vec, up ); double agl; - if ( current_aircraft.fdm_state ) { - agl = current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER - - globals->get_scenery()->get_cur_elev(); - } else { - agl = 0.0; - } + agl = globals->get_current_view()->getAltitudeASL_ft() + * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev(); // sgTrans just happens to be the // vector from scenery center to the center of this tile which @@ -845,12 +841,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgCopyVec3( lift_vec, up ); double agl; - if ( current_aircraft.fdm_state ) { - agl = current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER - - globals->get_scenery()->get_cur_elev(); - } else { - agl = 0.0; - } + agl = globals->get_current_view()->getAltitudeASL_ft() + * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev(); // sgTrans just happens to be the // vector from scenery center to the center of this tile which @@ -900,12 +892,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgCopyVec3( lift_vec, up ); double agl1; - if ( current_aircraft.fdm_state ) { - agl1 = current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER - - globals->get_scenery()->get_cur_elev(); - } else { - agl1 = 0.0; - } + agl1 = globals->get_current_view()->getAltitudeASL_ft() + * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev(); // sgTrans just happens to be the // vector from scenery center to the center of this tile which diff --git a/src/Scenery/tileentry.hxx b/src/Scenery/tileentry.hxx index d29f761b0..e315d5150 100644 --- a/src/Scenery/tileentry.hxx +++ b/src/Scenery/tileentry.hxx @@ -190,6 +190,8 @@ private: ssgLeaf* gen_lights( ssgVertexArray *lights, int inc, float bright ); + double timestamp; + public: // ADA ---> @@ -272,6 +274,11 @@ public: * return the SSG Transform node for the terrain */ inline ssgTransform *get_terra_transform() { return terra_transform; } + + void set_timestamp(double time_ms) { timestamp = time_ms; } + + inline double get_timestamp() const { return timestamp; } + }; diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index d8463071c..a9d7f7865 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -145,7 +145,7 @@ void FGTileMgr::sched_tile( const SGBucket& b ) { // schedule a needed buckets for loading -void FGTileMgr::schedule_needed( double vis) { +void FGTileMgr::schedule_needed( double vis, SGBucket curr_bucket) { // sanity check (unfortunately needed!) if ( longitude < -180.0 || longitude > 180.0 || latitude < -90.0 || latitude > 90.0 ) @@ -162,8 +162,8 @@ void FGTileMgr::schedule_needed( double vis) { // vis = fgGetDouble("/environment/visibility-m"); - double tile_width = current_bucket.get_width_m(); - double tile_height = current_bucket.get_height_m(); + double tile_width = curr_bucket.get_width_m(); + double tile_height = curr_bucket.get_height_m(); // cout << "tile width = " << tile_width << " tile_height = " // << tile_height !<< endl; @@ -173,7 +173,8 @@ void FGTileMgr::schedule_needed( double vis) { if ( yrange < 1 ) { yrange = 1; } // cout << "xrange = " << xrange << " yrange = " << yrange << endl; - tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) ); + // note * 2 at end doubles cache size (for fdm and viewer) + tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) * 2 ); SGBucket b; @@ -223,7 +224,7 @@ void FGTileMgr::initialize_queue() // "rings" double visibility_meters = fgGetDouble("/environment/visibility-m"); - schedule_needed(visibility_meters); + schedule_needed(visibility_meters, current_bucket); // do we really want to lose this? CLO #if 0 @@ -248,32 +249,36 @@ void FGTileMgr::initialize_queue() // chunks. If the chunk isn't already in the cache, then read it from // disk. int FGTileMgr::update( double lon, double lat, double visibility_meters ) { + sgdVec3 abs_pos_vector; + sgdCopyVec3(abs_pos_vector , globals->get_current_view()->get_absolute_view_pos()); + return update( lon, lat, visibility_meters, abs_pos_vector, current_bucket, previous_bucket ); +} + +int FGTileMgr::update( double lon, double lat, double visibility_meters, sgdVec3 abs_pos_vector, SGBucket p_current, SGBucket p_previous ) { // SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for " // << lon << " " << lat ); longitude = lon; latitude = lat; + current_bucket = p_current; + previous_bucket = p_previous; + // SG_LOG( SG_TERRAIN, SG_DEBUG, "lon "<< lonlat[LON] << // " lat " << lonlat[LAT] ); - current_bucket.set_bucket( longitude, latitude ); // SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket ); - 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) ); - } + setCurrentTile( longitude, latitude); + // 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); - } + 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(); @@ -284,11 +289,12 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters ) { 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; + // cout << "loading next model ..." << endl; // load the next tile in the queue #ifdef ENABLE_THREADS FGDeferredModel* dm = model_queue.pop(); @@ -307,21 +313,20 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters ) { delete dm; } - + // cout << "current elevation (ssg) == " << scenery.get_cur_elev() << endl; + + // save bucket... previous_bucket = current_bucket; - last_longitude = longitude; - last_latitude = latitude; // activate loader thread one out of every 5 frames if ( counter_hack == 0 ) { - // Notify the tile loader that it can load another tile - - loader.update(); - + // Notify the tile loader that it can load another tile + loader.update(); + } else { + counter_hack = (counter_hack + 1) % 5; } - counter_hack = (counter_hack + 1) % 5; if ( !attach_queue.empty() ) { #ifdef ENABLE_THREADS @@ -336,60 +341,14 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters ) { // cout << "Adding ssg nodes for " } - sgdVec3 sc; - sgdSetVec3( sc, - globals->get_scenery()->get_center()[0], - globals->get_scenery()->get_center()[1], - globals->get_scenery()->get_center()[2] ); + // no reason to update this if we haven't moved... + if ( longitude != last_longitude || latitude == last_latitude ) { + // update current elevation... + updateCurrentElevAtPos(abs_pos_vector); + } - /* - cout << "abs view pos = " - << globals->get_current_view()->get_abs_view_pos()[0] << "," - << globals->get_current_view()->get_abs_view_pos()[1] << "," - << globals->get_current_view()->get_abs_view_pos()[2] - << " view pos = " - << globals->get_current_view()->get_view_pos()[0] << "," - << globals->get_current_view()->get_view_pos()[1] << "," - << globals->get_current_view()->get_view_pos()[2] - << endl; - cout << "current_tile = " << current_tile << endl; - cout << "Scenery center = " << sc[0] << "," << sc[1] << "," << sc[2] - << endl; - */ - - // 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) - sgdSetVec3( sc, - globals->get_scenery()->get_center()[0], - globals->get_scenery()->get_center()[1], - globals->get_scenery()->get_center()[2] ); - hit = fgCurrentElev(globals->get_current_view()->get_absolute_view_pos(), - sc, - current_tile->get_terra_transform(), - &hit_list, - &hit_elev, - &hit_radius, - hit_normal); - } - - if ( hit ) { - 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 ); - } - // cout << "Current elevation = " << scenery.get_cur_elev() << endl; + last_longitude = longitude; + last_latitude = latitude; #if 0 } @@ -398,6 +357,69 @@ int FGTileMgr::update( double lon, double lat, 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() ); + 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) ); + } +} + +void FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector) { + + sgdVec3 sc; + sgdSetVec3( sc, + globals->get_scenery()->get_center()[0], + globals->get_scenery()->get_center()[1], + globals->get_scenery()->get_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) + sgdSetVec3( sc, + globals->get_scenery()->get_center()[0], + globals->get_scenery()->get_center()[1], + globals->get_scenery()->get_center()[2] ); + hit = fgCurrentElev(abs_pos_vector, + sc, + current_tile->get_terra_transform(), + &hit_list, + &hit_elev, + &hit_radius, + hit_normal); + } + + if ( hit ) { + 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 ); + } + +} void FGTileMgr::prep_ssg_nodes(float vis) { // float vis = 0.0; diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index c1955f7db..41a69669e 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -78,7 +78,7 @@ private: void sched_tile( const SGBucket& b ); // schedule a needed buckets for loading - void schedule_needed(double visibility_meters); + void schedule_needed(double visibility_meters, SGBucket curr_bucket); // see comment at prep_ssg_nodes() void prep_ssg_node( int idx ); @@ -163,6 +163,9 @@ public: // local chunks. If the chunk isn't already in the cache, then // read it from disk. int update( double lon, double lat, double visibility_meters ); + int update( double lon, double lat, double visibility_meters, sgdVec3 abs_pos_vector, SGBucket p_current, SGBucket p_previous ); + void setCurrentTile( double longitude, double latitude ); + void updateCurrentElevAtPos(sgdVec3 abs_pos_vector); // Determine scenery altitude. Normally this just happens when we // render the scene, but we'd also like to be able to do this @@ -179,6 +182,14 @@ public: // transform and update it's range selector based on current // visibilty void prep_ssg_nodes(float visibility_meters); + + // + // Set flag with event manager so that non-moving view refreshes tiles... + // + void refresh_view_timestamps(); + + inline SGBucket get_current_bucket () { return current_bucket; } + inline SGBucket get_previous_bucket () { return previous_bucket; } };