1998-05-20 20:53:53 +00:00
|
|
|
// tilemgr.cxx -- routines to handle dynamic management of scenery tiles
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started January 1998.
|
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt
|
1998-05-20 20:53:53 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
2006-02-21 01:16:04 +00:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1998-05-20 20:53:53 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
1998-01-07 23:50:01 +00:00
|
|
|
|
|
|
|
|
1998-04-24 00:51:07 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-03 22:09:02 +00:00
|
|
|
|
2007-12-14 22:51:56 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
|
|
|
|
2008-11-18 22:45:57 +00:00
|
|
|
#include <osgViewer/Viewer>
|
2011-11-08 20:25:10 +00:00
|
|
|
#include <osgDB/Registry>
|
2008-11-18 22:45:57 +00:00
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
#include <simgear/constants.h>
|
2000-02-16 23:01:03 +00:00
|
|
|
#include <simgear/debug/logstream.hxx>
|
2003-09-24 17:20:55 +00:00
|
|
|
#include <simgear/structure/exception.hxx>
|
2003-05-15 21:35:51 +00:00
|
|
|
#include <simgear/scene/model/modellib.hxx>
|
2011-11-12 18:45:20 +00:00
|
|
|
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
2011-06-11 22:44:07 +00:00
|
|
|
#include <simgear/scene/tsync/terrasync.hxx>
|
2013-09-30 11:03:47 +00:00
|
|
|
#include <simgear/misc/strutils.hxx>
|
2014-01-06 08:28:40 +00:00
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
1998-05-23 14:09:20 +00:00
|
|
|
|
The following changes were made to flightgear-0.7.5 code to implement the follow
ing features:
a) ADA Flight model - ADA.cxx, ADA.hxx, flight.hxx
b) Fighter a/c HUD - flight.hxx, hud.hxx, hud.cxx, cockpit.cxx, hud_ladr.c
xx, hud_card.cxx
c) 3-window display - options.hxx, options.cxx, viewer.cxx
d) Moving objects (ship) - main.cxx
e) Patches - main.cxx
ADA.cxx, ADA.hxx
--------------------------
Interface to the external ADA flight dynamics package.
flight.hxx
----------
Included prototypes for accepting additional data fron the External flight
model for fighter aircraft HUD
Hud.hxx
-------
Included prototypes for accepting additional data for fighter HUD from Exernal F
light model.
Defined FIGHTER_HUD pre-processor directive to enable compilation of fighter hud
code.
hud.cxx, cockpit.cxx, hud_ladr.cxx, hud_card.cxx
---------------------------------------
Included code to initialise additional reticles/text for fighter HUD which is co
nditionally
compiled if FIGHTER_HUD is defined.
options.hxx
-----------
Added window_offset, and function to retrieve its value for 3 windows
options.cxx
-----------
Changed few options to suit ADA/CEF projection system/screens and checks for win
dow offset.
views.cxx
---------
Added code to retrieve view offset for window.
Main.cxx
--------
Added code to load and move an aircraft carrier.
Patch to enable clouds from command line until Curtis fixes it. By default cloud
s are disabled.
2000-10-19 19:46:13 +00:00
|
|
|
#include <Main/globals.hxx>
|
2002-02-22 22:51:34 +00:00
|
|
|
#include <Main/fg_props.hxx>
|
2012-04-25 21:28:00 +00:00
|
|
|
#include <Viewer/renderer.hxx>
|
2012-09-24 21:42:25 +00:00
|
|
|
#include <Viewer/splash.hxx>
|
2006-03-09 09:04:03 +00:00
|
|
|
#include <Scripting/NasalSys.hxx>
|
2013-02-09 15:33:05 +00:00
|
|
|
#include <Scripting/NasalModelData.hxx>
|
1999-08-12 17:13:44 +00:00
|
|
|
|
1998-06-05 22:39:53 +00:00
|
|
|
#include "scenery.hxx"
|
2007-12-14 22:51:56 +00:00
|
|
|
#include "SceneryPager.hxx"
|
1998-12-03 01:18:16 +00:00
|
|
|
#include "tilemgr.hxx"
|
1998-06-05 22:39:53 +00:00
|
|
|
|
2007-12-14 22:51:56 +00:00
|
|
|
using flightgear::SceneryPager;
|
1998-09-08 15:05:10 +00:00
|
|
|
|
2011-02-13 17:56:46 +00:00
|
|
|
|
2000-12-03 20:15:46 +00:00
|
|
|
FGTileMgr::FGTileMgr():
|
2000-12-04 05:24:38 +00:00
|
|
|
state( Start ),
|
2011-12-17 14:22:50 +00:00
|
|
|
last_state( Running ),
|
2012-03-25 11:43:28 +00:00
|
|
|
scheduled_visibility(100.0),
|
2012-01-29 09:34:11 +00:00
|
|
|
_terra_sync(NULL),
|
2012-01-29 09:44:28 +00:00
|
|
|
_visibilityMeters(fgGetNode("/environment/visibility-m", true)),
|
2012-02-07 20:12:51 +00:00
|
|
|
_maxTileRangeM(fgGetNode("/sim/rendering/static-lod/bare", true)),
|
2012-04-15 13:30:44 +00:00
|
|
|
_disableNasalHooks(fgGetNode("/sim/temp/disable-scenery-nasal", true)),
|
2012-09-24 21:42:25 +00:00
|
|
|
_scenery_loaded(fgGetNode("/sim/sceneryloaded", true)),
|
|
|
|
_scenery_override(fgGetNode("/sim/sceneryloaded-override", true)),
|
2012-04-15 13:30:44 +00:00
|
|
|
_pager(FGScenery::getPagerSingleton())
|
1999-06-13 05:58:02 +00:00
|
|
|
{
|
|
|
|
}
|
1999-05-06 21:14:06 +00:00
|
|
|
|
1998-01-24 00:03:27 +00:00
|
|
|
|
2011-06-11 22:44:07 +00:00
|
|
|
FGTileMgr::~FGTileMgr()
|
|
|
|
{
|
2008-05-14 22:10:07 +00:00
|
|
|
// remove all nodes we might have left behind
|
|
|
|
osg::Group* group = globals->get_scenery()->get_terrain_branch();
|
|
|
|
group->removeChildren(0, group->getNumChildren());
|
2011-04-15 19:34:44 +00:00
|
|
|
// clear OSG cache
|
|
|
|
osgDB::Registry::instance()->clearObjectCache();
|
1999-06-13 05:58:02 +00:00
|
|
|
}
|
1999-05-06 21:14:06 +00:00
|
|
|
|
1998-01-07 23:50:01 +00:00
|
|
|
|
1998-05-20 20:53:53 +00:00
|
|
|
// Initialize the Tile Manager subsystem
|
2010-10-01 18:09:19 +00:00
|
|
|
void FGTileMgr::init() {
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." );
|
1998-06-05 22:39:53 +00:00
|
|
|
|
2011-11-12 18:45:20 +00:00
|
|
|
_options = new simgear::SGReaderWriterOptions;
|
2014-01-19 16:49:32 +00:00
|
|
|
|
|
|
|
materialLibChanged();
|
2011-11-12 18:45:20 +00:00
|
|
|
_options->setPropertyNode(globals->get_props());
|
2011-02-13 17:56:46 +00:00
|
|
|
|
2008-05-14 22:10:07 +00:00
|
|
|
osgDB::FilePathList &fp = _options->getDatabasePathList();
|
|
|
|
const string_list &sc = globals->get_fg_scenery();
|
|
|
|
fp.clear();
|
|
|
|
std::copy(sc.begin(), sc.end(), back_inserter(fp));
|
2012-03-15 18:04:55 +00:00
|
|
|
_options->setPluginStringData("SimGear::FG_ROOT", globals->get_fg_root());
|
2013-08-29 21:12:34 +00:00
|
|
|
|
|
|
|
if (globals->get_subsystem("terrasync")) {
|
|
|
|
_options->setPluginStringData("SimGear::TERRASYNC_ROOT", fgGetString("/sim/terrasync/scenery-dir"));
|
|
|
|
}
|
|
|
|
|
2012-03-15 18:04:55 +00:00
|
|
|
if (!_disableNasalHooks->getBoolValue())
|
|
|
|
_options->setModelData(new FGNasalModelDataProxy);
|
2008-05-14 22:10:07 +00:00
|
|
|
|
2010-10-01 18:09:19 +00:00
|
|
|
reinit();
|
|
|
|
}
|
2001-05-30 18:21:03 +00:00
|
|
|
|
2010-10-01 18:09:19 +00:00
|
|
|
void FGTileMgr::reinit()
|
|
|
|
{
|
2012-11-27 23:26:47 +00:00
|
|
|
_terra_sync = static_cast<simgear::SGTerraSync*> (globals->get_subsystem("terrasync"));
|
2013-09-30 11:07:35 +00:00
|
|
|
|
2012-04-07 14:35:04 +00:00
|
|
|
// protect against multiple scenery reloads and properly reset flags,
|
|
|
|
// otherwise aircraft fall through the ground while reloading scenery
|
|
|
|
if (!fgGetBool("/sim/sceneryloaded",true))
|
|
|
|
return;
|
2012-04-07 14:19:09 +00:00
|
|
|
fgSetBool("/sim/sceneryloaded",false);
|
|
|
|
fgSetDouble("/sim/startup/splash-alpha", 1.0);
|
2012-07-19 21:06:08 +00:00
|
|
|
|
2014-01-19 16:49:32 +00:00
|
|
|
materialLibChanged();
|
2012-04-07 14:19:09 +00:00
|
|
|
|
2011-02-13 18:24:54 +00:00
|
|
|
// remove all old scenery nodes from scenegraph and clear cache
|
|
|
|
osg::Group* group = globals->get_scenery()->get_terrain_branch();
|
|
|
|
group->removeChildren(0, group->getNumChildren());
|
2010-11-19 12:59:43 +00:00
|
|
|
tile_cache.init();
|
|
|
|
|
2011-04-15 19:34:44 +00:00
|
|
|
// clear OSG cache, except on initial start-up
|
|
|
|
if (state != Start)
|
|
|
|
{
|
|
|
|
osgDB::Registry::instance()->clearObjectCache();
|
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
state = Inited;
|
|
|
|
|
|
|
|
previous_bucket.make_bad();
|
|
|
|
current_bucket.make_bad();
|
2012-03-25 11:43:28 +00:00
|
|
|
scheduled_visibility = 100.0;
|
2011-06-11 22:44:07 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// force an update now
|
|
|
|
update(0.0);
|
1998-01-07 23:50:01 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 16:49:32 +00:00
|
|
|
void FGTileMgr::materialLibChanged()
|
|
|
|
{
|
|
|
|
_options->setMaterialLib(globals->get_matlib());
|
|
|
|
_options->getMaterialLib()->refreshActiveMaterials();
|
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
/* schedule a tile for loading, keep request for given amount of time.
|
|
|
|
* Returns true if tile is already loaded. */
|
|
|
|
bool FGTileMgr::sched_tile( const SGBucket& b, double priority, bool current_view, double duration)
|
|
|
|
{
|
1999-06-13 05:58:02 +00:00
|
|
|
// see if tile already exists in the cache
|
2008-05-14 22:10:07 +00:00
|
|
|
TileEntry *t = tile_cache.get_tile( b );
|
2010-11-19 12:59:43 +00:00
|
|
|
if (!t)
|
|
|
|
{
|
|
|
|
// create a new entry
|
|
|
|
t = new TileEntry( b );
|
|
|
|
// insert the tile into the cache, update will generate load request
|
|
|
|
if ( tile_cache.insert_tile( t ) )
|
|
|
|
{
|
|
|
|
// Attach to scene graph
|
2011-04-17 08:19:58 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
t->addToSceneGraph(globals->get_scenery()->get_terrain_branch());
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
// insert failed (cache full with no available entries to
|
|
|
|
// delete.) Try again later
|
|
|
|
delete t;
|
|
|
|
return false;
|
2002-07-25 21:57:58 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_DEBUG, " New tile cache size " << (int)tile_cache.get_size() );
|
1999-06-13 05:58:02 +00:00
|
|
|
}
|
2010-11-19 12:59:43 +00:00
|
|
|
|
|
|
|
// update tile's properties
|
|
|
|
tile_cache.request_tile(t,priority,current_view,duration);
|
|
|
|
|
|
|
|
return t->is_loaded();
|
1999-06-13 05:58:02 +00:00
|
|
|
}
|
1998-05-20 20:53:53 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
/* schedule needed buckets for the current view position for loading,
|
|
|
|
* keep request for given amount of time */
|
|
|
|
void FGTileMgr::schedule_needed(const SGBucket& curr_bucket, double vis)
|
|
|
|
{
|
2001-11-12 22:05:47 +00:00
|
|
|
// sanity check (unfortunately needed!)
|
2014-02-13 18:52:52 +00:00
|
|
|
if (!curr_bucket.isValid() )
|
2001-11-12 22:05:47 +00:00
|
|
|
{
|
|
|
|
SG_LOG( SG_TERRAIN, SG_ALERT,
|
2014-02-13 18:52:52 +00:00
|
|
|
"Attempting to schedule tiles for invalid bucket" );
|
2011-06-11 22:44:07 +00:00
|
|
|
return;
|
2001-11-12 22:05:47 +00:00
|
|
|
}
|
|
|
|
|
From: "Jim Wilson" <jimw@kelcomaine.com>
This is a new improved patch for the previous tile manager fixes.
Rather than building dependencies between FGlocation or the viewer or fdm with
tilemgr what I ended up doing was linking the pieces together in the Mainloop
in main.cxx. You'll see what I mean...it's been commented fairly well. More
than likely we should move that chunk somewhere...just not sure where yet.
The changes seem clean now. As I get more ideas there could be some further
improvement in organizing the update in tilemgr. You'll note that I left an
override in there for the tilemgr::update() function to preserve earlier
functionality if someone needs it (e.g. usage independent of an fdm or
viewer), not to mention there are a few places in flightgear that call it
directly that have not been changed to the new interface (and may not need to be).
The code has been optimized to avoid duplicate traversals and seems to run
generally quite well. Note that there can be a short delay reloading tiles
that have been dropped from static views. We could call the tile scheduler on
a view switch, but it's not a big deal and at the moment I'd like to get this
in so people can try it and comment on it as it is.
Everything has been resycned with CVS tonight and I've included the
description submitted earlier (below).
Best,
Jim
Changes synced with CVS approx 20:30EDT 2002-05-09 (after this evenings updates).
Files:
http://www.spiderbark.com/fgfs/viewer-update-20020516.tar.gz
or
http://www.spiderbark.com/fgfs/viewer-update-20020516.diffs.gz
Description:
In a nutshell, these patches begin to take what was one value for ground
elevation and calculate ground elevation values seperately for the FDM and the
viewer (eye position). Several outstanding view related bugs have been fixed.
With the introduction of the new viewer code a lot of that Flight Gear code
broke related to use of a global variable called "scenery.cur_elev".
Therefore the ground_elevation and other associated items (like the current
tile bucket) is maintained per FDM instance and per View. Each of these has a
"point" or location that can be identified. See changes to FGLocation class
and main.cxx.
Most of the problems related to the new viewer in terms of sky, ground and
runway lights, and tower views are fixed.
There are four minor problems remaining. 1) The sun/moon spins when you pan
the "lookat" tower view only (view #3). 2) Under stress (esp. magic carpet
full speed with max visibility), there is a memory leak in the tile caching
that was not introduced with these changes. 3) I have not tested these
changes or made corrections to the ADA or External FDM interfaces. 4) The
change view function doesn't call the time/light update (not a problem unless
a tower is very far away).
Details:
FDM/flight.cxx, flight.hxx - FGInterface ties to FGAircraftModel so that it's
location data can be accessed for runway (ground elevation under aircraft)
elevation.
FDM/larsim.cxx, larcsim.hxx - gets runway elevation from FGInterface now.
Commented out function that is causing a namespace conflict, hasn't been
called with recent code anyway.
FDM/JSBSim/JSBSim.cxx, YASim/YASim.cxx - gets runway elevation from
FGInterface now.
Scenery/newcache.cxx, newcache.hxx - changed caching scheme to time based
(oldest tiles discard).
Scenery/tileentry.cxx, tileentry.hxx - added place to record time, changed
rendering to reference viewer altitude in order to fix a problem with ground
and runway lights.
Scenery/tilemgr.cxx, tilemgr.hxx - Modified update() to accept values for
multiple locations. Refresh function added in order to periodically make
the tiles current for a non-moving view (like a tower).
Main/fg_init.cxx - register event for making tiles current in a non-moving
view (like a tower).
Main/location.hxx - added support for current ground elevation data.
Main/main.cxx - added second tilemgr call for fdm, fixed places where viewer
position data was required for correct sky rendering.
Main/options.cxx - fixed segfault reported by Curtis when using --view-offset
command line parameter.
Main/viewer.cxx, viewer.hxx - removed fudging of view position. Fixed numerous
bugs that were causing eye and target values to get mixed up.
2002-05-17 17:25:28 +00:00
|
|
|
double tile_width = curr_bucket.get_width_m();
|
|
|
|
double tile_height = curr_bucket.get_height_m();
|
2014-02-13 18:52:52 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO,
|
|
|
|
"scheduling needed tiles for " << curr_bucket
|
|
|
|
<< ", tile-width-m:" << tile_width << ", tile-height-m:" << tile_height);
|
|
|
|
|
|
|
|
|
2001-04-11 02:47:15 +00:00
|
|
|
// cout << "tile width = " << tile_width << " tile_height = "
|
2004-03-18 02:37:01 +00:00
|
|
|
// << tile_height << endl;
|
2000-12-03 20:15:46 +00:00
|
|
|
|
2011-10-17 16:41:59 +00:00
|
|
|
double tileRangeM = std::min(vis,_maxTileRangeM->getDoubleValue());
|
2012-03-25 11:43:28 +00:00
|
|
|
int xrange = (int)(tileRangeM / tile_width) + 1;
|
|
|
|
int yrange = (int)(tileRangeM / tile_height) + 1;
|
2004-01-26 22:44:27 +00:00
|
|
|
if ( xrange < 1 ) { xrange = 1; }
|
2000-12-03 20:15:46 +00:00
|
|
|
if ( yrange < 1 ) { yrange = 1; }
|
|
|
|
|
2008-05-14 22:10:07 +00:00
|
|
|
// make the cache twice as large to avoid losing terrain when switching
|
|
|
|
// between aircraft and tower views
|
2002-08-01 06:15:59 +00:00
|
|
|
tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) * 2 );
|
2004-03-18 02:37:01 +00:00
|
|
|
// cout << "xrange = " << xrange << " yrange = " << yrange << endl;
|
|
|
|
// cout << "max cache size = " << tile_cache.get_max_cache_size()
|
|
|
|
// << " current cache size = " << tile_cache.get_size() << endl;
|
2000-12-03 20:15:46 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// clear flags of all tiles belonging to the previous view set
|
|
|
|
tile_cache.clear_current_view();
|
2010-10-02 21:03:27 +00:00
|
|
|
|
|
|
|
// update timestamps, so all tiles scheduled now are *newer* than any tile previously loaded
|
|
|
|
osg::FrameStamp* framestamp
|
|
|
|
= globals->get_renderer()->getViewer()->getFrameStamp();
|
|
|
|
tile_cache.set_current_time(framestamp->getReferenceTime());
|
|
|
|
|
2001-01-17 23:30:35 +00:00
|
|
|
SGBucket b;
|
|
|
|
|
2001-03-21 23:10:15 +00:00
|
|
|
int x, y;
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
/* schedule all tiles, use distance-based loading priority,
|
|
|
|
* so tiles are loaded in innermost-to-outermost sequence. */
|
|
|
|
for ( x = -xrange; x <= xrange; ++x )
|
|
|
|
{
|
|
|
|
for ( y = -yrange; y <= yrange; ++y )
|
|
|
|
{
|
2014-02-13 18:52:52 +00:00
|
|
|
SGBucket b = curr_bucket.sibling(x, y);
|
|
|
|
if (!b.isValid()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
float priority = (-1.0) * (x*x+y*y);
|
|
|
|
sched_tile( b, priority, true, 0.0 );
|
2013-09-30 11:03:47 +00:00
|
|
|
|
|
|
|
if (_terra_sync) {
|
|
|
|
_terra_sync->scheduleTile(b);
|
|
|
|
}
|
2002-12-07 02:26:50 +00:00
|
|
|
}
|
2000-06-15 22:32:26 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-03 21:01:59 +00:00
|
|
|
|
2002-11-30 02:21:04 +00:00
|
|
|
/**
|
|
|
|
* Update the various queues maintained by the tilemagr (private
|
|
|
|
* internal function, do not call directly.)
|
|
|
|
*/
|
2013-09-30 15:13:04 +00:00
|
|
|
void FGTileMgr::update_queues(bool& isDownloadingScenery)
|
2002-11-30 02:21:04 +00:00
|
|
|
{
|
2008-11-25 22:49:19 +00:00
|
|
|
osg::FrameStamp* framestamp
|
|
|
|
= globals->get_renderer()->getViewer()->getFrameStamp();
|
2010-11-19 12:59:43 +00:00
|
|
|
double current_time = framestamp->getReferenceTime();
|
|
|
|
double vis = _visibilityMeters->getDoubleValue();
|
|
|
|
TileEntry *e;
|
|
|
|
int loading=0;
|
|
|
|
int sz=0;
|
2014-01-06 08:28:40 +00:00
|
|
|
bool didRefreshMaterialCache = false;
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
tile_cache.set_current_time( current_time );
|
|
|
|
tile_cache.reset_traversal();
|
|
|
|
|
|
|
|
while ( ! tile_cache.at_end() )
|
|
|
|
{
|
|
|
|
e = tile_cache.get_current();
|
|
|
|
if ( e )
|
|
|
|
{
|
|
|
|
// Prepare the ssg nodes corresponding to each tile.
|
|
|
|
// Set the ssg transform and update it's range selector
|
|
|
|
// based on current visibilty
|
|
|
|
e->prep_ssg_node(vis);
|
2013-09-30 11:03:47 +00:00
|
|
|
|
2013-09-30 15:13:04 +00:00
|
|
|
if (!e->is_loaded()) {
|
2014-01-06 08:28:40 +00:00
|
|
|
if (!didRefreshMaterialCache) {
|
|
|
|
didRefreshMaterialCache = true;
|
|
|
|
globals->get_matlib()->refreshActiveMaterials();
|
|
|
|
}
|
|
|
|
|
2013-09-30 15:13:04 +00:00
|
|
|
bool nonExpiredOrCurrent = !e->is_expired(current_time) || e->is_current_view();
|
|
|
|
bool downloading = isTileDirSyncing(e->tileFileName);
|
|
|
|
isDownloadingScenery |= downloading;
|
|
|
|
if ( !downloading && nonExpiredOrCurrent) {
|
|
|
|
// schedule tile for loading with osg pager
|
|
|
|
_pager->queueRequest(e->tileFileName,
|
|
|
|
e->getNode(),
|
|
|
|
e->get_priority(),
|
|
|
|
framestamp,
|
|
|
|
e->getDatabaseRequest(),
|
|
|
|
_options.get());
|
|
|
|
loading++;
|
|
|
|
}
|
|
|
|
} // of tile not loaded case
|
|
|
|
} else {
|
2011-08-11 22:09:26 +00:00
|
|
|
SG_LOG(SG_TERRAIN, SG_ALERT, "Warning: empty tile in cache!");
|
2010-11-19 12:59:43 +00:00
|
|
|
}
|
|
|
|
tile_cache.next();
|
|
|
|
sz++;
|
|
|
|
}
|
2002-11-30 02:21:04 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
int drop_count = sz - tile_cache.get_max_cache_size();
|
|
|
|
if (( drop_count > 0 )&&
|
|
|
|
((loading==0)||(drop_count > 10)))
|
|
|
|
{
|
|
|
|
long drop_index = tile_cache.get_drop_tile();
|
|
|
|
while ( drop_index > -1 )
|
|
|
|
{
|
|
|
|
// schedule tile for deletion with osg pager
|
|
|
|
TileEntry* old = tile_cache.get_tile(drop_index);
|
|
|
|
tile_cache.clear_entry(drop_index);
|
|
|
|
|
|
|
|
osg::ref_ptr<osg::Object> subgraph = old->getNode();
|
|
|
|
old->removeFromSceneGraph();
|
|
|
|
delete old;
|
|
|
|
// zeros out subgraph ref_ptr, so subgraph is owned by
|
|
|
|
// the pager and will be deleted in the pager thread.
|
2012-04-15 13:30:44 +00:00
|
|
|
_pager->queueDeleteRequest(subgraph);
|
2010-11-19 12:59:43 +00:00
|
|
|
|
|
|
|
if (--drop_count > 0)
|
|
|
|
drop_index = tile_cache.get_drop_tile();
|
|
|
|
else
|
|
|
|
drop_index = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-11-30 02:21:04 +00:00
|
|
|
|
2002-11-30 14:22:00 +00:00
|
|
|
// given the current lon/lat (in degrees), fill in the array of local
|
|
|
|
// chunks. If the chunk isn't already in the cache, then read it from
|
|
|
|
// disk.
|
2010-10-01 18:09:19 +00:00
|
|
|
void FGTileMgr::update(double)
|
2002-11-30 14:22:00 +00:00
|
|
|
{
|
2010-10-01 18:09:19 +00:00
|
|
|
double vis = _visibilityMeters->getDoubleValue();
|
2012-09-25 09:06:30 +00:00
|
|
|
schedule_tiles_at(globals->get_view_position(), vis);
|
2010-11-19 12:59:43 +00:00
|
|
|
|
2013-09-30 15:13:04 +00:00
|
|
|
bool waitingOnTerrasync = false;
|
|
|
|
update_queues(waitingOnTerrasync);
|
2012-09-24 21:42:25 +00:00
|
|
|
|
|
|
|
// scenery loading check, triggers after each sim (tile manager) reinit
|
|
|
|
if (!_scenery_loaded->getBoolValue())
|
|
|
|
{
|
2012-09-27 14:15:02 +00:00
|
|
|
bool fdmInited = fgGetBool("sim/fdm-initialized");
|
2012-12-15 15:25:45 +00:00
|
|
|
bool positionFinalized = fgGetBool("sim/position-finalized");
|
|
|
|
bool sceneryOverride = _scenery_override->getBoolValue();
|
|
|
|
|
2013-09-30 15:13:04 +00:00
|
|
|
|
2012-12-15 15:25:45 +00:00
|
|
|
// we are done if final position is set and the scenery & FDM are done.
|
|
|
|
// scenery-override can ignore the last two, but not position finalization.
|
|
|
|
if (positionFinalized && (sceneryOverride || (isSceneryLoaded() && fdmInited)))
|
2012-09-24 21:42:25 +00:00
|
|
|
{
|
|
|
|
_scenery_loaded->setBoolValue(true);
|
|
|
|
fgSplashProgress("");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-30 15:13:04 +00:00
|
|
|
if (!positionFinalized) {
|
|
|
|
fgSplashProgress("finalize-position");
|
|
|
|
} else if (waitingOnTerrasync) {
|
|
|
|
fgSplashProgress("downloading-scenery");
|
|
|
|
} else {
|
|
|
|
fgSplashProgress("loading-scenery");
|
|
|
|
}
|
|
|
|
|
2012-09-24 21:42:25 +00:00
|
|
|
// be nice to loader threads while waiting for initial scenery, reduce to 20fps
|
|
|
|
SGTimeStamp::sleepForMSec(50);
|
|
|
|
}
|
|
|
|
}
|
2002-11-30 14:22:00 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 21:42:25 +00:00
|
|
|
// schedule tiles for the viewer bucket
|
|
|
|
// (FDM/AI/groundcache/... should use "schedule_scenery" instead)
|
|
|
|
void FGTileMgr::schedule_tiles_at(const SGGeod& location, double range_m)
|
2002-11-30 14:22:00 +00:00
|
|
|
{
|
2002-12-06 22:29:46 +00:00
|
|
|
// SG_LOG( SG_TERRAIN, SG_DEBUG, "FGTileMgr::update() for "
|
2012-09-24 21:42:25 +00:00
|
|
|
// << longitude << " " << latitude );
|
2002-11-30 02:21:04 +00:00
|
|
|
|
2009-03-07 11:24:47 +00:00
|
|
|
current_bucket.set_bucket( location );
|
2010-11-19 12:59:43 +00:00
|
|
|
|
|
|
|
// schedule more tiles when visibility increased considerably
|
|
|
|
// TODO Calculate tile size - instead of using fixed value (5000m)
|
2012-03-25 11:43:28 +00:00
|
|
|
if (range_m - scheduled_visibility > 5000.0)
|
2010-11-19 12:59:43 +00:00
|
|
|
previous_bucket.make_bad();
|
|
|
|
|
2002-12-06 22:29:46 +00:00
|
|
|
// SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating tile list for "
|
|
|
|
// << current_bucket );
|
2003-08-28 20:52:34 +00:00
|
|
|
fgSetInt( "/environment/current-tile-id", current_bucket.gen_index() );
|
2002-11-30 02:21:04 +00:00
|
|
|
|
2011-06-11 22:44:07 +00:00
|
|
|
// do tile load scheduling.
|
2002-11-30 02:21:04 +00:00
|
|
|
// Note that we need keep track of both viewer buckets and fdm buckets.
|
|
|
|
if ( state == Running ) {
|
2011-12-17 14:22:50 +00:00
|
|
|
if (last_state != state)
|
|
|
|
{
|
|
|
|
SG_LOG( SG_TERRAIN, SG_DEBUG, "State == Running" );
|
|
|
|
}
|
2007-12-14 22:52:31 +00:00
|
|
|
if (current_bucket != previous_bucket) {
|
2002-12-07 02:26:50 +00:00
|
|
|
// We've moved to a new bucket, we need to schedule any
|
|
|
|
// needed tiles for loading.
|
2014-02-13 18:52:52 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_INFO, "FGTileMgr: at " << location << ", scheduling needed for:" << current_bucket
|
|
|
|
<< ", visbility=" << range_m);
|
2010-11-19 12:59:43 +00:00
|
|
|
scheduled_visibility = range_m;
|
|
|
|
schedule_needed(current_bucket, range_m);
|
2002-12-07 02:26:50 +00:00
|
|
|
}
|
2013-09-30 11:03:47 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// save bucket
|
|
|
|
previous_bucket = current_bucket;
|
2002-11-30 02:21:04 +00:00
|
|
|
} else if ( state == Start || state == Inited ) {
|
2011-12-17 14:22:50 +00:00
|
|
|
SG_LOG( SG_TERRAIN, SG_DEBUG, "State == Start || Inited" );
|
2010-11-19 12:59:43 +00:00
|
|
|
// do not update bucket yet (position not valid in initial loop)
|
2002-12-07 02:26:50 +00:00
|
|
|
state = Running;
|
2010-11-19 12:59:43 +00:00
|
|
|
previous_bucket.make_bad();
|
2002-11-30 02:21:04 +00:00
|
|
|
}
|
2011-12-17 14:22:50 +00:00
|
|
|
last_state = state;
|
1998-09-08 15:05:10 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
/** Schedules scenery for given position. Load request remains valid for given duration
|
|
|
|
* (duration=0.0 => nothing is loaded).
|
|
|
|
* Used for FDM/AI/groundcache/... requests. Viewer uses "schedule_tiles_at" instead.
|
|
|
|
* Returns true when all tiles for the given position are already loaded, false otherwise.
|
|
|
|
*/
|
|
|
|
bool FGTileMgr::schedule_scenery(const SGGeod& position, double range_m, double duration)
|
2005-08-14 12:57:12 +00:00
|
|
|
{
|
2010-11-19 12:59:43 +00:00
|
|
|
// sanity check (unfortunately needed!)
|
2014-02-05 22:04:58 +00:00
|
|
|
if (!position.isValid())
|
2010-11-19 12:59:43 +00:00
|
|
|
return false;
|
2014-02-05 22:04:58 +00:00
|
|
|
const float priority = 0.0;
|
|
|
|
bool available = true;
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
SGBucket bucket(position);
|
|
|
|
available = sched_tile( bucket, priority, false, duration );
|
2005-08-14 12:57:12 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
if ((!available)&&(duration==0.0))
|
|
|
|
return false;
|
2005-08-14 12:57:12 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
SGVec3d cartPos = SGVec3d::fromGeod(position);
|
2007-12-14 22:51:56 +00:00
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// Traverse all tiles required to be there for the given visibility.
|
|
|
|
double tile_width = bucket.get_width_m();
|
|
|
|
double tile_height = bucket.get_height_m();
|
|
|
|
double tile_r = 0.5*sqrt(tile_width*tile_width + tile_height*tile_height);
|
|
|
|
double max_dist = tile_r + range_m;
|
|
|
|
double max_dist2 = max_dist*max_dist;
|
|
|
|
|
|
|
|
int xrange = (int)fabs(range_m / tile_width) + 1;
|
|
|
|
int yrange = (int)fabs(range_m / tile_height) + 1;
|
|
|
|
|
|
|
|
for ( int x = -xrange; x <= xrange; ++x )
|
2007-12-14 22:51:56 +00:00
|
|
|
{
|
2010-11-19 12:59:43 +00:00
|
|
|
for ( int y = -yrange; y <= yrange; ++y )
|
|
|
|
{
|
|
|
|
// We have already checked for the center tile.
|
|
|
|
if ( x != 0 || y != 0 )
|
|
|
|
{
|
2014-02-13 18:52:52 +00:00
|
|
|
SGBucket b = bucket.sibling(x, y );
|
|
|
|
if (!b.isValid()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
double distance2 = distSqr(cartPos, SGVec3d::fromGeod(b.get_center()));
|
|
|
|
// Do not ask if it is just the next tile but way out of range.
|
|
|
|
if (distance2 <= max_dist2)
|
|
|
|
{
|
|
|
|
available &= sched_tile( b, priority, false, duration );
|
|
|
|
if ((!available)&&(duration==0.0))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-14 22:51:56 +00:00
|
|
|
}
|
2010-11-19 12:59:43 +00:00
|
|
|
|
|
|
|
return available;
|
2007-12-14 22:51:56 +00:00
|
|
|
}
|
|
|
|
|
2010-11-19 12:59:43 +00:00
|
|
|
// Returns true if tiles around current view position have been loaded
|
2007-12-14 22:51:56 +00:00
|
|
|
bool FGTileMgr::isSceneryLoaded()
|
|
|
|
{
|
2010-11-19 12:59:43 +00:00
|
|
|
double range_m = 100.0;
|
|
|
|
if (scheduled_visibility < range_m)
|
|
|
|
range_m = scheduled_visibility;
|
|
|
|
|
2014-02-13 18:52:52 +00:00
|
|
|
return schedule_scenery(globals->get_view_position(), range_m, 0.0);
|
2007-12-14 22:51:56 +00:00
|
|
|
}
|
2013-09-30 11:03:47 +00:00
|
|
|
|
|
|
|
bool FGTileMgr::isTileDirSyncing(const std::string& tileFileName) const
|
|
|
|
{
|
|
|
|
if (!_terra_sync) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string nameWithoutExtension = tileFileName.substr(0, tileFileName.size() - 4);
|
|
|
|
long int bucketIndex = simgear::strutils::to_int(nameWithoutExtension);
|
|
|
|
SGBucket bucket(bucketIndex);
|
|
|
|
|
|
|
|
return _terra_sync->isTileDirPending(bucket.gen_base_path());
|
|
|
|
}
|
|
|
|
|