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:
parent
0efc08b6b6
commit
8ae364a220
7 changed files with 79 additions and 41 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, "" );
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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...
|
||||
|
|
Loading…
Reference in a new issue