1
0
Fork 0

WS30 Move VPB tile loading to the tile manager

Previously VPB tiles were loaded by the STG file loader.

This was not ideal as the VPB tile granularity is 1x1 degree
while the STG file loader is 20x20km.

This change makes the tile manager load VPB tiles explicitly
on range, and allows better prioritization of the underlying
terrain.
This commit is contained in:
Stuart Buchanan 2021-10-20 23:39:59 +01:00
parent c8a3f60245
commit c1fc71066b
6 changed files with 155 additions and 27 deletions

View file

@ -75,13 +75,21 @@ void TileCache::init( void ) {
// Search for the specified "bucket" in the cache
bool TileCache::exists( const SGBucket& b ) const {
bool TileCache::exists_stg( const SGBucket& b ) const {
long tile_index = b.gen_index();
const_tile_map_iterator it = tile_cache.find( tile_index );
return ( it != tile_cache.end() );
}
bool TileCache::exists_vpb( const SGBucket& b ) const {
// VPB tiles are stored with negative index to avoid clash with STG index
long tile_index = - b.gen_vpb_index();
const_tile_map_iterator it = tile_cache.find( tile_index );
return ( it != tile_cache.end() );
}
// Return the index of a tile to be dropped from the cache, return -1 if
// nothing available to be removed.
@ -191,7 +199,7 @@ void TileCache::clear_cache() {
/**
* Create a new tile and schedule it for loading.
*/
bool TileCache::insert_tile( TileEntry *e ) {
bool TileCache::insert_tile( STGTileEntry *e ) {
// register tile in the cache
long tile_index = e->get_tile_bucket().gen_index();
tile_cache[tile_index] = e;
@ -200,6 +208,19 @@ bool TileCache::insert_tile( TileEntry *e ) {
return true;
}
/**
* Create a new tile and schedule it for loading. VPB version, with negative index.
*/
bool TileCache::insert_tile( VPBTileEntry *e ) {
// register tile in the cache
long tile_index = - e->get_tile_bucket().gen_vpb_index();
tile_cache[tile_index] = e;
e->update_time_expired(current_time);
return true;
}
// update tile's priority and expiry time according to current request
void TileCache::request_tile(TileEntry* t,float priority,bool current_view,double request_time)
{
@ -223,3 +244,31 @@ void TileCache::request_tile(TileEntry* t,float priority,bool current_view,doubl
t->update_time_expired( current_time+request_time );
}
}
// Return a pointer to the specified tile cache entry
STGTileEntry* TileCache::get_stg_tile( const SGBucket& b ) const {
const_tile_map_iterator it = std::find_if(tile_cache.begin(), tile_cache.end(),
[b](auto &t) {
return ((b.gen_index() == t.first) && (t.second->getExtension() == TileEntry::Extension::STG));
});
if ( it != tile_cache.end() ) {
return dynamic_cast<STGTileEntry*>(it->second);
} else {
return NULL;
}
}
// Return a pointer to the specified tile cache entry
VPBTileEntry* TileCache::get_vpb_tile( const SGBucket& b ) const {
const_tile_map_iterator it = std::find_if(tile_cache.begin(), tile_cache.end(),
[b](auto &t) {
// Negative indices are used for the VPB tiles.
return (( - b.gen_vpb_index() == t.first) && (t.second->getExtension() == TileEntry::Extension::VPB));
});
if ( it != tile_cache.end() ) {
return dynamic_cast<VPBTileEntry*>(it->second);
} else {
return NULL;
}
}

View file

@ -68,7 +68,8 @@ public:
void init( void );
// Check if the specified "bucket" exists in the cache
bool exists( const SGBucket& b ) const;
bool exists_stg( const SGBucket& b ) const;
bool exists_vpb( const SGBucket& b ) const;
// Return the index of a tile to be dropped from the cache, return -1 if
// nothing available to be removed.
@ -88,18 +89,16 @@ public:
// Return a pointer to the specified tile cache entry
inline TileEntry *get_tile( const long tile_index ) const {
const_tile_map_iterator it = tile_cache.find( tile_index );
if ( it != tile_cache.end() ) {
return it->second;
} else {
return NULL;
}
const_tile_map_iterator it = tile_cache.find( tile_index );
if ( it != tile_cache.end() ) {
return it->second;
} else {
return NULL;
}
}
// Return a pointer to the specified tile cache entry
inline TileEntry *get_tile( const SGBucket& b ) const {
return get_tile( b.gen_index() );
}
STGTileEntry* get_stg_tile( const SGBucket& b ) const;
VPBTileEntry* get_vpb_tile( const SGBucket& b ) const;
// Return the cache size
inline size_t get_size() const { return tile_cache.size(); }
@ -121,7 +120,8 @@ public:
* @param b
* @return success/failure
*/
bool insert_tile( TileEntry* e );
bool insert_tile( STGTileEntry* e );
bool insert_tile( VPBTileEntry* e );
void set_current_time(double val) { current_time = val; }
double get_current_time() const { return current_time; }

View file

@ -37,10 +37,9 @@
using std::string;
// Constructor
// Base constructor
TileEntry::TileEntry ( const SGBucket& b )
: tile_bucket( b ),
tileFileName(b.gen_index_str()),
_node( new osg::LOD ),
_priority(-FLT_MAX),
_current_view(false),
@ -48,8 +47,6 @@ TileEntry::TileEntry ( const SGBucket& b )
{
_create_orthophoto();
tileFileName += ".stg";
_node->setName(tileFileName);
// Give a default LOD range so that traversals that traverse
// active children (like the groundcache lookup) will work before
// tile manager has had a chance to update this node.
@ -131,3 +128,31 @@ TileEntry::removeFromSceneGraph()
}
}
// Constructor - STG Variant
STGTileEntry::STGTileEntry ( const SGBucket& b ) : TileEntry(b)
{
tileFileName = b.gen_index_str() + ".stg";
_node->setName(tileFileName);
}
// Destructor - STG Variant
STGTileEntry::~STGTileEntry ()
{
}
// Constructur - VPB version
VPBTileEntry::VPBTileEntry ( const SGBucket& b ) : TileEntry(b)
{
tileFileName = "vpb/" + b.gen_vpb_base() + ".osgb";
_node->setName(tileFileName);
// Give a default LOD range so that traversals that traverse
// active children (like the groundcache lookup) will work before
// tile manager has had a chance to update this node.
_node->setRange(0, 0.0, 160000.0);
}
// Destructor - VPB Variant
VPBTileEntry::~VPBTileEntry ()
{
}

View file

@ -56,10 +56,11 @@ public:
SGBucket tile_bucket;
std::string tileFileName;
private:
protected:
// pointer to ssg range selector for this tile
osg::ref_ptr<osg::LOD> _node;
private:
// Reference to DatabaseRequest object set and used by the
// osgDB::DatabasePager.
osg::ref_ptr<osg::Referenced> _databaseRequest;
@ -82,12 +83,12 @@ private:
public:
// Constructor
// Constructor.
TileEntry( const SGBucket& b );
TileEntry( const TileEntry& t );
// Destructor
~TileEntry();
virtual ~TileEntry() = 0;
// Update the ssg transform node for this tile so it can be
// properly drawn relative to our (0,0,0) point
@ -148,6 +149,27 @@ public:
{
return _databaseRequest;
}
enum Extension {
STG, VPB
};
virtual TileEntry::Extension getExtension() = 0;
};
class STGTileEntry : public TileEntry {
public:
STGTileEntry ( const SGBucket& b );
~STGTileEntry();
inline TileEntry::Extension getExtension() { return TileEntry::Extension::STG; };
};
class VPBTileEntry : public TileEntry {
public:
VPBTileEntry ( const SGBucket& b );
~VPBTileEntry();
inline TileEntry::Extension getExtension() { return TileEntry::Extension::VPB; };
};
#endif // _TILEENTRY_HXX

View file

@ -146,7 +146,8 @@ FGTileMgr::FGTileMgr():
_scenery_loaded(fgGetNode("/sim/sceneryloaded", true)),
_scenery_override(fgGetNode("/sim/sceneryloaded-override", true)),
_pager(FGScenery::getPagerSingleton()),
_enableCache(true)
_enableCache(true),
_use_vpb(false)
{
}
@ -206,6 +207,7 @@ void FGTileMgr::reinit()
double rough = fgGetDouble("/sim/rendering/static-lod/rough-delta", SG_OBJECT_RANGE_ROUGH) + detailed;
double bare = fgGetDouble("/sim/rendering/static-lod/bare", SG_OBJECT_RANGE_BARE) + rough;
double tile_min_expiry = fgGetDouble("/sim/rendering/plod-minimum-expiry-time-secs", SG_TILE_MIN_EXPIRY);
_use_vpb = fgGetBool("/scenery/use-vpb");
_options->setPluginStringData("SimGear::LOD_RANGE_BARE", std::to_string(bare));
_options->setPluginStringData("SimGear::LOD_RANGE_ROUGH", std::to_string(rough));
@ -275,13 +277,12 @@ void FGTileMgr::materialLibChanged()
bool FGTileMgr::sched_tile( const SGBucket& b, double priority, bool current_view, double duration)
{
// see if tile already exists in the cache
TileEntry *t = tile_cache.get_tile( b );
STGTileEntry *t = tile_cache.get_stg_tile( b );
if (!t)
{
// create a new entry
t = new TileEntry( b );
SG_LOG( SG_TERRAIN, SG_INFO, "sched_tile: new tile entry for:" << b );
t = new STGTileEntry( b );
SG_LOG( SG_TERRAIN, SG_INFO, "sched_tile: new STG tile entry for:" << b );
// insert the tile into the cache, update will generate load request
if ( tile_cache.insert_tile( t ) )
@ -303,6 +304,36 @@ bool FGTileMgr::sched_tile( const SGBucket& b, double priority, bool current_vie
// update tile's properties
tile_cache.request_tile(t,priority,current_view,duration);
if (_use_vpb) {
VPBTileEntry *v = tile_cache.get_vpb_tile( b );
if (!v)
{
// create a new entry
v = new VPBTileEntry( b );
SG_LOG( SG_TERRAIN, SG_INFO, "sched_tile: new VPB tile entry for:" << b );
// insert the tile into the cache, update will generate load request
if ( tile_cache.insert_tile( v ) )
{
// Attach to scene graph
v->addToSceneGraph(globals->get_scenery()->get_terrain_branch());
} else {
// insert failed (cache full with no available entries to
// delete.) Try again later
delete v;
return false;
}
SG_LOG( SG_TERRAIN, SG_DEBUG, " New tile cache size " << (int)tile_cache.get_size() );
}
// update tile's properties. We ensure VPB tiles have maximum priority - priority is calcualated as
// _negative_ the square of the distance from the viewer to the tile.
// so by multiplying by 0.1 we increase the number towards 0.
tile_cache.request_tile(v,priority * 0.1,current_view,duration);
}
return t->is_loaded();
}

View file

@ -91,6 +91,7 @@ private:
/// is caching of expired tiles enabled or not?
bool _enableCache;
bool _use_vpb;
public:
FGTileMgr();
~FGTileMgr();