From 4c10ef139c109c80ba6a17ee669c6feaacc26a95 Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 29 Apr 2005 14:38:24 +0000 Subject: [PATCH] Mathias: I have done a patch to eliminate the jitter of 3D-objects near the viewpoint (for example 3D cockpit objects). The problem is the roundoff accuracy of the float values used in the scenegraph together with the transforms of the eyepoint relative to the scenery center. The solution will be to move the scenery center near the view point. This way floats relative accuracy is enough to show a stable picture. To get that right I have introduced a transform node for the scenegraph which is responsible for that shift and uses double values as long as possible. The scenery subsystem now has a list of all those transforms required to place objects in the world and will tell all those transforms that the scenery center has changed when the set_scenery_center() of the scenery subsystem is called. The problem was not solvable by SGModelPlacement and SGLocation, since not all objects, especially the scenery, are placed using these classes. The first approach was to have the scenery center exactly at the eyepoint. This works well for the cockpit. But then the ground jitters a bit below the aircraft. With our default views you can't see that, but that F-18 has a camera view below the left engine intake with the nose gear and the ground in its field of view, here I could see that. Having the scenery center constant will still have this roundoff problems, but like it is now too, the roundoff error here is exactly the same in each frame, so you will not notice any jitter. The real solution is now to keep the scenery center constant as long as it is in a ball of 30m radius around the view point. If the scenery center is outside this ball, just put it at the view point. As a sideeffect of now beeing able to switch the scenery center in the whole scenegraph with one function call, I was able to remove a one half of a problem when switching views, where the scenery center was far off for one or two frames past switching from one view to the next. Also included is a fix to the other half of this problem, where the view position was not yet copied into a view when it is switched (at least under glut). This was responsible for the 'Error: ...' messages of the cloud subsystem when views were switched. --- src/AIModel/AIBase.cxx | 5 ++ src/ATC/AIEntity.cxx | 6 ++ src/FDM/groundcache.cxx | 10 +++- src/Main/main.cxx | 25 +++++++++ src/Main/renderer.cxx | 4 +- src/Main/viewer.cxx | 32 ++++++++--- src/Main/viewer.hxx | 2 + src/Main/viewmgr.cxx | 11 ++++ src/Main/viewmgr.hxx | 11 +--- src/Model/acmodel.cxx | 7 +++ src/Model/acmodel.hxx | 1 + src/Model/modelmgr.cxx | 7 +++ src/Scenery/scenery.cxx | 31 +++++++++++ src/Scenery/scenery.hxx | 13 ++++- src/Scenery/tileentry.cxx | 113 ++++++++++++++++++++++---------------- src/Scenery/tileentry.hxx | 23 +++----- src/Scenery/tilemgr.cxx | 10 ---- src/Scenery/tilemgr.hxx | 5 -- 18 files changed, 217 insertions(+), 99 deletions(-) diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index ce3968b90..8a618ab2d 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -69,6 +69,9 @@ FGAIBase::FGAIBase() } FGAIBase::~FGAIBase() { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(aip.getTransform()); + globals->get_scenery()->get_scene_graph()->removeKid(aip.getSceneGraph()); // unbind(); SGPropertyNode *root = globals->get_props()->getNode("ai/models", true); @@ -146,6 +149,8 @@ bool FGAIBase::init() { aip.setVisible(true); invisible = false; globals->get_scenery()->get_scene_graph()->addKid(aip.getSceneGraph()); + // Register that one at the scenery manager + globals->get_scenery()->register_placement_transform(aip.getTransform()); } else { if (model_path != "") { SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load model."); diff --git a/src/ATC/AIEntity.cxx b/src/ATC/AIEntity.cxx index 9dccebea0..79d10a6a2 100644 --- a/src/ATC/AIEntity.cxx +++ b/src/ATC/AIEntity.cxx @@ -48,6 +48,9 @@ FGAIEntity::~FGAIEntity() { _model->deRef(); // Ought to check valid? //cout << "Removing model from scene graph..." << endl; globals->get_scenery()->get_scene_graph()->removeKid(_aip.getSceneGraph()); + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(_aip.getTransform()); + //cout << "Done!" << endl; } @@ -57,6 +60,9 @@ void FGAIEntity::SetModel(ssgBranch* model) { _aip.init(_model); _aip.setVisible(false); globals->get_scenery()->get_scene_graph()->addKid(_aip.getSceneGraph()); + // Register that one at the scenery manager + globals->get_scenery()->register_placement_transform(_aip.getTransform()); + } void FGAIEntity::Update(double dt) { diff --git a/src/FDM/groundcache.cxx b/src/FDM/groundcache.cxx index 3a944a42b..5c4be473f 100644 --- a/src/FDM/groundcache.cxx +++ b/src/FDM/groundcache.cxx @@ -342,6 +342,10 @@ bool FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], double rad) { + Point3D old_cntr = globals->get_scenery()->get_center(); + Point3D cntr(pt[0], pt[1], pt[2]); + globals->get_scenery()->set_center( cntr ); + // Empty cache. cache_root.removeAllKids(); ground_radius = 0.0; @@ -379,7 +383,7 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], // We need the offset to the scenery scenery center. sgdVec3 doffset; - Point3D psc = globals->get_tile_mgr()->get_current_center(); + Point3D psc = globals->get_scenery()->get_center(); sgdSetVec3(doffset, psc[0], psc[1], psc[2]); sgdSubVec3(doffset, doffset, pt); @@ -396,7 +400,7 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], sgMakeTransMat4(xform, offset); - // Walk the terrain branch for now. + // Walk the scene graph and extract solid ground triangles and carrier data. ssgBranch *terrain = globals->get_scenery()->get_scene_graph(); cache_fill(terrain, xform, &acSphere, down, &wireSphere); @@ -412,6 +416,8 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], SG_LOG(SG_FLIGHT, SG_WARN, "prepare_ground_cache(): trying to build cache " "without any scenery below the aircraft" ); + globals->get_scenery()->set_center( old_cntr ); + return found_ground; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index f1bb31746..e3f255f6b 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -500,6 +500,28 @@ static void fgMainLoop( void ) { double visibility_meters = fgGetDouble("/environment/visibility-m"); FGViewer *current_view = globals->get_current_view(); + // Let the scenery center follow the current view position with + // 30m increments. + // + // Having the scenery center near the view position will eliminate + // jitter of objects which are placed very near the view position + // and haveing it's center near that view position. + // So the 3d insruments of the aircraft will not jitter with this. + // + // Following the view position exactly would introduce jitter of + // the scenery tiles (they would be from their center up to 10000m + // to the view and this will introduce roundoff too). By stepping + // at 30m incements the roundoff error of the scenery tiles is + // still present, but we will make exactly the same roundoff error + // at each frame until the center is switched to a new + // position. This roundoff is still visible but you will most + // propably not notice. + double *vp = globals->get_current_view()->get_absolute_view_pos(); + Point3D cntr(vp[0], vp[1], vp[2]); + if (30.0*30.0 < cntr.distance3Dsquared(globals->get_scenery()->get_center())) { + globals->get_scenery()->set_next_center( cntr ); + } + // get the location data for the primary FDM (now hardcoded to ac model)... SGLocation *acmodel_loc = NULL; acmodel_loc = (SGLocation *)globals-> @@ -517,6 +539,8 @@ static void fgMainLoop( void ) { acmodel_loc-> get_absolute_view_pos(globals-> get_scenery()->get_center()) ); + globals->get_scenery()->set_center( cntr ); + // save results of update in SGLocation for fdm... if ( globals->get_scenery()->get_cur_elev() > -9990 ) { acmodel_loc-> @@ -539,6 +563,7 @@ static void fgMainLoop( void ) { SGLocation *view_location = globals->get_current_view()->getSGLocation(); globals->get_tile_mgr()->update( view_location, visibility_meters, current_view->get_absolute_view_pos() ); + globals->get_scenery()->set_center( cntr ); // save results of update in SGLocation for fdm... if ( globals->get_scenery()->get_cur_elev() > -9990 ) { current_view->getSGLocation()-> diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index f1fa952d3..b3102774b 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -306,7 +306,9 @@ FGRenderer::update( bool refresh_camera_settings ) { FGViewer *current__view = globals->get_current_view(); // calculate our current position in cartesian space - globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() ); + Point3D cntr = globals->get_scenery()->get_next_center(); + globals->get_scenery()->set_center(cntr); + current__view->set_scenery_center(cntr); if ( refresh_camera_settings ) { // update view port diff --git a/src/Main/viewer.cxx b/src/Main/viewer.cxx index 74f25e834..6615f78b0 100644 --- a/src/Main/viewer.cxx +++ b/src/Main/viewer.cxx @@ -542,14 +542,15 @@ FGViewer::getZeroElevViewPos () void FGViewer::updateFromModelLocation (SGLocation * location) { - sgCopyMat4(LOCAL, location->getCachedTransformMatrix()); + Point3D center = globals->get_scenery()->get_next_center(); + sgCopyMat4(LOCAL, location->getTransformMatrix(center)); } void FGViewer::updateAtModelLocation (SGLocation * location) { - sgCopyMat4(ATLOCAL, - location->getCachedTransformMatrix()); + Point3D center = globals->get_scenery()->get_next_center(); + sgCopyMat4(ATLOCAL, location->getTransformMatrix(center)); } void @@ -560,8 +561,20 @@ FGViewer::recalcOurOwnLocation (SGLocation * location, double lon_deg, double la dampEyeData(roll_deg, pitch_deg, heading_deg); location->setPosition( lon_deg, lat_deg, alt_ft ); location->setOrientation( roll_deg, pitch_deg, heading_deg ); - sgCopyMat4(LOCAL, - location->getTransformMatrix(globals->get_scenery()->get_center())); + Point3D center = globals->get_scenery()->get_next_center(); + sgCopyMat4(LOCAL, location->getTransformMatrix(center)); +} + +void +FGViewer::set_scenery_center(const Point3D& center) +{ + _location->set_tile_center(center); + _location->getTransformMatrix(center); + if (_type == FG_LOOKAT) { + _target_location->set_tile_center(center); + _target_location->getTransformMatrix(center); + } + set_dirty(); } // recalc() is done every time one of the setters is called (making the @@ -670,10 +683,11 @@ FGViewer::recalcLookAt () _target_roll_deg, _target_pitch_deg, _target_heading_deg ); } // calculate the "at" target object positon relative to eye or view's tile center... + Point3D center = globals->get_scenery()->get_next_center(); sgdVec3 dVec3; - sgdSetVec3(dVec3, _location->get_tile_center()[0], _location->get_tile_center()[1], _location->get_tile_center()[2]); + sgdSetVec3(dVec3, center[0], center[1], center[2]); sgdSubVec3(dVec3, - _target_location->get_absolute_view_pos(globals->get_scenery()->get_center()), + _target_location->get_absolute_view_pos(center), dVec3 ); sgSetVec3(at_pos, dVec3[0], dVec3[1], dVec3[2]); @@ -739,10 +753,10 @@ void FGViewer::copyLocationData() { // Get our friendly vectors from the eye location... + sgdCopyVec3(_absolute_view_pos, + _location->get_absolute_view_pos(globals->get_scenery()->get_next_center())); 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(globals->get_scenery()->get_center())); sgCopyMat4(UP, _location->getCachedUpMatrix()); sgCopyVec3(_world_up, _location->get_world_up()); // these are the vectors that the sun and moon code like to get... diff --git a/src/Main/viewer.hxx b/src/Main/viewer.hxx index 5907997e9..4a319edc3 100644 --- a/src/Main/viewer.hxx +++ b/src/Main/viewer.hxx @@ -258,6 +258,8 @@ public: _ground_level_nearplane_m = near_m; } + void set_scenery_center(const Point3D& center); + ////////////////////////////////////////////////////////////////////// // Part 5: misc setters and getters ////////////////////////////////////////////////////////////////////// diff --git a/src/Main/viewmgr.cxx b/src/Main/viewmgr.cxx index bc1c54521..33fe8f7cb 100644 --- a/src/Main/viewmgr.cxx +++ b/src/Main/viewmgr.cxx @@ -24,6 +24,11 @@ #include // strcmp #include +#include + +#include + +#include #include "viewmgr.hxx" #include "fg_props.hxx" @@ -724,6 +729,12 @@ FGViewMgr::setView (int newview ) set_view( newview ); // copy in view data copyToCurrent (); + + // Copy the fdm's position into the SGLocation which is shared with + // some views ... + globals->get_aircraft_model()->update(0); + // Do the update ... + update(0); } diff --git a/src/Main/viewmgr.hxx b/src/Main/viewmgr.hxx index eff9d67ff..922d3561c 100644 --- a/src/Main/viewmgr.hxx +++ b/src/Main/viewmgr.hxx @@ -90,18 +90,11 @@ public: return views[i]; } inline FGViewer *next_view() { - ++current; - if ( current >= (int)views.size() ) { - current = 0; - } - copyToCurrent(); + setView((current+1 < (int)views.size()) ? (current + 1) : 0); return views[current]; } inline FGViewer *prev_view() { - --current; - if ( current < 0 ) { - current = views.size() - 1; - } + setView((0 < current) ? (current - 1) : (views.size() - 1)); return views[current]; } diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 6bcba3913..662a4a4b8 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -46,6 +46,10 @@ FGAircraftModel::FGAircraftModel () FGAircraftModel::~FGAircraftModel () { + // Unregister that one at the scenery manager + if (_aircraft) + globals->get_scenery()->unregister_placement_transform(_aircraft->getTransform()); + delete _aircraft; delete _scene; // SSG will delete it @@ -75,6 +79,9 @@ FGAircraftModel::init () _scene->addKid(_aircraft->getSceneGraph()); _selector->addKid(_aircraft->getSceneGraph()); globals->get_scenery()->get_aircraft_branch()->addKid(_selector); + + // Register that one at the scenery manager + globals->get_scenery()->register_placement_transform(_aircraft->getTransform()); } void diff --git a/src/Model/acmodel.hxx b/src/Model/acmodel.hxx index a59bd954a..e15705374 100644 --- a/src/Model/acmodel.hxx +++ b/src/Model/acmodel.hxx @@ -11,6 +11,7 @@ #endif #include +#include SG_USING_STD(string); SG_USING_STD(vector); diff --git a/src/Model/modelmgr.cxx b/src/Model/modelmgr.cxx index 4175f65bf..01743325f 100644 --- a/src/Model/modelmgr.cxx +++ b/src/Model/modelmgr.cxx @@ -101,6 +101,10 @@ FGModelMgr::init () // Add this model to the global scene graph globals->get_scenery()->get_scene_graph()->addKid(model->getSceneGraph()); + // Register that one at the scenery manager + globals->get_scenery()->register_placement_transform(model->getTransform()); + + // Save this instance for updating add_instance(instance); } @@ -188,6 +192,9 @@ FGModelMgr::Instance::Instance () FGModelMgr::Instance::~Instance () { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(model->getTransform()); + delete model; } diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 51b598c74..8e0f361c1 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -30,6 +30,7 @@ #include #include +#include #include
@@ -100,3 +101,33 @@ void FGScenery::bind() { void FGScenery::unbind() { fgUntie("/environment/ground-elevation-m"); } + +void FGScenery::set_center( Point3D p ) { + center = p; + sgdVec3 c; + sgdSetVec3(c, p.x(), p.y(), p.z()); + placement_list_type::iterator it = _placement_list.begin(); + while (it != _placement_list.end()) { + (*it)->setSceneryCenter(c); + ++it; + } +} + +void FGScenery::register_placement_transform(ssgPlacementTransform *trans) { + trans->ref(); + _placement_list.push_back(trans); + sgdVec3 c; + sgdSetVec3(c, center.x(), center.y(), center.z()); + trans->setSceneryCenter(c); +} + +void FGScenery::unregister_placement_transform(ssgPlacementTransform *trans) { + placement_list_type::iterator it = _placement_list.begin(); + while (it != _placement_list.end()) { + if ((*it) == trans) { + (*it)->deRef(); + it = _placement_list.erase(it); + } else + ++it; + } +} diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx index 3c753e1d1..d96660cee 100644 --- a/src/Scenery/scenery.hxx +++ b/src/Scenery/scenery.hxx @@ -29,15 +29,19 @@ # error This library requires C++ #endif +#include #include +#include #include #include +SG_USING_STD(list); class ssgRoot; class ssgBranch; +class ssgPlacementTransform; // Define a structure containing global scenery parameters @@ -72,6 +76,10 @@ class FGScenery : public SGSubsystem { ssgBranch *models_branch; ssgBranch *aircraft_branch; + // list of all placement transform, used to move the scenery center on the fly. + typedef list placement_list_type; + placement_list_type _placement_list; + public: FGScenery(); @@ -87,7 +95,7 @@ public: inline void set_cur_elev( double e ) { cur_elev = e; } inline Point3D get_center() const { return center; } - inline void set_center( Point3D p ) { center = p; } + void set_center( Point3D p ); inline Point3D get_next_center() const { return next_center; } inline void set_next_center( Point3D p ) { next_center = p; } @@ -142,6 +150,9 @@ public: inline void set_aircraft_branch (ssgBranch *t) { aircraft_branch = t; } + + void register_placement_transform(ssgPlacementTransform *trans); + void unregister_placement_transform(ssgPlacementTransform *trans); }; diff --git a/src/Scenery/tileentry.cxx b/src/Scenery/tileentry.cxx index e294e9f01..57b92d646 100644 --- a/src/Scenery/tileentry.cxx +++ b/src/Scenery/tileentry.cxx @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -62,10 +63,10 @@ SG_USING_STD(string); FGTileEntry::FGTileEntry ( const SGBucket& b ) : center( Point3D( 0.0 ) ), tile_bucket( b ), - terra_transform( new ssgTransform ), - vasi_lights_transform( new ssgTransform ), - rwy_lights_transform( new ssgTransform ), - taxi_lights_transform( new ssgTransform ), + terra_transform( new ssgPlacementTransform ), + vasi_lights_transform( new ssgPlacementTransform ), + rwy_lights_transform( new ssgPlacementTransform ), + taxi_lights_transform( new ssgPlacementTransform ), terra_range( new ssgRangeSelector ), vasi_lights_selector( new ssgSelector ), rwy_lights_selector( new ssgSelector ), @@ -316,8 +317,6 @@ bool FGTileEntry::free_tile() { void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { if ( !loaded ) return; - SetOffset( p ); - // visibility can change from frame to frame so we update the // range selector cutoff's each time. terra_range->setRange( 0, SG_ZERO ); @@ -328,9 +327,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { gnd_lights_range->setRange( 1, vis * 1.5 + bounding_radius ); } - sgVec3 sgTrans; - sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() ); - terra_transform->setTransform( sgTrans ); + sgdVec3 sgdTrans; + sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() ); FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); if ( gnd_lights_transform ) { @@ -348,12 +346,8 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { 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 - // is what we want to calculate the distance of - sgVec3 to; - sgCopyVec3( to, sgTrans ); - double dist = sgLengthVec3( to ); + // Compute the distance of the scenery center from the view position. + double dist = center.distance3D(p); if ( general.get_glDepthBits() > 16 ) { sgScaleVec3( lift_vec, 10.0 + agl / 100.0 + dist / 10000 ); @@ -361,11 +355,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgScaleVec3( lift_vec, 10.0 + agl / 20.0 + dist / 5000 ); } - sgVec3 lt_trans; - sgCopyVec3( lt_trans, sgTrans ); - - sgAddVec3( lt_trans, lift_vec ); - gnd_lights_transform->setTransform( lt_trans ); + sgdVec3 dlt_trans; + sgdCopyVec3( dlt_trans, sgdTrans ); + sgdVec3 dlift_vec; + sgdSetVec3( dlift_vec, lift_vec ); + sgdAddVec3( dlt_trans, dlift_vec ); + gnd_lights_transform->setTransform( dlt_trans ); // select which set of lights based on sun angle float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; @@ -404,11 +399,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgScaleVec3( lift_vec, 0.25 + agl / 150.0 ); } - sgVec3 lt_trans; - sgCopyVec3( lt_trans, sgTrans ); - - sgAddVec3( lt_trans, lift_vec ); - vasi_lights_transform->setTransform( lt_trans ); + sgdVec3 dlt_trans; + sgdCopyVec3( dlt_trans, sgdTrans ); + sgdVec3 dlift_vec; + sgdSetVec3( dlift_vec, lift_vec ); + sgdAddVec3( dlt_trans, dlift_vec ); + vasi_lights_transform->setTransform( dlt_trans ); // generally, vasi lights are always on vasi_lights_selector->select(0x01); @@ -438,11 +434,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgScaleVec3( lift_vec, 0.25 + agl / 150.0 ); } - sgVec3 lt_trans; - sgCopyVec3( lt_trans, sgTrans ); - - sgAddVec3( lt_trans, lift_vec ); - rwy_lights_transform->setTransform( lt_trans ); + sgdVec3 dlt_trans; + sgdCopyVec3( dlt_trans, sgdTrans ); + sgdVec3 dlift_vec; + sgdSetVec3( dlift_vec, lift_vec ); + sgdAddVec3( dlt_trans, dlift_vec ); + rwy_lights_transform->setTransform( dlt_trans ); // turn runway lights on/off based on sun angle and visibility float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; @@ -478,11 +475,12 @@ void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) { sgScaleVec3( lift_vec, 0.25 + agl / 150.0 ); } - sgVec3 lt_trans; - sgCopyVec3( lt_trans, sgTrans ); - - sgAddVec3( lt_trans, lift_vec ); - taxi_lights_transform->setTransform( lt_trans ); + sgdVec3 dlt_trans; + sgdCopyVec3( dlt_trans, sgdTrans ); + sgdVec3 dlift_vec; + sgdSetVec3( dlift_vec, lift_vec ); + sgdAddVec3( dlt_trans, dlift_vec ); + taxi_lights_transform->setTransform( dlt_trans ); // turn taxi lights on/off based on sun angle and visibility float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; @@ -938,12 +936,16 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) terra_transform->addKid( terra_range ); // calculate initial tile offset - SetOffset( globals->get_scenery()->get_center() ); - sgCoord sgcoord; - sgSetCoord( &sgcoord, - offset.x(), offset.y(), offset.z(), - 0.0, 0.0, 0.0 ); - terra_transform->setTransform( &sgcoord ); + sgdVec3 sgdTrans; + sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() ); + terra_transform->setTransform( sgdTrans ); + + sgdVec3 sgdCenter; + Point3D p = globals->get_scenery()->get_center(); + sgdSetVec3( sgdCenter, p.x(), p.y(), p.z() ); + terra_transform->setSceneryCenter( sgdCenter ); + globals->get_scenery()->register_placement_transform(terra_transform); + // terrain->addKid( terra_transform ); // Add ground lights to scene graph if any exist @@ -951,7 +953,7 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) gnd_lights_range = NULL; if ( light_pts->getNum() ) { SG_LOG( SG_TERRAIN, SG_DEBUG, "generating lights" ); - gnd_lights_transform = new ssgTransform; + gnd_lights_transform = new ssgPlacementTransform; gnd_lights_range = new ssgRangeSelector; gnd_lights_brightness = new ssgSelector; ssgLeaf *lights; @@ -967,22 +969,30 @@ FGTileEntry::load( const string_list &path_list, bool is_base ) gnd_lights_range->addKid( gnd_lights_brightness ); gnd_lights_transform->addKid( gnd_lights_range ); - gnd_lights_transform->setTransform( &sgcoord ); + gnd_lights_transform->setTransform( sgdTrans ); + gnd_lights_transform->setSceneryCenter( sgdCenter ); + globals->get_scenery()->register_placement_transform(gnd_lights_transform); } // Update vasi lights transform if ( vasi_lights_transform->getNumKids() > 0 ) { - vasi_lights_transform->setTransform( &sgcoord ); + vasi_lights_transform->setTransform( sgdTrans ); + vasi_lights_transform->setSceneryCenter( sgdCenter ); + globals->get_scenery()->register_placement_transform(vasi_lights_transform); } // Update runway lights transform if ( rwy_lights_transform->getNumKids() > 0 ) { - rwy_lights_transform->setTransform( &sgcoord ); + rwy_lights_transform->setTransform( sgdTrans ); + rwy_lights_transform->setSceneryCenter( sgdCenter ); + globals->get_scenery()->register_placement_transform(rwy_lights_transform); } // Update taxi lights transform if ( taxi_lights_transform->getNumKids() > 0 ) { - taxi_lights_transform->setTransform( &sgcoord ); + taxi_lights_transform->setTransform( sgdTrans ); + taxi_lights_transform->setSceneryCenter( sgdCenter ); + globals->get_scenery()->register_placement_transform(taxi_lights_transform); } } @@ -1070,6 +1080,9 @@ FGTileEntry::disconnect_ssg_nodes() SG_LOG( SG_TERRAIN, SG_DEBUG, "removing a fully loaded tile! terra_transform = " << terra_transform ); } + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(terra_transform); + // find the terrain branch parent int pcount = terra_transform->getNumParents(); if ( pcount > 0 ) { @@ -1092,6 +1105,8 @@ FGTileEntry::disconnect_ssg_nodes() // find the ground lighting branch if ( gnd_lights_transform ) { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(gnd_lights_transform); pcount = gnd_lights_transform->getNumParents(); if ( pcount > 0 ) { // find the first parent (should only be one) @@ -1114,6 +1129,8 @@ FGTileEntry::disconnect_ssg_nodes() // find the vasi lighting branch if ( vasi_lights_transform ) { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(vasi_lights_transform); pcount = vasi_lights_transform->getNumParents(); if ( pcount > 0 ) { // find the first parent (should only be one) @@ -1136,6 +1153,8 @@ FGTileEntry::disconnect_ssg_nodes() // find the runway lighting branch if ( rwy_lights_transform ) { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(rwy_lights_transform); pcount = rwy_lights_transform->getNumParents(); if ( pcount > 0 ) { // find the first parent (should only be one) @@ -1158,6 +1177,8 @@ FGTileEntry::disconnect_ssg_nodes() // find the taxi lighting branch if ( taxi_lights_transform ) { + // Unregister that one at the scenery manager + globals->get_scenery()->unregister_placement_transform(taxi_lights_transform); pcount = taxi_lights_transform->getNumParents(); if ( pcount > 0 ) { // find the first parent (should only be one) diff --git a/src/Scenery/tileentry.hxx b/src/Scenery/tileentry.hxx index bcc669c47..90471243b 100644 --- a/src/Scenery/tileentry.hxx +++ b/src/Scenery/tileentry.hxx @@ -58,6 +58,7 @@ typedef point_list::const_iterator const_point_list_iterator; class ssgLeaf; class ssgBranch; class ssgTransform; +class ssgPlacementTransform; class ssgSelector; class ssgRangeSelector; class ssgVertexArray; @@ -109,7 +110,6 @@ public: // global tile culling data Point3D center; double bounding_radius; - Point3D offset; // this tile's official location in the world SGBucket tile_bucket; @@ -128,11 +128,11 @@ private: // - kidn(fan) // pointer to ssg transform for this tile - ssgTransform *terra_transform; - ssgTransform *vasi_lights_transform; - ssgTransform *rwy_lights_transform; - ssgTransform *taxi_lights_transform; - ssgTransform *gnd_lights_transform; + ssgPlacementTransform *terra_transform; + ssgPlacementTransform *vasi_lights_transform; + ssgPlacementTransform *rwy_lights_transform; + ssgPlacementTransform *taxi_lights_transform; + ssgPlacementTransform *gnd_lights_transform; // pointer to ssg range selector for this tile ssgRangeSelector *terra_range; @@ -218,15 +218,6 @@ public: // completely freed. bool free_tile(); - // Calculate this tile's offset - void SetOffset( const Point3D& p) - { - offset = center - p; - } - - // Return this tile's offset - inline Point3D get_offset() const { return offset; } - // Update the ssg transform node for this tile so it can be // properly drawn relative to our (0,0,0) point void prep_ssg_node( const Point3D& p, sgVec3 up, float vis); @@ -283,7 +274,7 @@ public: /** * return the SSG Transform node for the terrain */ - inline ssgTransform *get_terra_transform() { return terra_transform; } + inline ssgPlacementTransform *get_terra_transform() { return terra_transform; } inline double get_timestamp() const { return timestamp; } inline void set_timestamp( double time_ms ) { timestamp = time_ms; } diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index b53b7d8cf..c0676ad70 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -410,15 +410,6 @@ int FGTileMgr::update( SGLocation *location, double visibility_meters, // << current_bucket ); fgSetInt( "/environment/current-tile-id", current_bucket.gen_index() ); - // set global scenery center from current tile center - current_tile = tile_cache.get_tile( current_bucket ); - if ( current_tile != NULL ) { - 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) ); - } - // do tile load scheduling. // Note that we need keep track of both viewer buckets and fdm buckets. if ( state == Running ) { @@ -517,7 +508,6 @@ void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) { Point3D center = location->get_tile_center(); if (center == Point3D(0.0)) return; - current_center = center; float *up = location->get_world_up(); FGTileEntry *e; diff --git a/src/Scenery/tilemgr.hxx b/src/Scenery/tilemgr.hxx index 4b2405f1f..6e4b30f34 100644 --- a/src/Scenery/tilemgr.hxx +++ b/src/Scenery/tilemgr.hxx @@ -103,10 +103,6 @@ private: * tile cache */ FGNewCache tile_cache; - /** - * and its center - */ - Point3D current_center; /** * Queue tiles for loading. @@ -192,7 +188,6 @@ public: // based on current visibilty void prep_ssg_nodes( float // visibility_meters ); void prep_ssg_nodes( SGLocation *location, float visibility_meters ); - const Point3D get_current_center(void) const { return current_center; } // Set flag with event manager so that non-moving view refreshes // tiles...