1
0
Fork 0

Jim Wilson:

This is a small fix for what turned out to be a major bug.  Ground elevation
was calculated incorrectly when distant from one of the view locations. This
resulted in several problems including bizarre gear trimming, mid air
"crashes" (as in thinking we hit the ground) and so on when close to or on the
ground.

Unfortunately it does require a second ssg traversal when in tower view
(only), but the increased load isn't all that noticable.  For the time being
this really is the best solution.  In a future update I will be eliminating
the unecessary per frame traversals for the static views (without having to
maintain multiple ssgRoots).

When we go to multiple FDM instances we will perhaps need to put the ssg
traversal and ground elevation queries for the FDMs into an event timer that
updates the FDMs ground elevation in a round robin fashion (maybe every 1/n
seconds where n is the number of FDM instances running).
This commit is contained in:
curt 2002-05-20 16:13:37 +00:00
parent 0efc08b6b6
commit 8ae364a220
7 changed files with 79 additions and 41 deletions

View file

@ -275,6 +275,7 @@ do_view_cycle (const SGPropertyNode * arg, SGCommandState ** state)
globals->get_props()->setBoolValue( "/sim/hud/visibility", false );
}
}
global_tile_mgr.refresh_view_timestamps();
// fgReshape(fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize"));
return true;
}
@ -666,5 +667,4 @@ fgInitCommands ()
}
}
// end of fg_commands.hxx
// end of fg_commands.cxx

View file

@ -36,6 +36,7 @@
#include <simgear/math/vector.hxx>
#include <Scenery/scenery.hxx>
#include "globals.hxx"
#include "location.hxx"
@ -112,7 +113,9 @@ FGLocation::FGLocation( void ):
_alt_ft(0),
_roll_deg(0),
_pitch_deg(0),
_heading_deg(0)
_heading_deg(0),
_cur_elev_m(0),
_tile_center(0)
{
sgdZeroVec3(_absolute_view_pos);
}
@ -241,7 +244,7 @@ FGLocation::recalcPosition (double lon_deg, double lat_deg, double alt_ft) const
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();
Point3D tmp = sgPolarToCart3d(p) - _tile_center;
sgSetVec3(_zero_elev_view_pos, tmp[0], tmp[1], tmp[2]);
// Calculate the absolute view position
@ -254,11 +257,15 @@ FGLocation::recalcPosition (double lon_deg, double lat_deg, double alt_ft) const
// Calculate the relative view position
// from the scenery center.
// aka Relative View Position
// FIXME: view position should ONLY be calculated in the viewer...
// Anything else should calculate their own positions relative to the
// viewer's tile_center.
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());
globals->get_scenery()->get_center().x(),
globals->get_scenery()->get_center().y(),
globals->get_scenery()->get_center().z());
sgdVec3 view_pos;
sgdSubVec3(view_pos, _absolute_view_pos, scenery_center);
sgSetVec3(_relative_view_pos, view_pos);

View file

@ -32,6 +32,7 @@
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/bucket/newbucket.hxx>
#include <simgear/math/point3d.hxx>
#include <plib/sg.h> // plib include
@ -115,6 +116,8 @@ public:
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; }
void set_tile_center ( Point3D tile_center ) { _tile_center = tile_center; }
inline Point3D get_tile_center () { return _tile_center; }
// Matrices...
virtual const sgVec4 * getTransformMatrix() { if ( _dirty ) { recalc(); } return TRANS; }
@ -150,6 +153,7 @@ private:
// getting current elevation from tilemgr.
SGBucket _previous_bucket;
SGBucket _current_bucket;
Point3D _tile_center;
// surface vector heading south
sgVec3 _surface_south;

View file

@ -625,7 +625,9 @@ void fgRenderFrame() {
# endif
// position tile nodes and update range selectors
global_tile_mgr.prep_ssg_nodes(visibility_meters);
// this is done in the main loop now...
// global_tile_mgr.prep_ssg_nodes(visibility_meters);
if ( fgGetBool("/sim/rendering/skyblend") ) {
// draw the sky backdrop
@ -1064,10 +1066,6 @@ static void fgMainLoop( void ) {
}
#endif
// redraw display
fgRenderFrame();
//
// Tile Manager updates - see if we need to load any new scenery tiles.
// this code ties together the fdm, viewer and scenery classes...
@ -1080,12 +1078,16 @@ static void fgMainLoop( void ) {
// ...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.prep_ssg_nodes(visibility_meters,
acmodel_location->get_world_up(),
acmodel_location->get_tile_center());
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()
acmodel_location->get_previous_bucket(),
acmodel_location->get_tile_center()
);
// save results of update in FGLocation for fdm...
if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
@ -1093,9 +1095,13 @@ static void fgMainLoop( void ) {
}
acmodel_location->set_current_bucket( global_tile_mgr.get_current_bucket() );
acmodel_location->set_previous_bucket( global_tile_mgr.get_previous_bucket() );
acmodel_location->set_tile_center( globals->get_scenery()->get_next_center() );
}
}
global_tile_mgr.prep_ssg_nodes(visibility_meters,
current_view->getFGLocation()->get_world_up(),
current_view->getFGLocation()->get_tile_center());
// 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
@ -1105,7 +1111,8 @@ static void fgMainLoop( void ) {
visibility_meters,
current_view->get_absolute_view_pos(),
current_view->getFGLocation()->get_current_bucket(),
current_view->getFGLocation()->get_previous_bucket()
current_view->getFGLocation()->get_previous_bucket(),
current_view->getFGLocation()->get_tile_center()
);
// save results of update in FGLocation for fdm...
if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
@ -1113,6 +1120,7 @@ static void fgMainLoop( void ) {
}
current_view->getFGLocation()->set_current_bucket( global_tile_mgr.get_current_bucket() );
current_view->getFGLocation()->set_previous_bucket( global_tile_mgr.get_previous_bucket() );
current_view->getFGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
// 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...
@ -1123,11 +1131,14 @@ static void fgMainLoop( void ) {
}
acmodel_location->set_current_bucket( global_tile_mgr.get_current_bucket() );
acmodel_location->set_previous_bucket( global_tile_mgr.get_previous_bucket() );
acmodel_location->set_tile_center( globals->get_scenery()->get_next_center() );
}
}
// END Tile Manager udpates
// redraw display
fgRenderFrame();
SG_LOG( SG_ALL, SG_DEBUG, "" );
}

View file

@ -561,8 +561,11 @@ FGViewer::recalcLookAt ()
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 "at" target object positon relative to eye or view's tile center...
sgdVec3 dVec3;
sgdSetVec3(dVec3, _location->get_tile_center()[0], _location->get_tile_center()[1], _location->get_tile_center()[2]);
sgdSubVec3(dVec3, _target_location->get_absolute_view_pos(), dVec3 );
sgSetVec3(at_pos, dVec3[0], dVec3[1], dVec3[2]);
// Update location data for eye...
if ( _from_model ) {

View file

@ -251,10 +251,14 @@ void FGTileMgr::initialize_queue()
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 );
return update( lon, lat, visibility_meters, abs_pos_vector,
current_bucket, previous_bucket,
globals->get_scenery()->get_center() );
}
int FGTileMgr::update( double lon, double lat, double visibility_meters, sgdVec3 abs_pos_vector, SGBucket p_current, SGBucket p_previous ) {
int FGTileMgr::update( double lon, double lat, double visibility_meters,
sgdVec3 abs_pos_vector, SGBucket p_current,
SGBucket p_previous, Point3D center ) {
// SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for "
// << lon << " " << lat );
@ -342,14 +346,14 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters, sgdVec3
}
// no reason to update this if we haven't moved...
if ( longitude != last_longitude || latitude == last_latitude ) {
if ( longitude != last_longitude || latitude != last_latitude ) {
// update current elevation...
updateCurrentElevAtPos(abs_pos_vector);
if (updateCurrentElevAtPos(abs_pos_vector, center)) {
last_longitude = longitude;
last_latitude = latitude;
}
}
last_longitude = longitude;
last_latitude = latitude;
#if 0
}
#endif
@ -378,28 +382,25 @@ void FGTileMgr::setCurrentTile(double longitude, double latitude) {
}
}
void FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector) {
int FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector, Point3D center) {
sgdVec3 sc;
sgdSetVec3( sc,
globals->get_scenery()->get_center()[0],
globals->get_scenery()->get_center()[1],
globals->get_scenery()->get_center()[2] );
center[0],
center[1],
center[2]);
// overridden with actual values if a terrain intersection is
// found
double hit_elev = -9999.0;
double hit_radius = 0.0;
sgdVec3 hit_normal = { 0.0, 0.0, 0.0 };
bool hit = false;
if ( fabs(sc[0]) > 1.0 || fabs(sc[1]) > 1.0 || fabs(sc[2]) > 1.0 ) {
// scenery center has been properly defined so any hit
// should be valid (and not just luck)
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(),
@ -418,13 +419,26 @@ void FGTileMgr::updateCurrentElevAtPos(sgdVec3 abs_pos_vector) {
globals->get_scenery()->set_cur_radius( 0.0 );
globals->get_scenery()->set_cur_normal( hit_normal );
}
return hit;
}
void FGTileMgr::prep_ssg_nodes(float vis) {
// float vis = 0.0;
// vis = fgGetDouble("/environment/visibility-m");
// traverse the potentially viewable tile list and update range
// selector and transform
// just setup and call new function...
sgVec3 up;
sgCopyVec3( up, globals->get_current_view()->get_world_up() );
Point3D center;
center = globals->get_scenery()->get_center();
prep_ssg_nodes( vis, up, center );
}
void FGTileMgr::prep_ssg_nodes(float vis, sgVec3 up, Point3D center) {
// traverse the potentially viewable tile list and update range
// selector and transform
@ -432,13 +446,10 @@ void FGTileMgr::prep_ssg_nodes(float vis) {
FGTileEntry *e;
tile_cache.reset_traversal();
sgVec3 up;
sgCopyVec3( up, globals->get_current_view()->get_world_up() );
while ( ! tile_cache.at_end() ) {
// cout << "processing a tile" << endl;
if ( (e = tile_cache.get_current()) ) {
e->prep_ssg_node( globals->get_scenery()->get_center(), up, vis);
e->prep_ssg_node( center, up, vis);
} else {
SG_LOG(SG_INPUT, SG_ALERT, "warning ... empty tile in cache");
}

View file

@ -30,6 +30,7 @@
#endif
#include <simgear/compiler.h>
#include <simgear/math/point3d.hxx>
#include <queue>
@ -163,9 +164,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 );
int update( double lon, double lat, double visibility_meters, sgdVec3 abs_pos_vector, SGBucket p_current, SGBucket p_previous, Point3D center );
void setCurrentTile( double longitude, double latitude );
void updateCurrentElevAtPos(sgdVec3 abs_pos_vector);
int updateCurrentElevAtPos(sgdVec3 abs_pos_vector, Point3D center );
// Determine scenery altitude. Normally this just happens when we
// render the scene, but we'd also like to be able to do this
@ -182,6 +183,7 @@ public:
// transform and update it's range selector based on current
// visibilty
void prep_ssg_nodes(float visibility_meters);
void prep_ssg_nodes(float visibility_meters, sgVec3 up, Point3D center);
//
// Set flag with event manager so that non-moving view refreshes tiles...