1
0
Fork 0

From: "Jim Wilson" <jimw@kelcomaine.com>

This is a new improved patch for the previous tile manager fixes.

Rather than building dependencies between FGlocation or the viewer or fdm with
tilemgr what I ended up doing was linking the pieces together in the Mainloop
in main.cxx.  You'll see what I mean...it's been commented fairly well.  More
than likely we should move that chunk somewhere...just not sure where yet.

The changes seem clean now. As I get more ideas there could be some further
improvement in organizing the update in tilemgr.  You'll note that I left an
override in there for the tilemgr::update() function to preserve earlier
functionality if someone needs it (e.g. usage independent of an fdm or
viewer), not to mention there are a few places in flightgear that call it
directly that have not been changed to the new interface (and may not need to be).

The code has been optimized to avoid duplicate traversals and seems to run
generally quite well.  Note that there can be a short delay reloading tiles
that have been dropped from static views.  We could call the tile scheduler on
a view switch, but it's not a big deal and at the moment I'd like to get this
in so people can try it and comment on it as it is.

Everything has been resycned with CVS tonight and I've included the
description submitted earlier (below).

Best,

Jim

Changes synced with CVS approx 20:30EDT 2002-05-09 (after this evenings updates).

Files:
http://www.spiderbark.com/fgfs/viewer-update-20020516.tar.gz
 or
http://www.spiderbark.com/fgfs/viewer-update-20020516.diffs.gz

Description:
In a nutshell, these patches begin to take what was one value for ground
elevation and calculate ground elevation values seperately for the FDM and the
viewer (eye position).  Several outstanding view related bugs have been fixed.

With the introduction of the new viewer code a lot of that Flight Gear code
broke related to use of a global variable called "scenery.cur_elev".

Therefore the ground_elevation and other associated items (like the current
tile bucket) is maintained per FDM instance and per View.  Each of these has a
"point" or location that can be identified.  See changes to FGLocation class
and main.cxx.

Most of the problems related to the new viewer in terms of sky, ground and
runway lights, and tower views are fixed.

There are four minor problems remaining.  1) The sun/moon spins when you pan
the "lookat" tower view only (view #3).  2) Under stress (esp. magic carpet
full speed with max visibility), there is a memory leak in the tile caching
that was not introduced with these changes.  3) I have not tested these
changes or made corrections to the ADA or External FDM interfaces.  4) The
change view function doesn't call the time/light update (not a problem unless
a tower is very far away).

Details:
FDM/flight.cxx, flight.hxx - FGInterface ties to FGAircraftModel so that it's
 location data can be accessed for runway (ground elevation under aircraft)
 elevation.

FDM/larsim.cxx, larcsim.hxx - gets runway elevation from FGInterface now.
Commented out function that is causing a namespace conflict, hasn't been
called with recent code anyway.

FDM/JSBSim/JSBSim.cxx, YASim/YASim.cxx - gets runway elevation from
FGInterface now.

Scenery/newcache.cxx, newcache.hxx - changed caching scheme to time based
(oldest tiles discard).

Scenery/tileentry.cxx, tileentry.hxx - added place to record time, changed
rendering to reference viewer altitude in order to fix a problem with ground
and runway lights.

Scenery/tilemgr.cxx, tilemgr.hxx - Modified update() to accept values for
multiple locations.   Refresh function added in  order to periodically make
the tiles current for a non-moving view (like a tower).

Main/fg_init.cxx - register event for making tiles current in a non-moving
view (like a tower).

Main/location.hxx - added support for current ground elevation data.

Main/main.cxx - added second tilemgr call for fdm, fixed places where viewer
position data was required for correct sky rendering.

Main/options.cxx - fixed segfault reported by Curtis when using --view-offset
command line parameter.

Main/viewer.cxx, viewer.hxx - removed fudging of view position. Fixed numerous
bugs that were causing eye and target values to get mixed up.
This commit is contained in:
curt 2002-05-17 17:25:28 +00:00
parent e8a6836525
commit b1674cb506
18 changed files with 559 additions and 414 deletions

View file

@ -34,7 +34,7 @@
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Scenery/scenery.hxx>
#include <FDM/flight.hxx>
#include <Aircraft/aircraft.hxx>
#include <Controls/controls.hxx>
@ -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;

View file

@ -25,8 +25,6 @@
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <Scenery/scenery.hxx>
#include <Main/fg_props.hxx>
#include <Aircraft/aircraft.hxx>
#include <Controls/controls.hxx>
@ -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,

View file

@ -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 );
*/
};

View file

@ -3,7 +3,6 @@
#include <simgear/xml/easyxml.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Scenery/scenery.hxx>
#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;

View file

@ -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 );

View file

@ -93,6 +93,9 @@
// #include <simgear/timing/timestamp.hxx>
#include <Main/fgfs.hxx>
#include <Model/acmodel.hxx>
#include <Model/model.hxx>
#include <Main/location.hxx>
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; }
};

View file

@ -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

View file

@ -31,6 +31,7 @@
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/bucket/newbucket.hxx>
#include <plib/sg.h> // 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

View file

@ -100,6 +100,8 @@ SG_USING_STD(endl);
#include <GUI/gui.h>
#include <Model/acmodel.hxx>
#include <Model/modelmgr.hxx>
#include <Model/model.hxx>
#include <Main/location.hxx>
#ifdef FG_NETWORK_OLK
#include <NetworkOLK/network.h>
#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, "" );
}

View file

@ -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

View file

@ -39,7 +39,6 @@
#include <simgear/math/sg_geodesy.hxx>
#include <Scenery/scenery.hxx>
//#include <Main/location.hxx>
#include <simgear/math/vector.hxx>
#include <Main/globals.hxx>
@ -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()
{

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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

View file

@ -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; }
};

View file

@ -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;

View file

@ -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; }
};