]> git.mxchange.org Git - flightgear.git/commitdiff
Mathias:
authorehofman <ehofman>
Fri, 29 Apr 2005 14:38:24 +0000 (14:38 +0000)
committerehofman <ehofman>
Fri, 29 Apr 2005 14:38:24 +0000 (14:38 +0000)
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.

18 files changed:
src/AIModel/AIBase.cxx
src/ATC/AIEntity.cxx
src/FDM/groundcache.cxx
src/Main/main.cxx
src/Main/renderer.cxx
src/Main/viewer.cxx
src/Main/viewer.hxx
src/Main/viewmgr.cxx
src/Main/viewmgr.hxx
src/Model/acmodel.cxx
src/Model/acmodel.hxx
src/Model/modelmgr.cxx
src/Scenery/scenery.cxx
src/Scenery/scenery.hxx
src/Scenery/tileentry.cxx
src/Scenery/tileentry.hxx
src/Scenery/tilemgr.cxx
src/Scenery/tilemgr.hxx

index ce3968b90c17483904eb5c2aff04cd534debb2c8..8a618ab2def98ddfe6057b6f10a3c516ac87db0d 100644 (file)
@@ -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.");
index 9dccebea01911ec734d2d84c3c6fa884eb23634f..79d10a6a2a823f0d6b5f4cfd9829a991bb690eac 100644 (file)
@@ -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) {
index 3a944a42b5fda8007664d217ca30333621e22baf..5c4be473ffe0e56cfb5bc2c1e396fb1d60de5a95 100644 (file)
@@ -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;
 }
 
index f1bb3174668eb31bbf6992dc7a71d2a5b2d487b1..e3f255f6b2cd6895bd3917fd334cf7f47d92d6f9 100644 (file)
@@ -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()->
index f1fa952d3c4f1e6bd8d4bead2eb237314cb99d80..b3102774bb8d727aa7d8a5f231a1d8ff04647d23 100644 (file)
@@ -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
index 74f25e83464d30ed8794a06b559dbcf059bb50b8..6615f78b0ba726ce3aac7ebee83f5b61db3c1bb6 100644 (file)
@@ -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...
index 5907997e900b7382ace2b9827b7b498a34ab6e58..4a319edc361190b969791a909feef64fe2c9058f 100644 (file)
@@ -258,6 +258,8 @@ public:
         _ground_level_nearplane_m = near_m;
     }
 
+    void set_scenery_center(const Point3D& center);
+
     //////////////////////////////////////////////////////////////////////
     // Part 5: misc setters and getters
     //////////////////////////////////////////////////////////////////////
index bc1c5452103578412d7c625ae0aed23b32591032..33fe8f7cb529dfff32d2cca298ff2d587e5a96d3 100644 (file)
 #include <string.h>            // strcmp
 
 #include <plib/sg.h>
+#include <plib/ssg.h>
+
+#include <simgear/compiler.h>
+
+#include <Model/acmodel.hxx>
 
 #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);
 }
 
 
index eff9d67ff3c78b4f1f0c779e2399f1fe84f958e7..922d3561cc6ee5a0f3688c1831f38e3927f344fd 100644 (file)
@@ -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];
     }
 
index 6bcba3913e8e773155fb39792b5f00d949fbcb18..662a4a4b81913622c8a4659206978602f7b12f68 100644 (file)
@@ -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 
index a59bd954a111a0b131a26fa710b4bd64102919ed..e15705374f0293bdf003f74d0749cb81b427d280 100644 (file)
@@ -11,6 +11,7 @@
 #endif
 
 #include <vector>
+#include <string>
 
 SG_USING_STD(string);
 SG_USING_STD(vector);
index 4175f65bf9de7bd0275bbe635ea6882c51fe9421..01743325fbb98f5939c18d25603d76aed5c6de3d 100644 (file)
@@ -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;
 }
 
index 51b598c7493db18a161664bd8e8195f7500fc8e2..8e0f361c1b1f64dca4325a619561cd42355e189e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
+#include <simgear/scene/model/placementtrans.hxx>
 
 #include <Main/fg_props.hxx>
 
@@ -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;
+    }
+}
index 3c753e1d1bb59117a72845d74857de1c881109ff..d96660ceec006e711508093d961c0c4c89553286 100644 (file)
 # error This library requires C++
 #endif                                   
 
+#include <list>
 
 #include <plib/sg.h>
 
+#include <simgear/compiler.h>
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/math/point3d.hxx>
 
+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<ssgPlacementTransform*> 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);
 };
 
 
index e294e9f015730aa1255e7a65389d6a872804009c..57b92d646b06e81acca3d777e6b69309df0d6aed 100644 (file)
@@ -43,6 +43,7 @@
 #include <simgear/scene/tgdb/apt_signs.hxx>
 #include <simgear/scene/tgdb/obj.hxx>
 #include <simgear/scene/tgdb/vasi.hxx>
+#include <simgear/scene/model/placementtrans.hxx>
 
 #include <Aircraft/aircraft.hxx>
 #include <Include/general.hxx>
@@ -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)
index bcc669c47378e878d5cdef2dea11f46dac32e5be..90471243beff45d5c245f27974e493538ed66216 100644 (file)
@@ -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; }
index b53b7d8cf3bf4383e82a7a6c2ba1da724696a82a..c0676ad7078ac0ef3dcbf934e06a298549e2c106 100644 (file)
@@ -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;
index 4b2405f1f96f9712b513939c3b39422d558f74e6..6e4b30f34e73a74abaeadcb0da13559db2585b59 100644 (file)
@@ -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...