1
0
Fork 0
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.
This commit is contained in:
ehofman 2005-04-29 14:38:24 +00:00
parent 3a6bc316ed
commit 4c10ef139c
18 changed files with 217 additions and 99 deletions

View file

@ -69,6 +69,9 @@ FGAIBase::FGAIBase()
} }
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()); globals->get_scenery()->get_scene_graph()->removeKid(aip.getSceneGraph());
// unbind(); // unbind();
SGPropertyNode *root = globals->get_props()->getNode("ai/models", true); SGPropertyNode *root = globals->get_props()->getNode("ai/models", true);
@ -146,6 +149,8 @@ bool FGAIBase::init() {
aip.setVisible(true); aip.setVisible(true);
invisible = false; invisible = false;
globals->get_scenery()->get_scene_graph()->addKid(aip.getSceneGraph()); 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 { } else {
if (model_path != "") { if (model_path != "") {
SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load model."); SG_LOG(SG_INPUT, SG_WARN, "AIBase: Could not load model.");

View file

@ -48,6 +48,9 @@ FGAIEntity::~FGAIEntity() {
_model->deRef(); // Ought to check valid? _model->deRef(); // Ought to check valid?
//cout << "Removing model from scene graph..." << endl; //cout << "Removing model from scene graph..." << endl;
globals->get_scenery()->get_scene_graph()->removeKid(_aip.getSceneGraph()); 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; //cout << "Done!" << endl;
} }
@ -57,6 +60,9 @@ void FGAIEntity::SetModel(ssgBranch* model) {
_aip.init(_model); _aip.init(_model);
_aip.setVisible(false); _aip.setVisible(false);
globals->get_scenery()->get_scene_graph()->addKid(_aip.getSceneGraph()); 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) { void FGAIEntity::Update(double dt) {

View file

@ -342,6 +342,10 @@ bool
FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3],
double rad) 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. // Empty cache.
cache_root.removeAllKids(); cache_root.removeAllKids();
ground_radius = 0.0; 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. // We need the offset to the scenery scenery center.
sgdVec3 doffset; 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]); sgdSetVec3(doffset, psc[0], psc[1], psc[2]);
sgdSubVec3(doffset, doffset, pt); sgdSubVec3(doffset, doffset, pt);
@ -396,7 +400,7 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3],
sgMakeTransMat4(xform, offset); 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(); ssgBranch *terrain = globals->get_scenery()->get_scene_graph();
cache_fill(terrain, xform, &acSphere, down, &wireSphere); 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 " SG_LOG(SG_FLIGHT, SG_WARN, "prepare_ground_cache(): trying to build cache "
"without any scenery below the aircraft" ); "without any scenery below the aircraft" );
globals->get_scenery()->set_center( old_cntr );
return found_ground; return found_ground;
} }

View file

@ -500,6 +500,28 @@ static void fgMainLoop( void ) {
double visibility_meters = fgGetDouble("/environment/visibility-m"); double visibility_meters = fgGetDouble("/environment/visibility-m");
FGViewer *current_view = globals->get_current_view(); 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)... // get the location data for the primary FDM (now hardcoded to ac model)...
SGLocation *acmodel_loc = NULL; SGLocation *acmodel_loc = NULL;
acmodel_loc = (SGLocation *)globals-> acmodel_loc = (SGLocation *)globals->
@ -517,6 +539,8 @@ static void fgMainLoop( void ) {
acmodel_loc-> acmodel_loc->
get_absolute_view_pos(globals-> get_absolute_view_pos(globals->
get_scenery()->get_center()) ); get_scenery()->get_center()) );
globals->get_scenery()->set_center( cntr );
// save results of update in SGLocation for fdm... // save results of update in SGLocation for fdm...
if ( globals->get_scenery()->get_cur_elev() > -9990 ) { if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
acmodel_loc-> acmodel_loc->
@ -539,6 +563,7 @@ static void fgMainLoop( void ) {
SGLocation *view_location = globals->get_current_view()->getSGLocation(); SGLocation *view_location = globals->get_current_view()->getSGLocation();
globals->get_tile_mgr()->update( view_location, visibility_meters, globals->get_tile_mgr()->update( view_location, visibility_meters,
current_view->get_absolute_view_pos() ); current_view->get_absolute_view_pos() );
globals->get_scenery()->set_center( cntr );
// save results of update in SGLocation for fdm... // save results of update in SGLocation for fdm...
if ( globals->get_scenery()->get_cur_elev() > -9990 ) { if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
current_view->getSGLocation()-> current_view->getSGLocation()->

View file

@ -306,7 +306,9 @@ FGRenderer::update( bool refresh_camera_settings ) {
FGViewer *current__view = globals->get_current_view(); FGViewer *current__view = globals->get_current_view();
// calculate our current position in cartesian space // 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 ) { if ( refresh_camera_settings ) {
// update view port // update view port

View file

@ -542,14 +542,15 @@ FGViewer::getZeroElevViewPos ()
void void
FGViewer::updateFromModelLocation (SGLocation * location) FGViewer::updateFromModelLocation (SGLocation * location)
{ {
sgCopyMat4(LOCAL, location->getCachedTransformMatrix()); Point3D center = globals->get_scenery()->get_next_center();
sgCopyMat4(LOCAL, location->getTransformMatrix(center));
} }
void void
FGViewer::updateAtModelLocation (SGLocation * location) FGViewer::updateAtModelLocation (SGLocation * location)
{ {
sgCopyMat4(ATLOCAL, Point3D center = globals->get_scenery()->get_next_center();
location->getCachedTransformMatrix()); sgCopyMat4(ATLOCAL, location->getTransformMatrix(center));
} }
void void
@ -560,8 +561,20 @@ FGViewer::recalcOurOwnLocation (SGLocation * location, double lon_deg, double la
dampEyeData(roll_deg, pitch_deg, heading_deg); dampEyeData(roll_deg, pitch_deg, heading_deg);
location->setPosition( lon_deg, lat_deg, alt_ft ); location->setPosition( lon_deg, lat_deg, alt_ft );
location->setOrientation( roll_deg, pitch_deg, heading_deg ); location->setOrientation( roll_deg, pitch_deg, heading_deg );
sgCopyMat4(LOCAL, Point3D center = globals->get_scenery()->get_next_center();
location->getTransformMatrix(globals->get_scenery()->get_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 // 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 ); _target_roll_deg, _target_pitch_deg, _target_heading_deg );
} }
// calculate the "at" target object positon relative to eye or view's tile center... // calculate the "at" target object positon relative to eye or view's tile center...
Point3D center = globals->get_scenery()->get_next_center();
sgdVec3 dVec3; 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, sgdSubVec3(dVec3,
_target_location->get_absolute_view_pos(globals->get_scenery()->get_center()), _target_location->get_absolute_view_pos(center),
dVec3 ); dVec3 );
sgSetVec3(at_pos, dVec3[0], dVec3[1], dVec3[2]); sgSetVec3(at_pos, dVec3[0], dVec3[1], dVec3[2]);
@ -739,10 +753,10 @@ void
FGViewer::copyLocationData() FGViewer::copyLocationData()
{ {
// Get our friendly vectors from the eye location... // 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(_zero_elev_view_pos, _location->get_zero_elev());
sgCopyVec3(_relative_view_pos, _location->get_view_pos()); 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()); sgCopyMat4(UP, _location->getCachedUpMatrix());
sgCopyVec3(_world_up, _location->get_world_up()); sgCopyVec3(_world_up, _location->get_world_up());
// these are the vectors that the sun and moon code like to get... // these are the vectors that the sun and moon code like to get...

View file

@ -258,6 +258,8 @@ public:
_ground_level_nearplane_m = near_m; _ground_level_nearplane_m = near_m;
} }
void set_scenery_center(const Point3D& center);
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Part 5: misc setters and getters // Part 5: misc setters and getters
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View file

@ -24,6 +24,11 @@
#include <string.h> // strcmp #include <string.h> // strcmp
#include <plib/sg.h> #include <plib/sg.h>
#include <plib/ssg.h>
#include <simgear/compiler.h>
#include <Model/acmodel.hxx>
#include "viewmgr.hxx" #include "viewmgr.hxx"
#include "fg_props.hxx" #include "fg_props.hxx"
@ -724,6 +729,12 @@ FGViewMgr::setView (int newview )
set_view( newview ); set_view( newview );
// copy in view data // copy in view data
copyToCurrent (); 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);
} }

View file

@ -90,18 +90,11 @@ public:
return views[i]; return views[i];
} }
inline FGViewer *next_view() { inline FGViewer *next_view() {
++current; setView((current+1 < (int)views.size()) ? (current + 1) : 0);
if ( current >= (int)views.size() ) {
current = 0;
}
copyToCurrent();
return views[current]; return views[current];
} }
inline FGViewer *prev_view() { inline FGViewer *prev_view() {
--current; setView((0 < current) ? (current - 1) : (views.size() - 1));
if ( current < 0 ) {
current = views.size() - 1;
}
return views[current]; return views[current];
} }

View file

@ -46,6 +46,10 @@ FGAircraftModel::FGAircraftModel ()
FGAircraftModel::~FGAircraftModel () FGAircraftModel::~FGAircraftModel ()
{ {
// Unregister that one at the scenery manager
if (_aircraft)
globals->get_scenery()->unregister_placement_transform(_aircraft->getTransform());
delete _aircraft; delete _aircraft;
delete _scene; delete _scene;
// SSG will delete it // SSG will delete it
@ -75,6 +79,9 @@ FGAircraftModel::init ()
_scene->addKid(_aircraft->getSceneGraph()); _scene->addKid(_aircraft->getSceneGraph());
_selector->addKid(_aircraft->getSceneGraph()); _selector->addKid(_aircraft->getSceneGraph());
globals->get_scenery()->get_aircraft_branch()->addKid(_selector); globals->get_scenery()->get_aircraft_branch()->addKid(_selector);
// Register that one at the scenery manager
globals->get_scenery()->register_placement_transform(_aircraft->getTransform());
} }
void void

View file

@ -11,6 +11,7 @@
#endif #endif
#include <vector> #include <vector>
#include <string>
SG_USING_STD(string); SG_USING_STD(string);
SG_USING_STD(vector); SG_USING_STD(vector);

View file

@ -101,6 +101,10 @@ FGModelMgr::init ()
// Add this model to the global scene graph // Add this model to the global scene graph
globals->get_scenery()->get_scene_graph()->addKid(model->getSceneGraph()); 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 // Save this instance for updating
add_instance(instance); add_instance(instance);
} }
@ -188,6 +192,9 @@ FGModelMgr::Instance::Instance ()
FGModelMgr::Instance::~Instance () FGModelMgr::Instance::~Instance ()
{ {
// Unregister that one at the scenery manager
globals->get_scenery()->unregister_placement_transform(model->getTransform());
delete model; delete model;
} }

View file

@ -30,6 +30,7 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/scene/tgdb/userdata.hxx> #include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/scene/model/placementtrans.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
@ -100,3 +101,33 @@ void FGScenery::bind() {
void FGScenery::unbind() { void FGScenery::unbind() {
fgUntie("/environment/ground-elevation-m"); 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;
}
}

View file

@ -29,15 +29,19 @@
# error This library requires C++ # error This library requires C++
#endif #endif
#include <list>
#include <plib/sg.h> #include <plib/sg.h>
#include <simgear/compiler.h>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/point3d.hxx> #include <simgear/math/point3d.hxx>
SG_USING_STD(list);
class ssgRoot; class ssgRoot;
class ssgBranch; class ssgBranch;
class ssgPlacementTransform;
// Define a structure containing global scenery parameters // Define a structure containing global scenery parameters
@ -72,6 +76,10 @@ class FGScenery : public SGSubsystem {
ssgBranch *models_branch; ssgBranch *models_branch;
ssgBranch *aircraft_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: public:
FGScenery(); FGScenery();
@ -87,7 +95,7 @@ public:
inline void set_cur_elev( double e ) { cur_elev = e; } inline void set_cur_elev( double e ) { cur_elev = e; }
inline Point3D get_center() const { return center; } 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 Point3D get_next_center() const { return next_center; }
inline void set_next_center( Point3D p ) { next_center = p; } inline void set_next_center( Point3D p ) { next_center = p; }
@ -142,6 +150,9 @@ public:
inline void set_aircraft_branch (ssgBranch *t) { inline void set_aircraft_branch (ssgBranch *t) {
aircraft_branch = t; aircraft_branch = t;
} }
void register_placement_transform(ssgPlacementTransform *trans);
void unregister_placement_transform(ssgPlacementTransform *trans);
}; };

View file

@ -43,6 +43,7 @@
#include <simgear/scene/tgdb/apt_signs.hxx> #include <simgear/scene/tgdb/apt_signs.hxx>
#include <simgear/scene/tgdb/obj.hxx> #include <simgear/scene/tgdb/obj.hxx>
#include <simgear/scene/tgdb/vasi.hxx> #include <simgear/scene/tgdb/vasi.hxx>
#include <simgear/scene/model/placementtrans.hxx>
#include <Aircraft/aircraft.hxx> #include <Aircraft/aircraft.hxx>
#include <Include/general.hxx> #include <Include/general.hxx>
@ -62,10 +63,10 @@ SG_USING_STD(string);
FGTileEntry::FGTileEntry ( const SGBucket& b ) FGTileEntry::FGTileEntry ( const SGBucket& b )
: center( Point3D( 0.0 ) ), : center( Point3D( 0.0 ) ),
tile_bucket( b ), tile_bucket( b ),
terra_transform( new ssgTransform ), terra_transform( new ssgPlacementTransform ),
vasi_lights_transform( new ssgTransform ), vasi_lights_transform( new ssgPlacementTransform ),
rwy_lights_transform( new ssgTransform ), rwy_lights_transform( new ssgPlacementTransform ),
taxi_lights_transform( new ssgTransform ), taxi_lights_transform( new ssgPlacementTransform ),
terra_range( new ssgRangeSelector ), terra_range( new ssgRangeSelector ),
vasi_lights_selector( new ssgSelector ), vasi_lights_selector( new ssgSelector ),
rwy_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) { void FGTileEntry::prep_ssg_node( const Point3D& p, sgVec3 up, float vis) {
if ( !loaded ) return; if ( !loaded ) return;
SetOffset( p );
// visibility can change from frame to frame so we update the // visibility can change from frame to frame so we update the
// range selector cutoff's each time. // range selector cutoff's each time.
terra_range->setRange( 0, SG_ZERO ); 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 ); gnd_lights_range->setRange( 1, vis * 1.5 + bounding_radius );
} }
sgVec3 sgTrans; sgdVec3 sgdTrans;
sgSetVec3( sgTrans, offset.x(), offset.y(), offset.z() ); sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() );
terra_transform->setTransform( sgTrans );
FGLight *l = (FGLight *)(globals->get_subsystem("lighting")); FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
if ( gnd_lights_transform ) { 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() agl = globals->get_current_view()->getAltitudeASL_ft()
* SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev(); * SG_FEET_TO_METER - globals->get_scenery()->get_cur_elev();
// sgTrans just happens to be the // Compute the distance of the scenery center from the view position.
// vector from scenery center to the center of this tile which double dist = center.distance3D(p);
// is what we want to calculate the distance of
sgVec3 to;
sgCopyVec3( to, sgTrans );
double dist = sgLengthVec3( to );
if ( general.get_glDepthBits() > 16 ) { if ( general.get_glDepthBits() > 16 ) {
sgScaleVec3( lift_vec, 10.0 + agl / 100.0 + dist / 10000 ); 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 ); sgScaleVec3( lift_vec, 10.0 + agl / 20.0 + dist / 5000 );
} }
sgVec3 lt_trans; sgdVec3 dlt_trans;
sgCopyVec3( lt_trans, sgTrans ); sgdCopyVec3( dlt_trans, sgdTrans );
sgdVec3 dlift_vec;
sgAddVec3( lt_trans, lift_vec ); sgdSetVec3( dlift_vec, lift_vec );
gnd_lights_transform->setTransform( lt_trans ); sgdAddVec3( dlt_trans, dlift_vec );
gnd_lights_transform->setTransform( dlt_trans );
// select which set of lights based on sun angle // select which set of lights based on sun angle
float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; 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 ); sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
} }
sgVec3 lt_trans; sgdVec3 dlt_trans;
sgCopyVec3( lt_trans, sgTrans ); sgdCopyVec3( dlt_trans, sgdTrans );
sgdVec3 dlift_vec;
sgAddVec3( lt_trans, lift_vec ); sgdSetVec3( dlift_vec, lift_vec );
vasi_lights_transform->setTransform( lt_trans ); sgdAddVec3( dlt_trans, dlift_vec );
vasi_lights_transform->setTransform( dlt_trans );
// generally, vasi lights are always on // generally, vasi lights are always on
vasi_lights_selector->select(0x01); 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 ); sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
} }
sgVec3 lt_trans; sgdVec3 dlt_trans;
sgCopyVec3( lt_trans, sgTrans ); sgdCopyVec3( dlt_trans, sgdTrans );
sgdVec3 dlift_vec;
sgAddVec3( lt_trans, lift_vec ); sgdSetVec3( dlift_vec, lift_vec );
rwy_lights_transform->setTransform( lt_trans ); sgdAddVec3( dlt_trans, dlift_vec );
rwy_lights_transform->setTransform( dlt_trans );
// turn runway lights on/off based on sun angle and visibility // turn runway lights on/off based on sun angle and visibility
float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; 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 ); sgScaleVec3( lift_vec, 0.25 + agl / 150.0 );
} }
sgVec3 lt_trans; sgdVec3 dlt_trans;
sgCopyVec3( lt_trans, sgTrans ); sgdCopyVec3( dlt_trans, sgdTrans );
sgdVec3 dlift_vec;
sgAddVec3( lt_trans, lift_vec ); sgdSetVec3( dlift_vec, lift_vec );
taxi_lights_transform->setTransform( lt_trans ); sgdAddVec3( dlt_trans, dlift_vec );
taxi_lights_transform->setTransform( dlt_trans );
// turn taxi lights on/off based on sun angle and visibility // turn taxi lights on/off based on sun angle and visibility
float sun_angle = l->get_sun_angle() * SGD_RADIANS_TO_DEGREES; 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 ); terra_transform->addKid( terra_range );
// calculate initial tile offset // calculate initial tile offset
SetOffset( globals->get_scenery()->get_center() ); sgdVec3 sgdTrans;
sgCoord sgcoord; sgdSetVec3( sgdTrans, center.x(), center.y(), center.z() );
sgSetCoord( &sgcoord, terra_transform->setTransform( sgdTrans );
offset.x(), offset.y(), offset.z(),
0.0, 0.0, 0.0 ); sgdVec3 sgdCenter;
terra_transform->setTransform( &sgcoord ); 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 ); // terrain->addKid( terra_transform );
// Add ground lights to scene graph if any exist // 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; gnd_lights_range = NULL;
if ( light_pts->getNum() ) { if ( light_pts->getNum() ) {
SG_LOG( SG_TERRAIN, SG_DEBUG, "generating lights" ); 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_range = new ssgRangeSelector;
gnd_lights_brightness = new ssgSelector; gnd_lights_brightness = new ssgSelector;
ssgLeaf *lights; 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_range->addKid( gnd_lights_brightness );
gnd_lights_transform->addKid( gnd_lights_range ); 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 // Update vasi lights transform
if ( vasi_lights_transform->getNumKids() > 0 ) { 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 // Update runway lights transform
if ( rwy_lights_transform->getNumKids() > 0 ) { 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 // Update taxi lights transform
if ( taxi_lights_transform->getNumKids() > 0 ) { 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 ); 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 // find the terrain branch parent
int pcount = terra_transform->getNumParents(); int pcount = terra_transform->getNumParents();
if ( pcount > 0 ) { if ( pcount > 0 ) {
@ -1092,6 +1105,8 @@ FGTileEntry::disconnect_ssg_nodes()
// find the ground lighting branch // find the ground lighting branch
if ( gnd_lights_transform ) { 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(); pcount = gnd_lights_transform->getNumParents();
if ( pcount > 0 ) { if ( pcount > 0 ) {
// find the first parent (should only be one) // find the first parent (should only be one)
@ -1114,6 +1129,8 @@ FGTileEntry::disconnect_ssg_nodes()
// find the vasi lighting branch // find the vasi lighting branch
if ( vasi_lights_transform ) { 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(); pcount = vasi_lights_transform->getNumParents();
if ( pcount > 0 ) { if ( pcount > 0 ) {
// find the first parent (should only be one) // find the first parent (should only be one)
@ -1136,6 +1153,8 @@ FGTileEntry::disconnect_ssg_nodes()
// find the runway lighting branch // find the runway lighting branch
if ( rwy_lights_transform ) { 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(); pcount = rwy_lights_transform->getNumParents();
if ( pcount > 0 ) { if ( pcount > 0 ) {
// find the first parent (should only be one) // find the first parent (should only be one)
@ -1158,6 +1177,8 @@ FGTileEntry::disconnect_ssg_nodes()
// find the taxi lighting branch // find the taxi lighting branch
if ( taxi_lights_transform ) { 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(); pcount = taxi_lights_transform->getNumParents();
if ( pcount > 0 ) { if ( pcount > 0 ) {
// find the first parent (should only be one) // find the first parent (should only be one)

View file

@ -58,6 +58,7 @@ typedef point_list::const_iterator const_point_list_iterator;
class ssgLeaf; class ssgLeaf;
class ssgBranch; class ssgBranch;
class ssgTransform; class ssgTransform;
class ssgPlacementTransform;
class ssgSelector; class ssgSelector;
class ssgRangeSelector; class ssgRangeSelector;
class ssgVertexArray; class ssgVertexArray;
@ -109,7 +110,6 @@ public:
// global tile culling data // global tile culling data
Point3D center; Point3D center;
double bounding_radius; double bounding_radius;
Point3D offset;
// this tile's official location in the world // this tile's official location in the world
SGBucket tile_bucket; SGBucket tile_bucket;
@ -128,11 +128,11 @@ private:
// - kidn(fan) // - kidn(fan)
// pointer to ssg transform for this tile // pointer to ssg transform for this tile
ssgTransform *terra_transform; ssgPlacementTransform *terra_transform;
ssgTransform *vasi_lights_transform; ssgPlacementTransform *vasi_lights_transform;
ssgTransform *rwy_lights_transform; ssgPlacementTransform *rwy_lights_transform;
ssgTransform *taxi_lights_transform; ssgPlacementTransform *taxi_lights_transform;
ssgTransform *gnd_lights_transform; ssgPlacementTransform *gnd_lights_transform;
// pointer to ssg range selector for this tile // pointer to ssg range selector for this tile
ssgRangeSelector *terra_range; ssgRangeSelector *terra_range;
@ -218,15 +218,6 @@ public:
// completely freed. // completely freed.
bool free_tile(); 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 // Update the ssg transform node for this tile so it can be
// properly drawn relative to our (0,0,0) point // properly drawn relative to our (0,0,0) point
void prep_ssg_node( const Point3D& p, sgVec3 up, float vis); void prep_ssg_node( const Point3D& p, sgVec3 up, float vis);
@ -283,7 +274,7 @@ public:
/** /**
* return the SSG Transform node for the terrain * 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 double get_timestamp() const { return timestamp; }
inline void set_timestamp( double time_ms ) { timestamp = time_ms; } inline void set_timestamp( double time_ms ) { timestamp = time_ms; }

View file

@ -410,15 +410,6 @@ int FGTileMgr::update( SGLocation *location, double visibility_meters,
// << current_bucket ); // << current_bucket );
fgSetInt( "/environment/current-tile-id", current_bucket.gen_index() ); 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. // do tile load scheduling.
// Note that we need keep track of both viewer buckets and fdm buckets. // Note that we need keep track of both viewer buckets and fdm buckets.
if ( state == Running ) { if ( state == Running ) {
@ -517,7 +508,6 @@ void FGTileMgr::prep_ssg_nodes( SGLocation *location, float vis ) {
Point3D center = location->get_tile_center(); Point3D center = location->get_tile_center();
if (center == Point3D(0.0)) if (center == Point3D(0.0))
return; return;
current_center = center;
float *up = location->get_world_up(); float *up = location->get_world_up();
FGTileEntry *e; FGTileEntry *e;

View file

@ -103,10 +103,6 @@ private:
* tile cache * tile cache
*/ */
FGNewCache tile_cache; FGNewCache tile_cache;
/**
* and its center
*/
Point3D current_center;
/** /**
* Queue tiles for loading. * Queue tiles for loading.
@ -192,7 +188,6 @@ public:
// based on current visibilty void prep_ssg_nodes( float // based on current visibilty void prep_ssg_nodes( float
// visibility_meters ); // visibility_meters );
void prep_ssg_nodes( SGLocation *location, 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 // Set flag with event manager so that non-moving view refreshes
// tiles... // tiles...