/* Define if lex declares yytext as a char * by default, not a char[]. */
#undef YYTEXT_POINTER
+/* Define to use tile loading threads */
+#undef ENABLE_THREADS
+
\f
/* Leave that blank line there!! Autoheader needs it.
If you're adding to this file, keep in mind:
virtual void unbind ();
virtual void update ();
virtual bool update( int multi_loop );
- virtual bool ToggleDataLogging(bool state) {};
- virtual bool ToggleDataLogging(void) {};
+ virtual bool ToggleDataLogging(bool state) { return false; }
+ virtual bool ToggleDataLogging(void) { return false; }
// Define the various supported flight models (many not yet implemented)
enum {
/* Define if the X Window System is missing or not being used. */
#undef X_DISPLAY_MISSING
+/* Define to use tile loading threads */
+#undef ENABLE_THREADS
+
/* Define if you have the GetLocalTime function. */
#undef HAVE_GETLOCALTIME
$(top_builddir)/src/Network/libNetwork.a
endif
+if WITH_THREADS
+THREAD_LIBS = -lsgthreads
+else
+THREAD_LIBS =
+endif
+
if OLD_AUTOMAKE
# nothing CXXFLAGS += -DPKGLIBDIR=\"$(pkglibdir)\"
else
-lsgroute -lsgsky -lsgephem -lsgtiming -lsgio -lsgscreen \
-lsgmath -lsgbucket -lsgdebug -lsgmagvar -lsgmisc -lsgxml \
$(SERIAL_LIBS) \
+ $(THREAD_LIBS) \
-lplibpu -lplibfnt -lplibssg -lplibsg \
-lmk4 -lz \
$(opengl_LIBS) \
cur_fdm_state->update( 0 );
FGSteam::update( 0 );
- if ( global_tile_mgr.queue_size() == 0 ) {
+ //if ( global_tile_mgr.queue_size() == 0 ) {
initial_freeze = false;
- }
+ //}
}
if ( fgGetString("/sim/view-mode") == "pilot" ) {
in >> m;
// build the ssgSimpleState
- SGPath tex_path( globals->get_fg_root() );
- tex_path.append( "Textures.high" );
+ SGPath tmp_path( globals->get_fg_root() );
+ tmp_path.append( "Textures.high" );
- SGPath tmp_path = tex_path;
- tmp_path.append( m.get_texture_name() );
- if ( ! local_file_exists(tmp_path.str())
+ SGPath tex_path = tmp_path;
+ tex_path.append( m.get_texture_name() );
+ if ( ! local_file_exists(tex_path.str())
|| general.get_glMaxTexSize() < 512 ) {
tex_path = SGPath( globals->get_fg_root() );
tex_path.append( "Textures" );
+ tex_path.append( m.get_texture_name() );
}
SG_LOG( SG_TERRAIN, SG_INFO, " Loading material "
shade_model = GL_FLAT;
}
- m.build_ssg_state( tex_path.str(), shade_model,
- fgGetBool("/sim/rendering/textures") );
+ m.set_texture_name( tex_path.str() );
+ m.build_ssg_state( shade_model,
+ fgGetBool("/sim/rendering/textures"),
+ false );
#if EXTRA_DEBUG
m.dump_info();
string tex_name = full_path.substr( pos + 1 );
string tex_path = full_path.substr( 0, pos );
- FGNewMat m( mat_name, tex_name );
+ FGNewMat m( mat_name, full_path );
SG_LOG( SG_TERRAIN, SG_INFO, " Loading material "
- << mat_name << " (" << tex_path << ")");
+ << mat_name << " (" << full_path << ")");
#if EXTRA_DEBUG
m.dump_info();
shade_model = GL_FLAT;
}
- m.build_ssg_state( tex_path, shade_model,
- fgGetBool("/sim/rendering/textures") );
+ m.build_ssg_state( shade_model, fgGetBool("/sim/rendering/textures"),
+ true );
material_lib.matlib[mat_name] = m;
}
-void FGNewMat::build_ssg_state( const string& path,
- GLenum shade_model, bool texture_default )
+void FGNewMat::build_ssg_state( GLenum shade_model, bool texture_default,
+ bool defer_tex_load )
{
- SGPath tex_file( path );
- tex_file.append( texture_name );
-
state = new ssgStateSelector(2);
state->ref();
textured->enable( GL_TEXTURE_2D );
textured->disable( GL_BLEND );
textured->disable( GL_ALPHA_TEST );
- textured->setTexture( (char *)tex_file.c_str(), wrapu, wrapv );
+ if ( !defer_tex_load ) {
+ textured->setTexture( (char *)texture_name.c_str(), wrapu, wrapv );
+ texture_loaded = true;
+ } else {
+ texture_loaded = false;
+ }
// cout << "wrap u = " << wrapu << " wrapv = " << wrapv << endl;
textured->enable( GL_COLOR_MATERIAL );
textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
// material properties
sgVec4 ambient, diffuse, specular, emission;
+ // true if texture loading deferred, and not yet loaded
+ bool texture_loaded;
+
public:
// Constructor
friend istream& operator >> ( istream& in, FGNewMat& m );
// void load_texture( const string& root );
- void build_ssg_state( const string& path,
- GLenum shade_model, bool texture_default );
+ void build_ssg_state( GLenum shade_model, bool texture_default,
+ bool defer_tex_load = false );
void set_ssg_state( ssgSimpleState *s );
inline string get_material_name() const { return material_name; }
--- /dev/null
+// FGTileLoader - Queue scenery tiles for loading.
+//
+// Written by Bernie Bright, started March 2001.
+//
+// Copyright (C) 2001 Bernard Bright - bbright@bigpond.net.au
+//
+// 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
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Main/globals.hxx>
+#include "FGTileLoader.hxx"
+#include "tileentry.hxx"
+
+/**
+ *
+ */
+FGTileLoader::FGTileLoader()
+{
+#ifdef ENABLE_THREADS
+ // Create and start the loader threads.
+ for (int i = 0; i < MAX_THREADS; ++i)
+ {
+ threads[i] = new LoaderThread(this);
+ threads[i]->start();
+ }
+#endif // ENABLE_THREADS
+}
+
+/**
+ * Terminate all threads.
+ */
+FGTileLoader::~FGTileLoader()
+{
+#ifdef ENABLE_THREADS
+ // Wake up its time to die.
+ cond.broadcast();
+
+ for (int i = 0; i < MAX_THREADS; ++i)
+ {
+ threads[i]->cancel();
+ threads[i]->join();
+ }
+#endif // ENABLE_THREADS
+}
+
+/**
+ *
+ */
+void
+FGTileLoader::add( FGTileEntry* tile )
+{
+ /**
+ * Initialise tile_path here and not in ctor to avoid problems
+ * with the initialastion order of global objects.
+ */
+ static bool beenhere = false;
+ if (!beenhere)
+ {
+ if ( globals->get_fg_scenery() != (string)"" ) {
+ tile_path.set( globals->get_fg_scenery() );
+ } else {
+ tile_path.set( globals->get_fg_root() );
+ tile_path.append( "Scenery" );
+ }
+ beenhere = true;
+ }
+
+#ifdef ENABLE_THREADS
+ mutex.lock();
+ tile_queue.push( tile );
+ // Signal waiting working threads.
+ cond.signal();
+ mutex.unlock();
+#else
+ tile->load( tile_path, true );
+#endif // ENABLE_THREADS
+}
+
+#ifdef ENABLE_THREADS
+/**
+ *
+ */
+void
+FGTileLoader::LoaderThread::run()
+{
+ pthread_cleanup_push( cleanup_handler, loader );
+ while ( true ) {
+ // Wait for a load request to be placed in the queue.
+ loader->mutex.lock();
+ while (loader->empty())
+ {
+ loader->cond.wait( loader->mutex );
+ }
+
+ // Have we been canceled - exits if yes.
+ //pthread_testcancel();
+ if (loader->empty())
+ {
+ loader->mutex.unlock();
+ pthread_exit( PTHREAD_CANCELED );
+ }
+
+ // Grab the tile to load and release the mutex.
+ FGTileEntry* tile = loader->tile_queue.front();
+ loader->tile_queue.pop();
+ loader->mutex.unlock();
+
+ set_cancel( SGThread::CANCEL_DISABLE );
+ tile->load( loader->tile_path, true );
+ set_cancel( SGThread::CANCEL_DEFERRED );
+ }
+ pthread_cleanup_pop(1);
+}
+
+/**
+ * Ensure mutex is unlocked.
+ */
+void
+cleanup_handler( void* arg )
+{
+ FGTileLoader* loader = (FGTileLoader*) arg;
+ loader->mutex.unlock();
+}
+#endif // ENABLE_THREADS
--- /dev/null
+// FGTileLoader - Queue scenery tiles for loading.
+//
+// Written by Bernie Bright, started March 2001.
+//
+// Copyright (C) 2001 Bernard Bright - bbright@bigpond.net.au
+//
+// 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
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef FG_TILE_LOADER_HXX
+#define FG_TILE_LOADER_HXX
+
+#include <queue>
+#include <pthread.h>
+
+#include <simgear/bucket/newbucket.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#ifdef ENABLE_THREADS
+# include <simgear/threads/SGThread.hxx>
+#endif
+
+// Forward reference.
+class FGTileEntry;
+
+/**
+ * Queues tiles for loading, possibly by a separate thread.
+ */
+class FGTileLoader
+{
+public:
+
+ /**
+ * Constructor.
+ */
+ FGTileLoader();
+
+ /**
+ * Destructor.
+ */
+ ~FGTileLoader();
+
+ /**
+ * Add a tile to the end of the load queue.
+ * @param tile The tile to be loaded from disk.
+ * @param vis Current visibilty (in feet?) (see FGTileMgr::vis).
+ */
+ void add( FGTileEntry* tile );
+
+ /**
+ * Returns whether the load queue is empty (contains no elements).
+ * @return true if load queue is empty otherwise returns false.
+ */
+ bool empty() const { return tile_queue.empty(); }
+
+private:
+
+private:
+
+ /**
+ * FIFO queue of tiles to load from data files.
+ */
+ std::queue< FGTileEntry* > tile_queue;
+
+ /**
+ * Base name of directory containing tile data file.
+ */
+ SGPath tile_path;
+
+#ifdef ENABLE_THREADS
+ /**
+ * Maximum number of threads to create for loading tiles.
+ */
+ enum { MAX_THREADS = 1 };
+
+ /**
+ * This class represents the thread of execution responsible for
+ * loading a tile.
+ */
+ class LoaderThread : public SGThread
+ {
+ public:
+ LoaderThread( FGTileLoader* l ) : loader(l) {}
+ ~LoaderThread() {}
+
+ /**
+ * Reads the tile from disk.
+ */
+ void run();
+
+ private:
+ FGTileLoader* loader;
+
+ private:
+ // not implemented.
+ LoaderThread();
+ LoaderThread( const LoaderThread& );
+ LoaderThread& operator=( const LoaderThread& );
+ };
+
+ friend class LoaderThread;
+
+ /**
+ * Array of loading threads.
+ */
+ LoaderThread* threads[ MAX_THREADS ];
+
+ /**
+ * Lock and synchronize access to tile queue.
+ */
+ SGMutex mutex;
+ SGCondition cond;
+
+ /**
+ * Thread cleanup handler.
+ */
+ friend void cleanup_handler( void* );
+#endif // ENABLE_THREADS
+};
+
+#endif // FG_TILE_LOADER_HXX
noinst_LIBRARIES = libScenery.a
libScenery_a_SOURCES = \
+ FGTileLoader.cxx FGTileLoader.hxx \
hitlist.cxx hitlist.hxx \
newcache.cxx newcache.hxx \
scenery.cxx scenery.hxx \
#include "newcache.hxx"
#include "tileentry.hxx"
-#include "tilemgr.hxx" // temp, need to delete later
-
-SG_USING_NAMESPACE(std);
-// the tile cache
-FGNewCache global_tile_cache;
+SG_USING_NAMESPACE(std);
// Constructor
SG_LOG( SG_TERRAIN, SG_DEBUG, "FREEING CACHE ENTRY = " << cache_index );
FGTileEntry *e = tile_cache[cache_index];
e->free_tile();
- delete( e );
+ delete e;
tile_cache.erase( cache_index );
}
// Search for the specified "bucket" in the cache
-bool FGNewCache::exists( const SGBucket& b ) {
+bool FGNewCache::exists( const SGBucket& b ) const {
long tile_index = b.gen_index();
- tile_map_iterator it = tile_cache.find( tile_index );
+ const_tile_map_iterator it = tile_cache.find( tile_index );
return ( it != tile_cache.end() );
}
+// depricated for threading
+#if 0
// Fill in a tile cache entry with real data for the specified bucket
void FGNewCache::fill_in( const SGBucket& b ) {
SG_LOG( SG_TERRAIN, SG_DEBUG, "FILL IN CACHE ENTRY = " << b.gen_index() );
// Load the appropriate data file
e->load( tile_path, true );
}
+#endif
// Ensure at least one entry is free in the cache
void FGNewCache::make_space() {
SG_LOG( SG_TERRAIN, SG_DEBUG, "Make space in cache" );
-
-
SG_LOG( SG_TERRAIN, SG_DEBUG, "cache entries = " << tile_cache.size() );
SG_LOG( SG_TERRAIN, SG_DEBUG, "max size = " << max_cache_size );
long index = current->first;
FGTileEntry *e = current->second;
- // calculate approximate distance from view point
- sgdCopyVec3( abs_view_pos,
- globals->get_current_view()->get_abs_view_pos() );
-
- SG_LOG( SG_TERRAIN, SG_DEBUG, "DIST Abs view pos = "
- << abs_view_pos[0] << ","
- << abs_view_pos[1] << ","
- << abs_view_pos[2] );
- SG_LOG( SG_TERRAIN, SG_DEBUG,
- " ref point = " << e->center );
-
- sgdVec3 center;
- sgdSetVec3( center, e->center.x(), e->center.y(), e->center.z() );
- dist = sgdDistanceVec3( center, abs_view_pos );
-
- SG_LOG( SG_TERRAIN, SG_DEBUG, " distance = " << dist );
-
- if ( dist > max_dist ) {
- max_dist = dist;
- max_index = index;
+ if ( e->is_loaded() ) {
+ // calculate approximate distance from view point
+ sgdCopyVec3( abs_view_pos,
+ globals->get_current_view()->get_abs_view_pos() );
+
+ SG_LOG( SG_TERRAIN, SG_DEBUG, "DIST Abs view pos = "
+ << abs_view_pos[0] << ","
+ << abs_view_pos[1] << ","
+ << abs_view_pos[2] );
+ SG_LOG( SG_TERRAIN, SG_DEBUG,
+ " ref point = " << e->center );
+
+ sgdVec3 center;
+ sgdSetVec3( center,
+ e->center.x(), e->center.y(), e->center.z() );
+ dist = sgdDistanceVec3( center, abs_view_pos );
+
+ SG_LOG( SG_TERRAIN, SG_DEBUG, " distance = " << dist );
+
+ if ( dist > max_dist ) {
+ max_dist = dist;
+ max_index = index;
+ }
}
}
}
}
}
+
+
+/**
+ * Create a new tile and schedule it for loading.
+ */
+void
+FGNewCache::load_tile( const SGBucket& b )
+{
+ // clear out a distant entry in the cache if needed.
+ make_space();
+
+ // create the entry
+ FGTileEntry *e = new FGTileEntry( b );
+
+ // register it in the cache
+ long tile_index = b.gen_index();
+ tile_cache[tile_index] = e;
+
+ // Schedule tile for loading
+ loader.add( e );
+}
#include <simgear/math/point3d.hxx>
#include "tileentry.hxx"
+#include "FGTileLoader.hxx"
SG_USING_STD(map);
-
-typedef map < long, FGTileEntry * > tile_map;
-typedef tile_map::iterator tile_map_iterator;
-typedef tile_map::const_iterator const_tile_map_iterator;
-
-
// A class to store and manage a pile of tiles
class FGNewCache {
+ typedef map < long, FGTileEntry * > tile_map;
+ typedef tile_map::iterator tile_map_iterator;
+ typedef tile_map::const_iterator const_tile_map_iterator;
+
// cache storage space
tile_map tile_cache;
// Free a tile cache entry
void entry_free( long cache_index );
+ /**
+ * Queue tiles for loading.
+ */
+ FGTileLoader loader;
+
public:
// Constructor
void init( void );
// Check if the specified "bucket" exists in the cache
- bool exists( const SGBucket& b );
+ bool exists( const SGBucket& b ) const;
// Ensure at least one entry is free in the cache
void make_space();
// Fill in a tile cache entry with real data for the specified bucket
- void fill_in( const SGBucket& b );
+ // void fill_in( const SGBucket& b );
// Return a pointer to the specified tile cache entry
inline FGTileEntry *get_tile( const long tile_index ) {
inline int get_max_cache_size() const { return max_cache_size; }
inline void set_max_cache_size( int m ) { max_cache_size = m; }
-};
-
-// the tile cache
-extern FGNewCache global_tile_cache;
+ /**
+ * Create a new tile and enqueue it for loading.
+ * @param b
+ */
+ void load_tile( const SGBucket& b );
+};
#endif // _NEWCACHE_HXX
basename.append( index_str );
string path = basename.str();
- SG_LOG( SG_TERRAIN, SG_INFO, "Loading tile " << path );
+ SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << path );
// fgObjLoad will generate ground lighting for us ...
ssgVertexArray *light_pts = new ssgVertexArray( 100 );
* random ground light points
*/
void load( const SGPath& base, bool is_base );
+
+ /**
+ * Return true if the tile entry is loaded, otherwise return false
+ * indicating that the loading thread is still working on this.
+ */
+ inline bool is_loaded() const { return loaded; }
};
} else {
SG_LOG( SG_TERRAIN, SG_INFO,
"... First time through." );
- global_tile_cache.init();
+ tile_cache.init();
}
hit_list.clear();
// schedule a tile for loading
void FGTileMgr::sched_tile( const SGBucket& b ) {
// see if tile already exists in the cache
- FGTileEntry *t = global_tile_cache.get_tile( b );
+ FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) {
// register a load request
- load_queue.push_back( b );
+ tile_cache.load_tile( b );
}
}
+// depricated for threading
+#if 0
// load a tile
void FGTileMgr::load_tile( const SGBucket& b ) {
// see if tile already exists in the cache
- FGTileEntry *t = global_tile_cache.get_tile( b );
+ FGTileEntry *t = tile_cache.get_tile( b );
if ( t == NULL ) {
SG_LOG( SG_TERRAIN, SG_DEBUG, "Loading tile " << b );
- global_tile_cache.fill_in( b );
- t = global_tile_cache.get_tile( b );
+ tile_cache.fill_in( b );
+ t = tile_cache.get_tile( b );
t->prep_ssg_node( scenery.center, vis);
} else {
SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile already in cache " << b );
}
}
+#endif
static void CurrentNormalInLocalPlane(sgVec3 dst, sgVec3 src) {
#else
vis = current_weather.get_visibility();
#endif
- cout << "visibility = " << vis << endl;
+ // cout << "visibility = " << vis << endl;
double tile_width = current_bucket.get_width_m();
double tile_height = current_bucket.get_height_m();
- cout << "tile width = " << tile_width << " tile_height = " << tile_height
- << endl;
+ // cout << "tile width = " << tile_width << " tile_height = "
+ // << tile_height !<< endl;
xrange = (int)(vis / tile_width) + 1;
yrange = (int)(vis / tile_height) + 1;
if ( xrange < 1 ) { xrange = 1; }
if ( yrange < 1 ) { yrange = 1; }
- cout << "xrange = " << xrange << " yrange = " << yrange << endl;
+ // cout << "xrange = " << xrange << " yrange = " << yrange << endl;
- global_tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
+ tile_cache.set_max_cache_size( (2*xrange + 2) * (2*yrange + 2) );
SGBucket b;
for ( y = -1; y <= 1; ++y ) {
if ( x != 0 || y != 0 ) {
b = sgBucketOffset( longitude, latitude, x, y );
- if ( ! global_tile_cache.exists( b ) ) {
- sched_tile( b );
- }
+ sched_tile( b );
}
}
}
for ( y = -yrange; y <= yrange; ++y ) {
if ( x < -1 || x > 1 || y < -1 || y > 1 ) {
SGBucket b = sgBucketOffset( longitude, latitude, x, y );
- if ( ! global_tile_cache.exists( b ) ) {
- sched_tile( b );
- }
+ sched_tile( b );
}
}
}
// system and load all relavant tiles
SG_LOG( SG_TERRAIN, SG_INFO, "Updating Tile list for " << current_bucket );
- cout << "tile cache size = " << global_tile_cache.get_size() << endl;
+ // cout << "tile cache size = " << tile_cache.get_size() << endl;
int i;
// wipe/initialize tile cache
- // global_tile_cache.init();
+ // tile_cache.init();
previous_bucket.make_bad();
// build the local area list and schedule tiles for loading
schedule_needed();
+ // do we really want to lose this? CLO
+#if 0
// 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 ) {
load_tile( pending );
}
}
+#endif
}
// tile_cache -- which actually handles all the
// (de)allocations
void FGTileMgr::destroy_queue() {
- load_queue.clear();
+ // load_queue.clear();
}
current_bucket.set_bucket( longitude, latitude );
// SG_LOG( SG_TERRAIN, SG_DEBUG, "Updating Tile list for " << current_bucket );
- if ( global_tile_cache.exists( current_bucket ) ) {
- current_tile = global_tile_cache.get_tile( current_bucket );
+ if ( tile_cache.exists( current_bucket ) ) {
+ current_tile = tile_cache.get_tile( current_bucket );
scenery.next_center = current_tile->center;
} else {
SG_LOG( SG_TERRAIN, SG_WARN, "Tile not found (Ok if initializing)" );
state = Running;
}
+ // now handled by threaded tile pager
+#if 0
if ( load_queue.size() ) {
SG_LOG( SG_TERRAIN, SG_INFO, "Load queue size = " << load_queue.size()
<< " loading a tile" );
load_queue.pop_front();
load_tile( pending );
}
+#endif
if ( scenery.center == Point3D(0.0) ) {
// initializing
// selector and transform
FGTileEntry *e;
- global_tile_cache.reset_traversal();
+ tile_cache.reset_traversal();
- while ( ! global_tile_cache.at_end() ) {
+ while ( ! tile_cache.at_end() ) {
// cout << "processing a tile" << endl;
- if ( (e = global_tile_cache.get_current()) ) {
+ if ( (e = tile_cache.get_current()) ) {
e->prep_ssg_node( scenery.center, vis);
} else {
cout << "warning ... empty tile in cache" << endl;
}
- global_tile_cache.next();
+ tile_cache.next();
}
}
#include <simgear/compiler.h>
-#include <list>
-
#include <plib/ssg.h>
#include <simgear/bucket/newbucket.hxx>
#include "hitlist.hxx"
-
-SG_USING_STD(list);
-
+#include "newcache.hxx"
#if defined(USE_MEM) || defined(WIN32)
# define FG_MEM_COPY(to,from,n) memcpy(to, from, n)
load_state state;
- // pending tile load queue
- list < SGBucket > load_queue;
-
// initialize the cache
void initialize_queue();
// schedule a tile for loading
void sched_tile( const SGBucket& b );
- // load a tile
- void load_tile( const SGBucket& b );
-
// schedule a needed buckets for loading
void schedule_needed();
double last_longitude;
double last_latitude;
+ /**
+ *
+ */
+ FGNewCache tile_cache;
+
public:
// Constructor
// transform and update it's range selector based on current
// visibilty
void prep_ssg_nodes();
-
- inline int queue_size() const { return load_queue.size(); }
};