Created an FGTileMgr class to encapsulate the high level tile management
tasks. Created a tile load queue. When we init, or cross a tile boundary, we stuff the new tiles to be loaded on a load queue, and then only load one tile per frame. This will need further refinement, but it is better than what we had.
This commit is contained in:
parent
392e8c09c8
commit
2c6db0ec35
9 changed files with 280 additions and 122 deletions
|
@ -354,8 +354,14 @@ void GLUTspecialkey(int k, int x, int y) {
|
|||
if( (toggle_pause = !t->getPause()) )
|
||||
t->togglePauseMode();
|
||||
BusyCursor(0);
|
||||
fgTileMgrInit();
|
||||
fgTileMgrUpdate();
|
||||
if( global_tile_mgr.init() ) {
|
||||
// Load the local scenery data
|
||||
global_tile_mgr.update();
|
||||
} else {
|
||||
FG_LOG( FG_GENERAL, FG_ALERT,
|
||||
"Error in Tile Manager initialization!" );
|
||||
exit(-1);
|
||||
}
|
||||
BusyCursor(1);
|
||||
if(toggle_pause)
|
||||
t->togglePauseMode();
|
||||
|
|
|
@ -360,7 +360,7 @@ static void fgRenderFrame( void ) {
|
|||
// xglMaterialfv (GL_FRONT, GL_DIFFUSE, white);
|
||||
}
|
||||
|
||||
fgTileMgrRender();
|
||||
global_tile_mgr.render();
|
||||
|
||||
xglDisable( GL_TEXTURE_2D );
|
||||
xglDisable( GL_FOG );
|
||||
|
@ -587,7 +587,7 @@ static void fgMainLoop( void ) {
|
|||
#endif
|
||||
|
||||
// see if we need to load any new scenery tiles
|
||||
fgTileMgrUpdate();
|
||||
global_tile_mgr.update();
|
||||
|
||||
// Process/manage pending events
|
||||
global_events.Process();
|
||||
|
|
|
@ -205,9 +205,9 @@ int fgInitSubsystems( void )
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
if( fgTileMgrInit() ) {
|
||||
if( global_tile_mgr.init() ) {
|
||||
// Load the local scenery data
|
||||
fgTileMgrUpdate();
|
||||
global_tile_mgr.update();
|
||||
} else {
|
||||
FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
|
||||
exit(-1);
|
||||
|
@ -438,9 +438,9 @@ void fgReInitSubsystems( void )
|
|||
t->togglePauseMode();
|
||||
|
||||
fgInitPosition();
|
||||
if( fgTileMgrInit() ) {
|
||||
if( global_tile_mgr.init() ) {
|
||||
// Load the local scenery data
|
||||
fgTileMgrUpdate();
|
||||
global_tile_mgr.update();
|
||||
} else {
|
||||
FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
|
||||
exit(-1);
|
||||
|
|
|
@ -78,7 +78,7 @@ FGTileCache::init( void )
|
|||
<< sizeof( e ) );
|
||||
if ( target_cache_size > (int)tile_cache.size() ) {
|
||||
// FGTileEntry e;
|
||||
e.used = false;
|
||||
e.mark_unused();
|
||||
int expansion_amt = target_cache_size - (int)tile_cache.size();
|
||||
for ( i = 0; i < expansion_amt; ++i ) {
|
||||
tile_cache.push_back( e );
|
||||
|
@ -90,10 +90,10 @@ FGTileCache::init( void )
|
|||
<< tile_cache.size() );
|
||||
|
||||
for ( i = 0; i < (int)tile_cache.size(); i++ ) {
|
||||
if ( tile_cache[i].used ) {
|
||||
if ( !tile_cache[i].is_unused() ) {
|
||||
entry_free(i);
|
||||
}
|
||||
tile_cache[i].used = false;
|
||||
tile_cache[i].mark_unused();
|
||||
tile_cache[i].tile_bucket.make_bad();
|
||||
}
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, " done with init()" );
|
||||
|
@ -120,7 +120,7 @@ FGTileCache::exists( const FGBucket& p )
|
|||
|
||||
// Fill in a tile cache entry with real data for the specified bucket
|
||||
void
|
||||
FGTileCache::fill_in( int index, FGBucket& p )
|
||||
FGTileCache::fill_in( int index, const FGBucket& p )
|
||||
{
|
||||
// Load the appropriate data file and build tile fragment list
|
||||
FGPath tile_path( current_options.get_fg_root() );
|
||||
|
@ -128,7 +128,7 @@ FGTileCache::fill_in( int index, FGBucket& p )
|
|||
tile_path.append( p.gen_base_path() );
|
||||
tile_path.append( p.gen_index_str() );
|
||||
|
||||
tile_cache[index].used = true;
|
||||
tile_cache[index].mark_loaded();
|
||||
tile_cache[index].tile_bucket = p;
|
||||
fgObjLoad( tile_path.str(), &tile_cache[index] );
|
||||
// tile_cache[ index ].ObjLoad( tile_path, p );
|
||||
|
@ -169,7 +169,7 @@ FGTileCache::next_avail( void )
|
|||
max_index = 0;
|
||||
|
||||
for ( i = 0; i < (int)tile_cache.size(); i++ ) {
|
||||
if ( ! tile_cache[i].used ) {
|
||||
if ( tile_cache[i].is_unused() ) {
|
||||
return(i);
|
||||
} else {
|
||||
// calculate approximate distance from view point
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void entry_free( int index );
|
||||
|
||||
// Fill in a tile cache entry with real data for the specified bucket
|
||||
void fill_in( int index, FGBucket& p );
|
||||
void fill_in( int index, const FGBucket& p );
|
||||
|
||||
// Return a pointer to the specified tile cache entry
|
||||
FGTileEntry *get_tile( int index ) {
|
||||
|
|
|
@ -42,7 +42,7 @@ FG_USING_STD(mem_fun_ref);
|
|||
// Constructor
|
||||
FGTileEntry::FGTileEntry ( void )
|
||||
: ncount(0),
|
||||
used(false)
|
||||
state(Unused)
|
||||
{
|
||||
nodes.clear();
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ FGTileEntry::release_fragments()
|
|||
for_each( begin(), end(),
|
||||
mem_fun_ref( &fgFRAGMENT::deleteDisplayList ));
|
||||
fragment_list.erase( begin(), end() );
|
||||
used = false;
|
||||
mark_unused();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -68,6 +68,15 @@ typedef point_list::const_iterator const_point_list_iterator;
|
|||
// Scenery tile class
|
||||
class FGTileEntry {
|
||||
|
||||
private:
|
||||
|
||||
// Tile state
|
||||
enum tile_state {
|
||||
Unused = 0,
|
||||
Scheduled = 1,
|
||||
Loaded = 2
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
typedef vector < fgFRAGMENT > container;
|
||||
|
@ -91,7 +100,7 @@ public:
|
|||
FGBucket tile_bucket;
|
||||
|
||||
// the tile cache will mark here if the tile is being used
|
||||
bool used;
|
||||
tile_state state;
|
||||
|
||||
container fragment_list;
|
||||
|
||||
|
@ -156,6 +165,12 @@ public:
|
|||
// so m[15] is unchanged
|
||||
}
|
||||
|
||||
inline bool is_unused() const { return state == Unused; }
|
||||
inline bool is_loaded() const { return state == Loaded; }
|
||||
|
||||
inline void mark_unused() { state = Unused; }
|
||||
inline void mark_scheduled() { state = Scheduled; }
|
||||
inline void mark_loaded() { state = Loaded; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -61,34 +61,24 @@
|
|||
#endif
|
||||
|
||||
|
||||
#define FG_LOCAL_X_Y 81 // max(o->tile_diameter) ** 2
|
||||
|
||||
#define FG_SQUARE( X ) ( (X) * (X) )
|
||||
|
||||
#if defined(USE_MEM) || defined(WIN32)
|
||||
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
#else
|
||||
# define FG_MEM_COPY(to,from,n) bcopy(from, to, n)
|
||||
#endif
|
||||
// the tile manager
|
||||
FGTileMgr global_tile_mgr;
|
||||
|
||||
|
||||
// Tile loading state
|
||||
enum fgTileLoadState {
|
||||
START = 0,
|
||||
INITED = 1,
|
||||
RUNNING = 2
|
||||
};
|
||||
// Constructor
|
||||
FGTileMgr::FGTileMgr ( void ):
|
||||
state( Start )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// closest (potentially viewable) tiles, centered on current tile.
|
||||
// This is an array of pointers to cache indexes.
|
||||
int tiles[FG_LOCAL_X_Y];
|
||||
|
||||
static fgTileLoadState state = START;
|
||||
// Destructor
|
||||
FGTileMgr::~FGTileMgr ( void ) {
|
||||
}
|
||||
|
||||
|
||||
// Initialize the Tile Manager subsystem
|
||||
int fgTileMgrInit( void ) {
|
||||
int FGTileMgr::init( void ) {
|
||||
FG_LOG( FG_TERRAIN, FG_INFO, "Initializing Tile Manager subsystem." );
|
||||
|
||||
// load default material library
|
||||
|
@ -96,28 +86,39 @@ int fgTileMgrInit( void ) {
|
|||
material_mgr.load_lib();
|
||||
}
|
||||
|
||||
state = INITED;
|
||||
state = Inited;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// load a tile
|
||||
void fgTileMgrLoadTile( FGBucket& p, int *index) {
|
||||
FGTileCache *c;
|
||||
|
||||
c = &global_tile_cache;
|
||||
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Updating for bucket " << p );
|
||||
|
||||
// if not in cache, load tile into the next available slot
|
||||
*index = c->exists(p);
|
||||
// schedule a tile for loading
|
||||
void FGTileMgr::sched_tile( const FGBucket& b, int *index ) {
|
||||
// see if tile already exists in the cache
|
||||
*index = global_tile_cache.exists( b );
|
||||
if ( *index < 0 ) {
|
||||
*index = c->next_avail();
|
||||
c->fill_in(*index, p);
|
||||
// find the next availabel cache entry and mark it as scheduled
|
||||
*index = global_tile_cache.next_avail();
|
||||
FGTileEntry *t = global_tile_cache.get_tile( *index );
|
||||
t->mark_scheduled();
|
||||
|
||||
// register a load request
|
||||
FGLoadRec request;
|
||||
request.b = b;
|
||||
request.index = *index;
|
||||
load_queue.push_back( request );
|
||||
}
|
||||
}
|
||||
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Selected cache index: " << *index );
|
||||
|
||||
// load a tile
|
||||
void FGTileMgr::load_tile( const FGBucket& b, int cache_index) {
|
||||
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Loading tile " << b );
|
||||
|
||||
global_tile_cache.fill_in(cache_index, b);
|
||||
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Loaded for cache index: " << cache_index );
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,7 +140,7 @@ static double point_line_dist_squared( const Point3D& tc, const Point3D& vp,
|
|||
// explicitely. lat & lon are in radians. abs_view_pos in meters.
|
||||
// Returns result in meters.
|
||||
double
|
||||
fgTileMgrCurElevNEW( const FGBucket& p ) {
|
||||
FGTileMgr::current_elev_new( const FGBucket& p ) {
|
||||
FGTileEntry *t;
|
||||
fgFRAGMENT *frag_ptr;
|
||||
Point3D abs_view_pos = current_view.get_abs_view_pos();
|
||||
|
@ -237,7 +238,7 @@ fgTileMgrCurElevNEW( const FGBucket& p ) {
|
|||
// explicitely. lat & lon are in radians. abs_view_pos in meters.
|
||||
// Returns result in meters.
|
||||
double
|
||||
fgTileMgrCurElev( double lon, double lat, const Point3D& abs_view_pos ) {
|
||||
FGTileMgr::current_elev( double lon, double lat, const Point3D& abs_view_pos ) {
|
||||
FGTileCache *c;
|
||||
FGTileEntry *t;
|
||||
fgFRAGMENT *frag_ptr;
|
||||
|
@ -341,7 +342,7 @@ fgTileMgrCurElev( double lon, double lat, const Point3D& abs_view_pos ) {
|
|||
|
||||
// given the current lon/lat, fill in the array of local chunks. If
|
||||
// the chunk isn't already in the cache, then read it from disk.
|
||||
int fgTileMgrUpdate( void ) {
|
||||
int FGTileMgr::update( void ) {
|
||||
FGTileCache *c;
|
||||
FGInterface *f;
|
||||
FGBucket p2;
|
||||
|
@ -361,11 +362,11 @@ int fgTileMgrUpdate( void ) {
|
|||
dw = tile_diameter / 2;
|
||||
dh = tile_diameter / 2;
|
||||
|
||||
if ( (p1 == p_last) && (state == RUNNING) ) {
|
||||
if ( (p1 == p_last) && (state == Running) ) {
|
||||
// same bucket as last time
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Same bucket as last time" );
|
||||
} else if ( (state == START) || (state == INITED) ) {
|
||||
state = RUNNING;
|
||||
} else if ( (state == Start) || (state == Inited) ) {
|
||||
state = Running;
|
||||
|
||||
// First time through or we have teleporte, initialize the
|
||||
// system and load all relavant tiles
|
||||
|
@ -380,16 +381,72 @@ int fgTileMgrUpdate( void ) {
|
|||
c->init();
|
||||
p_last.make_bad();
|
||||
|
||||
// build the local area list and update cache
|
||||
for ( j = 0; j < tile_diameter; j++ ) {
|
||||
// build the local area list and schedule tiles for loading
|
||||
|
||||
// start with the center tile and work out in concentric
|
||||
// "rings"
|
||||
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
0, 0 );
|
||||
sched_tile( p2, &tiles[(dh*tile_diameter) + dw]);
|
||||
|
||||
for ( i = 3; i <= tile_diameter; i = i + 2 ) {
|
||||
int span = i / 2;
|
||||
|
||||
// bottom row
|
||||
for ( j = -span; j <= span; ++j ) {
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
j, -span );
|
||||
sched_tile( p2, &tiles[((dh-span)*tile_diameter) + dw+j]);
|
||||
}
|
||||
|
||||
// top row
|
||||
for ( j = -span; j <= span; ++j ) {
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
j, span );
|
||||
sched_tile( p2, &tiles[((dh+span)*tile_diameter) + dw+j]);
|
||||
}
|
||||
|
||||
// middle rows
|
||||
for ( j = -span + 1; j <= span - 1; ++j ) {
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
-span, j );
|
||||
sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw-span]);
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
span, j );
|
||||
sched_tile( p2, &tiles[((dh+j)*tile_diameter) + dw+span]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* for ( j = 0; j < tile_diameter; j++ ) {
|
||||
for ( i = 0; i < tile_diameter; i++ ) {
|
||||
// fgBucketOffset(&p1, &p2, i - dw, j - dh);
|
||||
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
|
||||
f->get_Latitude() * RAD_TO_DEG,
|
||||
i - dw, j -dh );
|
||||
fgTileMgrLoadTile( p2, &tiles[(j*tile_diameter) + i]);
|
||||
sched_tile( p2, &tiles[(j*tile_diameter) + i]);
|
||||
}
|
||||
} */
|
||||
|
||||
// Now force a load of the center tile and inner ring so we
|
||||
// have something to see in our first frame.
|
||||
for ( i = 0; i < 9; ++i ) {
|
||||
if ( load_queue.size() ) {
|
||||
FG_LOG( FG_TERRAIN, FG_INFO,
|
||||
"Load queue not empty, loading a tile" );
|
||||
|
||||
FGLoadRec pending = load_queue.front();
|
||||
load_queue.pop_front();
|
||||
load_tile( pending.b, pending.index );
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// We've moved to a new bucket, we need to scroll our
|
||||
// structures, and load in the new tiles
|
||||
|
@ -413,7 +470,7 @@ int fgTileMgrUpdate( void ) {
|
|||
// load in new column
|
||||
// fgBucketOffset(&p_last, &p2, dw + 1, j - dh);
|
||||
p2 = fgBucketOffset( last_lon, last_lat, dw + 1, j - dh );
|
||||
fgTileMgrLoadTile( p2, &tiles[(j*tile_diameter) +
|
||||
sched_tile( p2, &tiles[(j*tile_diameter) +
|
||||
tile_diameter - 1]);
|
||||
}
|
||||
} else if ( (p1.get_lon() < p_last.get_lon()) ||
|
||||
|
@ -429,7 +486,7 @@ int fgTileMgrUpdate( void ) {
|
|||
// load in new column
|
||||
// fgBucketOffset(&p_last, &p2, -dw - 1, j - dh);
|
||||
p2 = fgBucketOffset( last_lon, last_lat, -dw - 1, j - dh );
|
||||
fgTileMgrLoadTile( p2, &tiles[(j*tile_diameter) + 0]);
|
||||
sched_tile( p2, &tiles[(j*tile_diameter) + 0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,7 +503,7 @@ int fgTileMgrUpdate( void ) {
|
|||
// load in new column
|
||||
// fgBucketOffset(&p_last, &p2, i - dw, dh + 1);
|
||||
p2 = fgBucketOffset( last_lon, last_lat, i - dw, dh + 1);
|
||||
fgTileMgrLoadTile( p2, &tiles[((tile_diameter-1) *
|
||||
sched_tile( p2, &tiles[((tile_diameter-1) *
|
||||
tile_diameter) + i]);
|
||||
}
|
||||
} else if ( (p1.get_lat() < p_last.get_lat()) ||
|
||||
|
@ -462,18 +519,25 @@ int fgTileMgrUpdate( void ) {
|
|||
// load in new column
|
||||
// fgBucketOffset(&p_last, &p2, i - dw, -dh - 1);
|
||||
p2 = fgBucketOffset( last_lon, last_lat, i - dw, -dh - 1);
|
||||
fgTileMgrLoadTile( p2, &tiles[0 + i]);
|
||||
sched_tile( p2, &tiles[0 + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( load_queue.size() ) {
|
||||
FG_LOG( FG_TERRAIN, FG_INFO, "Load queue not empty, loading a tile" );
|
||||
|
||||
FGLoadRec pending = load_queue.front();
|
||||
load_queue.pop_front();
|
||||
load_tile( pending.b, pending.index );
|
||||
}
|
||||
|
||||
// find our current elevation (feed in the current bucket to save work)
|
||||
Point3D geod_pos = Point3D( f->get_Longitude(), f->get_Latitude(), 0.0);
|
||||
Point3D tmp_abs_view_pos = fgGeodToCart(geod_pos);
|
||||
|
||||
scenery.cur_elev =
|
||||
fgTileMgrCurElev( f->get_Longitude(), f->get_Latitude(),
|
||||
tmp_abs_view_pos );
|
||||
current_elev( f->get_Longitude(), f->get_Latitude(), tmp_abs_view_pos );
|
||||
|
||||
p_last = p1;
|
||||
last_lon = f->get_Longitude() * RAD_TO_DEG;
|
||||
|
@ -671,7 +735,7 @@ update_tile_geometry( FGTileEntry *t, GLdouble *MODEL_VIEW)
|
|||
|
||||
|
||||
// Render the local tiles
|
||||
void fgTileMgrRender( void ) {
|
||||
void FGTileMgr::render( void ) {
|
||||
FGInterface *f;
|
||||
FGTileCache *c;
|
||||
FGTileEntry *t;
|
||||
|
@ -706,6 +770,8 @@ void fgTileMgrRender( void ) {
|
|||
// fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index);
|
||||
t = c->get_tile(index);
|
||||
|
||||
if ( t->is_loaded() ) {
|
||||
|
||||
// calculate tile offset
|
||||
t->SetOffset( scenery.center );
|
||||
|
||||
|
@ -731,8 +797,12 @@ void fgTileMgrRender( void ) {
|
|||
// Fine (fragment based) culling
|
||||
frag_offset = frag_ptr->center - scenery.center;
|
||||
|
||||
if ( viewable(frag_offset, frag_ptr->bounding_radius*2) ) {
|
||||
// add to transient per-material property fragment list
|
||||
if ( viewable(frag_offset,
|
||||
frag_ptr->bounding_radius*2) )
|
||||
{
|
||||
// add to transient per-material property
|
||||
// fragment list
|
||||
|
||||
// frag_ptr->tile_offset.x = t->offset.x;
|
||||
// frag_ptr->tile_offset.y = t->offset.y;
|
||||
// frag_ptr->tile_offset.z = t->offset.z;
|
||||
|
@ -749,7 +819,8 @@ void fgTileMgrRender( void ) {
|
|||
} else {
|
||||
// printf("Culled a fragment %.2f %.2f %.2f %.2f\n",
|
||||
// frag_ptr->center.x, frag_ptr->center.y,
|
||||
// frag_ptr->center.z, frag_ptr->bounding_radius);
|
||||
// frag_ptr->center.z,
|
||||
// frag_ptr->bounding_radius);
|
||||
culled++;
|
||||
}
|
||||
}
|
||||
|
@ -759,6 +830,9 @@ void fgTileMgrRender( void ) {
|
|||
} else {
|
||||
culled += t->fragment_list.size();
|
||||
}
|
||||
} else {
|
||||
FG_LOG( FG_TERRAIN, FG_DEBUG, "Skipping a not yet loaded tile" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( (drawn + culled) > 0 ) {
|
||||
|
|
|
@ -29,29 +29,92 @@
|
|||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <Include/compiler.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <Bucket/newbucket.hxx>
|
||||
|
||||
|
||||
FG_USING_STD(list);
|
||||
|
||||
|
||||
#define FG_LOCAL_X_Y 81 // max(o->tile_diameter) ** 2
|
||||
|
||||
#define FG_SQUARE( X ) ( (X) * (X) )
|
||||
|
||||
#if defined(USE_MEM) || defined(WIN32)
|
||||
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
|
||||
#else
|
||||
# define FG_MEM_COPY(to,from,n) bcopy(from, to, n)
|
||||
#endif
|
||||
|
||||
|
||||
class FGLoadRec {
|
||||
|
||||
public:
|
||||
|
||||
FGBucket b;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
class FGTileMgr {
|
||||
|
||||
private:
|
||||
|
||||
// closest (potentially viewable) tiles, centered on current tile.
|
||||
// This is an array of pointers to cache indexes.
|
||||
int tiles[FG_LOCAL_X_Y];
|
||||
|
||||
// Tile loading state
|
||||
enum load_state {
|
||||
Start = 0,
|
||||
Inited = 1,
|
||||
Running = 2
|
||||
};
|
||||
|
||||
load_state state;
|
||||
|
||||
// pending tile load queue
|
||||
list < FGLoadRec > load_queue;
|
||||
|
||||
// schedule a tile for loading
|
||||
void sched_tile( const FGBucket& b, int *index );
|
||||
|
||||
// load a tile
|
||||
void load_tile( const FGBucket& b, int cache_index );
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
FGTileMgr ( void );
|
||||
|
||||
// Destructor
|
||||
~FGTileMgr ( void );
|
||||
|
||||
// Initialize the Tile Manager subsystem
|
||||
int fgTileMgrInit( void );
|
||||
|
||||
|
||||
// given the current lon/lat, fill in the array of local chunks. If
|
||||
// the chunk isn't already in the cache, then read it from disk.
|
||||
int fgTileMgrUpdate( void );
|
||||
int init( void );
|
||||
|
||||
// given the current lon/lat, fill in the array of local chunks.
|
||||
// If the chunk isn't already in the cache, then read it from
|
||||
// disk.
|
||||
int update( void );
|
||||
|
||||
// Determine scenery altitude. Normally this just happens when we
|
||||
// render the scene, but we'd also like to be able to do this
|
||||
// explicitely. lat & lon are in radians. abs_view_pos in meters.
|
||||
// Returns result in meters.
|
||||
double fgTileMgrCurElevNEW( const FGBucket& p );
|
||||
double fgTileMgrCurElev( double lon, double lat, const Point3D& abs_view_pos );
|
||||
|
||||
// explicitely. lat & lon are in radians. abs_view_pos in
|
||||
// meters. Returns result in meters.
|
||||
double current_elev_new( const FGBucket& p );
|
||||
double current_elev( double lon, double lat, const Point3D& abs_view_pos );
|
||||
|
||||
// Render the local tiles --- hack, hack, hack
|
||||
void fgTileMgrRender( void );
|
||||
void render( void );
|
||||
};
|
||||
|
||||
|
||||
// the tile manager
|
||||
extern FGTileMgr global_tile_mgr;
|
||||
|
||||
|
||||
#endif // _TILEMGR_HXX
|
||||
|
|
Loading…
Reference in a new issue