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.
This commit is contained in:
parent
3a6bc316ed
commit
4c10ef139c
18 changed files with 217 additions and 99 deletions
|
@ -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.");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()->
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -258,6 +258,8 @@ public:
|
|||
_ground_level_nearplane_m = near_m;
|
||||
}
|
||||
|
||||
void set_scenery_center(const Point3D& center);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Part 5: misc setters and getters
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
SG_USING_STD(string);
|
||||
SG_USING_STD(vector);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,19 @@
|
|||
# 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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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...
|
||||
|
|
Loading…
Reference in a new issue