1
0
Fork 0

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:
curt 1999-06-13 05:58:02 +00:00
parent 392e8c09c8
commit 2c6db0ec35
9 changed files with 280 additions and 122 deletions

View file

@ -354,8 +354,14 @@ void GLUTspecialkey(int k, int x, int y) {
if( (toggle_pause = !t->getPause()) ) if( (toggle_pause = !t->getPause()) )
t->togglePauseMode(); t->togglePauseMode();
BusyCursor(0); BusyCursor(0);
fgTileMgrInit(); if( global_tile_mgr.init() ) {
fgTileMgrUpdate(); // 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); BusyCursor(1);
if(toggle_pause) if(toggle_pause)
t->togglePauseMode(); t->togglePauseMode();

View file

@ -360,7 +360,7 @@ static void fgRenderFrame( void ) {
// xglMaterialfv (GL_FRONT, GL_DIFFUSE, white); // xglMaterialfv (GL_FRONT, GL_DIFFUSE, white);
} }
fgTileMgrRender(); global_tile_mgr.render();
xglDisable( GL_TEXTURE_2D ); xglDisable( GL_TEXTURE_2D );
xglDisable( GL_FOG ); xglDisable( GL_FOG );
@ -587,7 +587,7 @@ static void fgMainLoop( void ) {
#endif #endif
// see if we need to load any new scenery tiles // see if we need to load any new scenery tiles
fgTileMgrUpdate(); global_tile_mgr.update();
// Process/manage pending events // Process/manage pending events
global_events.Process(); global_events.Process();

View file

@ -205,9 +205,9 @@ int fgInitSubsystems( void )
exit(-1); exit(-1);
} }
if( fgTileMgrInit() ) { if( global_tile_mgr.init() ) {
// Load the local scenery data // Load the local scenery data
fgTileMgrUpdate(); global_tile_mgr.update();
} else { } else {
FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" ); FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
exit(-1); exit(-1);
@ -438,9 +438,9 @@ void fgReInitSubsystems( void )
t->togglePauseMode(); t->togglePauseMode();
fgInitPosition(); fgInitPosition();
if( fgTileMgrInit() ) { if( global_tile_mgr.init() ) {
// Load the local scenery data // Load the local scenery data
fgTileMgrUpdate(); global_tile_mgr.update();
} else { } else {
FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" ); FG_LOG( FG_GENERAL, FG_ALERT, "Error in Tile Manager initialization!" );
exit(-1); exit(-1);

View file

@ -78,7 +78,7 @@ FGTileCache::init( void )
<< sizeof( e ) ); << sizeof( e ) );
if ( target_cache_size > (int)tile_cache.size() ) { if ( target_cache_size > (int)tile_cache.size() ) {
// FGTileEntry e; // FGTileEntry e;
e.used = false; e.mark_unused();
int expansion_amt = target_cache_size - (int)tile_cache.size(); int expansion_amt = target_cache_size - (int)tile_cache.size();
for ( i = 0; i < expansion_amt; ++i ) { for ( i = 0; i < expansion_amt; ++i ) {
tile_cache.push_back( e ); tile_cache.push_back( e );
@ -90,10 +90,10 @@ FGTileCache::init( void )
<< tile_cache.size() ); << tile_cache.size() );
for ( i = 0; i < (int)tile_cache.size(); i++ ) { for ( i = 0; i < (int)tile_cache.size(); i++ ) {
if ( tile_cache[i].used ) { if ( !tile_cache[i].is_unused() ) {
entry_free(i); entry_free(i);
} }
tile_cache[i].used = false; tile_cache[i].mark_unused();
tile_cache[i].tile_bucket.make_bad(); tile_cache[i].tile_bucket.make_bad();
} }
FG_LOG( FG_TERRAIN, FG_DEBUG, " done with init()" ); 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 // Fill in a tile cache entry with real data for the specified bucket
void 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 // Load the appropriate data file and build tile fragment list
FGPath tile_path( current_options.get_fg_root() ); 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_base_path() );
tile_path.append( p.gen_index_str() ); tile_path.append( p.gen_index_str() );
tile_cache[index].used = true; tile_cache[index].mark_loaded();
tile_cache[index].tile_bucket = p; tile_cache[index].tile_bucket = p;
fgObjLoad( tile_path.str(), &tile_cache[index] ); fgObjLoad( tile_path.str(), &tile_cache[index] );
// tile_cache[ index ].ObjLoad( tile_path, p ); // tile_cache[ index ].ObjLoad( tile_path, p );
@ -169,7 +169,7 @@ FGTileCache::next_avail( void )
max_index = 0; max_index = 0;
for ( i = 0; i < (int)tile_cache.size(); i++ ) { for ( i = 0; i < (int)tile_cache.size(); i++ ) {
if ( ! tile_cache[i].used ) { if ( tile_cache[i].is_unused() ) {
return(i); return(i);
} else { } else {
// calculate approximate distance from view point // calculate approximate distance from view point

View file

@ -75,7 +75,7 @@ public:
void entry_free( int index ); void entry_free( int index );
// Fill in a tile cache entry with real data for the specified bucket // 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 // Return a pointer to the specified tile cache entry
FGTileEntry *get_tile( int index ) { FGTileEntry *get_tile( int index ) {

View file

@ -42,7 +42,7 @@ FG_USING_STD(mem_fun_ref);
// Constructor // Constructor
FGTileEntry::FGTileEntry ( void ) FGTileEntry::FGTileEntry ( void )
: ncount(0), : ncount(0),
used(false) state(Unused)
{ {
nodes.clear(); nodes.clear();
} }
@ -65,7 +65,7 @@ FGTileEntry::release_fragments()
for_each( begin(), end(), for_each( begin(), end(),
mem_fun_ref( &fgFRAGMENT::deleteDisplayList )); mem_fun_ref( &fgFRAGMENT::deleteDisplayList ));
fragment_list.erase( begin(), end() ); fragment_list.erase( begin(), end() );
used = false; mark_unused();
} }

View file

@ -68,6 +68,15 @@ typedef point_list::const_iterator const_point_list_iterator;
// Scenery tile class // Scenery tile class
class FGTileEntry { class FGTileEntry {
private:
// Tile state
enum tile_state {
Unused = 0,
Scheduled = 1,
Loaded = 2
};
public: public:
typedef vector < fgFRAGMENT > container; typedef vector < fgFRAGMENT > container;
@ -91,7 +100,7 @@ public:
FGBucket tile_bucket; FGBucket tile_bucket;
// the tile cache will mark here if the tile is being used // the tile cache will mark here if the tile is being used
bool used; tile_state state;
container fragment_list; container fragment_list;
@ -156,6 +165,12 @@ public:
// so m[15] is unchanged // 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; }
}; };

View file

@ -61,34 +61,24 @@
#endif #endif
#define FG_LOCAL_X_Y 81 // max(o->tile_diameter) ** 2 // the tile manager
FGTileMgr global_tile_mgr;
#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
// Tile loading state // Constructor
enum fgTileLoadState { FGTileMgr::FGTileMgr ( void ):
START = 0, state( Start )
INITED = 1, {
RUNNING = 2 }
};
// closest (potentially viewable) tiles, centered on current tile. // Destructor
// This is an array of pointers to cache indexes. FGTileMgr::~FGTileMgr ( void ) {
int tiles[FG_LOCAL_X_Y]; }
static fgTileLoadState state = START;
// Initialize the Tile Manager subsystem // Initialize the Tile Manager subsystem
int fgTileMgrInit( void ) { int FGTileMgr::init( void ) {
FG_LOG( FG_TERRAIN, FG_INFO, "Initializing Tile Manager subsystem." ); FG_LOG( FG_TERRAIN, FG_INFO, "Initializing Tile Manager subsystem." );
// load default material library // load default material library
@ -96,28 +86,39 @@ int fgTileMgrInit( void ) {
material_mgr.load_lib(); material_mgr.load_lib();
} }
state = INITED; state = Inited;
return 1; return 1;
} }
// load a tile // schedule a tile for loading
void fgTileMgrLoadTile( FGBucket& p, int *index) { void FGTileMgr::sched_tile( const FGBucket& b, int *index ) {
FGTileCache *c; // see if tile already exists in the cache
*index = global_tile_cache.exists( b );
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);
if ( *index < 0 ) { if ( *index < 0 ) {
*index = c->next_avail(); // find the next availabel cache entry and mark it as scheduled
c->fill_in(*index, p); *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. // explicitely. lat & lon are in radians. abs_view_pos in meters.
// Returns result in meters. // Returns result in meters.
double double
fgTileMgrCurElevNEW( const FGBucket& p ) { FGTileMgr::current_elev_new( const FGBucket& p ) {
FGTileEntry *t; FGTileEntry *t;
fgFRAGMENT *frag_ptr; fgFRAGMENT *frag_ptr;
Point3D abs_view_pos = current_view.get_abs_view_pos(); 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. // explicitely. lat & lon are in radians. abs_view_pos in meters.
// Returns result in meters. // Returns result in meters.
double 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; FGTileCache *c;
FGTileEntry *t; FGTileEntry *t;
fgFRAGMENT *frag_ptr; 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 // 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. // the chunk isn't already in the cache, then read it from disk.
int fgTileMgrUpdate( void ) { int FGTileMgr::update( void ) {
FGTileCache *c; FGTileCache *c;
FGInterface *f; FGInterface *f;
FGBucket p2; FGBucket p2;
@ -361,11 +362,11 @@ int fgTileMgrUpdate( void ) {
dw = tile_diameter / 2; dw = tile_diameter / 2;
dh = tile_diameter / 2; dh = tile_diameter / 2;
if ( (p1 == p_last) && (state == RUNNING) ) { if ( (p1 == p_last) && (state == Running) ) {
// same bucket as last time // same bucket as last time
FG_LOG( FG_TERRAIN, FG_DEBUG, "Same bucket as last time" ); FG_LOG( FG_TERRAIN, FG_DEBUG, "Same bucket as last time" );
} else if ( (state == START) || (state == INITED) ) { } else if ( (state == Start) || (state == Inited) ) {
state = RUNNING; state = Running;
// First time through or we have teleporte, initialize the // First time through or we have teleporte, initialize the
// system and load all relavant tiles // system and load all relavant tiles
@ -380,16 +381,72 @@ int fgTileMgrUpdate( void ) {
c->init(); c->init();
p_last.make_bad(); p_last.make_bad();
// build the local area list and update cache // build the local area list and schedule tiles for loading
for ( j = 0; j < tile_diameter; j++ ) {
// 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++ ) { for ( i = 0; i < tile_diameter; i++ ) {
// fgBucketOffset(&p1, &p2, i - dw, j - dh); // fgBucketOffset(&p1, &p2, i - dw, j - dh);
p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG, p2 = fgBucketOffset( f->get_Longitude() * RAD_TO_DEG,
f->get_Latitude() * RAD_TO_DEG, f->get_Latitude() * RAD_TO_DEG,
i - dw, j -dh ); 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 { } else {
// We've moved to a new bucket, we need to scroll our // We've moved to a new bucket, we need to scroll our
// structures, and load in the new tiles // structures, and load in the new tiles
@ -413,7 +470,7 @@ int fgTileMgrUpdate( void ) {
// load in new column // load in new column
// fgBucketOffset(&p_last, &p2, dw + 1, j - dh); // fgBucketOffset(&p_last, &p2, dw + 1, j - dh);
p2 = fgBucketOffset( last_lon, last_lat, 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]); tile_diameter - 1]);
} }
} else if ( (p1.get_lon() < p_last.get_lon()) || } else if ( (p1.get_lon() < p_last.get_lon()) ||
@ -429,7 +486,7 @@ int fgTileMgrUpdate( void ) {
// load in new column // load in new column
// fgBucketOffset(&p_last, &p2, -dw - 1, j - dh); // fgBucketOffset(&p_last, &p2, -dw - 1, j - dh);
p2 = fgBucketOffset( last_lon, last_lat, -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 // load in new column
// fgBucketOffset(&p_last, &p2, i - dw, dh + 1); // fgBucketOffset(&p_last, &p2, i - dw, dh + 1);
p2 = fgBucketOffset( last_lon, last_lat, 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]); tile_diameter) + i]);
} }
} else if ( (p1.get_lat() < p_last.get_lat()) || } else if ( (p1.get_lat() < p_last.get_lat()) ||
@ -462,18 +519,25 @@ int fgTileMgrUpdate( void ) {
// load in new column // load in new column
// fgBucketOffset(&p_last, &p2, i - dw, -dh - 1); // fgBucketOffset(&p_last, &p2, i - dw, -dh - 1);
p2 = fgBucketOffset( last_lon, last_lat, 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) // 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 geod_pos = Point3D( f->get_Longitude(), f->get_Latitude(), 0.0);
Point3D tmp_abs_view_pos = fgGeodToCart(geod_pos); Point3D tmp_abs_view_pos = fgGeodToCart(geod_pos);
scenery.cur_elev = scenery.cur_elev =
fgTileMgrCurElev( f->get_Longitude(), f->get_Latitude(), current_elev( f->get_Longitude(), f->get_Latitude(), tmp_abs_view_pos );
tmp_abs_view_pos );
p_last = p1; p_last = p1;
last_lon = f->get_Longitude() * RAD_TO_DEG; last_lon = f->get_Longitude() * RAD_TO_DEG;
@ -671,7 +735,7 @@ update_tile_geometry( FGTileEntry *t, GLdouble *MODEL_VIEW)
// Render the local tiles // Render the local tiles
void fgTileMgrRender( void ) { void FGTileMgr::render( void ) {
FGInterface *f; FGInterface *f;
FGTileCache *c; FGTileCache *c;
FGTileEntry *t; FGTileEntry *t;
@ -706,6 +770,8 @@ void fgTileMgrRender( void ) {
// fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index); // fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index);
t = c->get_tile(index); t = c->get_tile(index);
if ( t->is_loaded() ) {
// calculate tile offset // calculate tile offset
t->SetOffset( scenery.center ); t->SetOffset( scenery.center );
@ -731,8 +797,12 @@ void fgTileMgrRender( void ) {
// Fine (fragment based) culling // Fine (fragment based) culling
frag_offset = frag_ptr->center - scenery.center; frag_offset = frag_ptr->center - scenery.center;
if ( viewable(frag_offset, frag_ptr->bounding_radius*2) ) { if ( viewable(frag_offset,
// add to transient per-material property fragment list 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.x = t->offset.x;
// frag_ptr->tile_offset.y = t->offset.y; // frag_ptr->tile_offset.y = t->offset.y;
// frag_ptr->tile_offset.z = t->offset.z; // frag_ptr->tile_offset.z = t->offset.z;
@ -749,7 +819,8 @@ void fgTileMgrRender( void ) {
} else { } else {
// printf("Culled a fragment %.2f %.2f %.2f %.2f\n", // printf("Culled a fragment %.2f %.2f %.2f %.2f\n",
// frag_ptr->center.x, frag_ptr->center.y, // 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++; culled++;
} }
} }
@ -759,6 +830,9 @@ void fgTileMgrRender( void ) {
} else { } else {
culled += t->fragment_list.size(); culled += t->fragment_list.size();
} }
} else {
FG_LOG( FG_TERRAIN, FG_DEBUG, "Skipping a not yet loaded tile" );
}
} }
if ( (drawn + culled) > 0 ) { if ( (drawn + culled) > 0 ) {

View file

@ -29,29 +29,92 @@
# error This library requires C++ # error This library requires C++
#endif #endif
#include <Include/compiler.h>
#include <list>
#include <Bucket/newbucket.hxx> #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 // Initialize the Tile Manager subsystem
int fgTileMgrInit( 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 fgTileMgrUpdate( 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 // Determine scenery altitude. Normally this just happens when we
// render the scene, but we'd also like to be able to do this // 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. // explicitely. lat & lon are in radians. abs_view_pos in
// Returns result in meters. // meters. Returns result in meters.
double fgTileMgrCurElevNEW( const FGBucket& p ); double current_elev_new( const FGBucket& p );
double fgTileMgrCurElev( double lon, double lat, const Point3D& abs_view_pos ); double current_elev( double lon, double lat, const Point3D& abs_view_pos );
// Render the local tiles --- hack, hack, hack // Render the local tiles --- hack, hack, hack
void fgTileMgrRender( void ); void render( void );
};
// the tile manager
extern FGTileMgr global_tile_mgr;
#endif // _TILEMGR_HXX #endif // _TILEMGR_HXX