diff --git a/Airports/simple.cxx b/Airports/simple.cxx
index 9e661eb4b..ffa093ba7 100644
--- a/Airports/simple.cxx
+++ b/Airports/simple.cxx
@@ -28,66 +28,89 @@
 #include <string>
 
 #include <Debug/fg_debug.h>
-#include <Include/fg_zlib.h>
 #include <Main/options.hxx>
+#include <Misc/fgstream.hxx>
+#include <Misc/stopwatch.hxx>
 
 #include "simple.hxx"
 
+#include "Include/fg_stl_config.h"
+#include STL_FUNCTIONAL
+#include STL_ALGORITHM
 
-// Constructor
-fgAIRPORTS::fgAIRPORTS( void ) {
+fgAIRPORTS::fgAIRPORTS() {
 }
 
 
 // load the data
 int fgAIRPORTS::load( const string& file ) {
-    fgAIRPORT a;
-    string path, fgpath, id;
-    char id_raw[256], line[256];
-    fgFile f;
-
     // build the path name to the airport file
-    path = current_options.get_fg_root() + "/Airports/" + file;
-    fgpath = path + ".gz";
+    string path = current_options.get_fg_root() + "/Airports/" + file;
+    StopWatch t;
 
-    // first try "path.gz"
-    if ( (f = fgopen(fgpath.c_str(), "rb")) == NULL ) {
-	// next try "path"
-        if ( (f = fgopen(path.c_str(), "rb")) == NULL ) {
-	    fgPrintf( FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", 
-		      path.c_str());
-	}
+    airports.erase( airports.begin(), airports.end() );
+
+    fg_gzifstream in( path );
+    if ( !in )
+	fgPrintf( FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", 
+		  path.c_str());
+
+    t.start();
+
+    // We can use the STL copy algorithm because the input
+    // file doesn't contain and comments or blank lines.
+    copy( istream_iterator<fgAIRPORT,ptrdiff_t>(in.stream()),
+	  istream_iterator<fgAIRPORT,ptrdiff_t>(),
+ 	  inserter( airports, airports.begin() ) );
+
+    t.stop();
+
+    fgPrintf( FG_GENERAL, FG_INFO, "Loaded %d airports in %f seconds\n",
+	      airports.size(), t.elapsedSeconds() );
+
+    return 1;
+}
+
+// class fgAIRPORT_eq : public unary_function<fgAIRPORT,bool>
+// {
+// public:
+//     explicit fgAIRPORT_eq( const string& id ) : _id(id) {}
+//     bool operator () ( const fgAIRPORT& a ) const { return a.id == _id; }
+// private:
+//     string _id;
+// };
+
+// search for the specified id
+bool
+fgAIRPORTS::search( const string& id, fgAIRPORT* a ) const
+{
+    StopWatch t;
+    t.start();
+//     const_iterator it = find_if( airports.begin(),
+// 				 airports.end(), fgAIRPORT_eq(id) );
+  
+    const_iterator it = airports.find( fgAIRPORT(id) );
+    t.stop();
+    if ( it != airports.end() )
+    {
+	*a = *it;
+	cout << "Found " << id << " in " << t.elapsedSeconds()
+	     << " seconds" << endl;
+	return true;
     }
-
-    while ( fggets(f, line, 250) != NULL ) {
-	// printf("%s", line);
-
-	sscanf( line, "%s %lf %lf %lfl\n", id_raw, &a.longitude, &a.latitude, 
-		&a.elevation );
-	id = id_raw;
-	airports[id] = a;
+    else
+    {
+	return false;
     }
-
-    fgclose(f);
-
-    return(1);
 }
 
 
-// search for the specified id
-fgAIRPORT fgAIRPORTS::search( char *id ) {
-    map < string, fgAIRPORT, less<string> > :: iterator find;
+fgAIRPORT
+fgAIRPORTS::search( const string& id ) const
+{
     fgAIRPORT a;
-
-    find = airports.find(id);
-    if ( find == airports.end() ) {
-	// not found
-	a.longitude = a.latitude = a.elevation = 0;
-    } else {
-	a = (*find).second;
-    }
-
-    return(a);
+    this->search( id, &a );
+    return a;
 }
 
 
@@ -97,6 +120,64 @@ fgAIRPORTS::~fgAIRPORTS( void ) {
 
 
 // $Log$
+// Revision 1.4  1998/09/01 19:02:53  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.3  1998/08/27 17:01:55  curt
 // Contributions from Bernie Bright <bbright@c031.aone.net.au>
 // - use strings for fg_root and airport_id and added methods to return
diff --git a/Airports/simple.hxx b/Airports/simple.hxx
index cefa0389f..49c1dd2b8 100644
--- a/Airports/simple.hxx
+++ b/Airports/simple.hxx
@@ -35,38 +35,64 @@
 
 
 #include <string>        // Standard C++ string library
-#include <map>           // STL associative "array"
+#include <set>
 
 #ifdef NEEDNAMESPACESTD
 using namespace std;
 #endif
 
 
-typedef struct {
-    // char id[5];
+class fgAIRPORT {
+public:
+    fgAIRPORT( const string& name = "",
+	       double lon = 0.0,
+	       double lat = 0.0,
+	       double ele = 0.0 )
+	: id(name), longitude(lon), latitude(lat), elevation(ele) {}
+
+    bool operator < ( const fgAIRPORT& a ) const {
+	return id < a.id;
+    }
+
+public:
+    string id;
     double longitude;
     double latitude;
     double elevation;
-} fgAIRPORT;
+};
 
+inline istream&
+operator >> ( istream& in, fgAIRPORT& a )
+{
+    return in >> a.id >> a.longitude >> a.latitude >> a.elevation;
+}
 
 class fgAIRPORTS {
-    map < string, fgAIRPORT, less<string> > airports;
+public:
+    typedef set< fgAIRPORT > container;
+    typedef container::iterator iterator;
+    typedef container::const_iterator const_iterator;
+
+private:
+    container airports;
 
 public:
 
     // Constructor
-    fgAIRPORTS( void );
+    fgAIRPORTS();
+
+    // Destructor
+    ~fgAIRPORTS();
 
     // load the data
     int load( const string& file );
 
-    // search for the specified id
-    fgAIRPORT search( char *id );
-
-    // Destructor
-    ~fgAIRPORTS( void );
-
+    // search for the specified id.
+    // Returns true if successful, otherwise returns false.
+    // On success, airport data is returned thru "airport" pointer.
+    // "airport" is not changed if "id" is not found.
+    bool search( const string& id, fgAIRPORT* airport ) const;
+    fgAIRPORT search( const string& id ) const;
 };
 
 
@@ -74,6 +100,64 @@ public:
 
 
 // $Log$
+// Revision 1.3  1998/09/01 19:02:54  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.2  1998/08/27 17:01:56  curt
 // Contributions from Bernie Bright <bbright@c031.aone.net.au>
 // - use strings for fg_root and airport_id and added methods to return
diff --git a/Astro/stars.cxx b/Astro/stars.cxx
index 3eed6dc91..98bc9c5a8 100644
--- a/Astro/stars.cxx
+++ b/Astro/stars.cxx
@@ -45,9 +45,10 @@
 #include <Debug/fg_debug.h>
 #include <Include/fg_constants.h>
 #include <Include/fg_types.h>
-#include <Include/fg_zlib.h>
+#include "Misc/fgstream.hxx"
 #include <Main/options.hxx>
 #include <Main/views.hxx>
+#include <Misc/stopwatch.hxx>
 #include <Time/fg_time.hxx>
 
 #include "orbits.hxx"
@@ -66,11 +67,7 @@ static GLint stars[FG_STAR_LEVELS];
 /* Initialize the Star Management Subsystem */
 int fgStarsInit( void ) {
     fgPoint3d starlist[FG_MAX_STARS];
-    fgFile fd;
     /* struct CelestialCoord pltPos; */
-    string path, gzpath;
-    char line[256], name[256];
-    char *front, *end;
     double right_ascension, declination, magnitude;
     double min_magnitude[FG_STAR_LEVELS];
     /* double ra_save, decl_save; */
@@ -79,66 +76,44 @@ int fgStarsInit( void ) {
 
     fgPrintf( FG_ASTRO, FG_INFO, "Initializing stars\n");
 
-    /* build the full path name to the stars data base file */
-    path = current_options.get_fg_root() + "/Astro/stars";
-    gzpath = path + ".gz";
-
     if ( FG_STAR_LEVELS < 4 ) {
 	fgPrintf( FG_ASTRO, FG_EXIT, "Big whups in stars.cxx\n");
     }
 
+    // build the full path name to the stars data base file
+    string path = current_options.get_fg_root() + "/Astro/stars" + ".gz";
+
     fgPrintf( FG_ASTRO, FG_INFO, "  Loading stars from %s\n", path.c_str() );
 
-    // load star data file
-    if ( (fd = fgopen(path.c_str(), "rb")) == NULL ) {
-	if ( (fd = fgopen(gzpath.c_str(), "rb")) == NULL ) {
-	    // Oops, lets not even try to continue. This is critical.
-	    fgPrintf( FG_ASTRO, FG_EXIT,
-		      "Cannot open star file: '%s'\n", path.c_str() );
-	}
-    }
+    fg_gzifstream in( path );
+    if ( ! in )
+	fgPrintf( FG_ASTRO, FG_EXIT,
+		  "Cannot open star file: '%s'\n", path.c_str() );
 
     starcount = 0;
 
+    StopWatch timer;
+    timer.start();
+
     // read in each line of the file
-    while ( (fggets(fd, line, 256) != NULL) && (starcount < FG_MAX_STARS) ) {
-	front = line;
-
-	// printf("  Read line = %s", front);
-
-	// advance to first non-whitespace character
-	while ( (front[0] == ' ') || (front[0] == '\t') ) {
-	    front++;
-	}
-
-	// printf("  Line length (after trimming) = %d\n", strlen(front));
-
-	if ( front[0] == '#' ) {
-	    // comment
-	} else if ( strlen(front) <= 1 ) {
-	    // blank line
-	} else {
-	    // star data line
-
-	    // get name
-	    end = front;
-	    while ( end[0] != ',' ) {
-		end++;
-	    }
-	    end[0] = '\0';
-	    strcpy(name, front);
-	    front = end;
-	    front++;
-
-	    sscanf(front, "%lf,%lf,%lf\n",
-		   &right_ascension, &declination, &magnitude);
-	    starlist[starcount].x = right_ascension;
-	    starlist[starcount].y = declination;
-	    starlist[starcount].z = magnitude;
-	    starcount++;
-	}
+    while ( ! in.eof() && starcount < FG_MAX_STARS )
+    {
+	in.eat_comments();
+	string name;
+	char c = 0;
+	getline( in.stream(), name, ',' );
+	in.stream() >> starlist[starcount].x >> c;
+	in.stream() >> starlist[starcount].y >> c;
+// 	in.stream() >> starlist[starcount].x; in.get(c);
+// 	in.stream() >> starlist[starcount].y; in.get(c);
+	in.stream() >> starlist[starcount].z;
+	++starcount;
     }
 
+    timer.stop();
+    cerr << "Loaded " << starcount << " stars in "
+	 << timer.elapsedSeconds() << " seconds" << endl;
+
     min_magnitude[0] = 4.2;
     min_magnitude[1] = 3.6;
     min_magnitude[2] = 3.0;
@@ -286,15 +261,73 @@ void fgStarsRender( void ) {
 
 
 /* $Log$
-/* Revision 1.12  1998/08/27 17:02:01  curt
-/* Contributions from Bernie Bright <bbright@c031.aone.net.au>
-/* - use strings for fg_root and airport_id and added methods to return
-/*   them as strings,
-/* - inlined all access methods,
-/* - made the parsing functions private methods,
-/* - deleted some unused functions.
-/* - propogated some of these changes out a bit further.
+/* Revision 1.13  1998/09/01 19:03:04  curt
+/* Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+/*  - The new classes in libmisc.tgz define a stream interface into zlib.
+/*    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+/*    to something more appropriate.  However you'll have to change the
+/*    include directives in all the other files.  Additionally you'll have
+/*    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
 /*
+/*    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+/*    test so I've included the required changes in config.tgz.
+/*
+/*    There are a fair few changes to Simulator/Objects as I've moved
+/*    things around.  Loading tiles is quicker but thats not where the delay
+/*    is.  Tile loading takes a few tenths of a second per file on a P200
+/*    but it seems to be the post-processing that leads to a noticeable
+/*    blip in framerate.  I suppose its time to start profiling to see where
+/*    the delays are.
+/*
+/*    I've included a brief description of each archives contents.
+/*
+/* Lib/Misc/
+/*   zfstream.cxx
+/*   zfstream.hxx
+/*     C++ stream interface into zlib.
+/*     Taken from zlib-1.1.3/contrib/iostream/.
+/*     Minor mods for STL compatibility.
+/*     There's no copyright associated with these so I assume they're
+/*     covered by zlib's.
+/*
+/*   fgstream.cxx
+/*   fgstream.hxx
+/*     FlightGear input stream using gz_ifstream.  Tries to open the
+/*     given filename.  If that fails then filename is examined and a
+/*     ".gz" suffix is removed or appended and that file is opened.
+/*
+/*   stopwatch.hxx
+/*     A simple timer for benchmarking.  Not used in production code.
+/*     Taken from the Blitz++ project.  Covered by GPL.
+/*
+/*   strutils.cxx
+/*   strutils.hxx
+/*     Some simple string manipulation routines.
+/*
+/* Simulator/Airports/
+/*   Load airports database using fgstream.
+/*   Changed fgAIRPORTS to use set<> instead of map<>.
+/*   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+/*   Returns true if found.
+/*
+/* Simulator/Astro/
+/*   Modified fgStarsInit() to load stars database using fgstream.
+/*
+/* Simulator/Objects/
+/*   Modified fgObjLoad() to use fgstream.
+/*   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+/*   Many changes to fgMATERIAL.
+/*   Some changes to fgFRAGMENT but I forget what!
+/*
+ * Revision 1.12  1998/08/27 17:02:01  curt
+ * Contributions from Bernie Bright <bbright@c031.aone.net.au>
+ * - use strings for fg_root and airport_id and added methods to return
+ *   them as strings,
+ * - inlined all access methods,
+ * - made the parsing functions private methods,
+ * - deleted some unused functions.
+ * - propogated some of these changes out a bit further.
+ *
  * Revision 1.11  1998/08/25 20:53:29  curt
  * Shuffled $FG_ROOT file layout.
  *
diff --git a/Main/Makefile.am b/Main/Makefile.am
index 9fed7728a..4ffd1a282 100644
--- a/Main/Makefile.am
+++ b/Main/Makefile.am
@@ -52,7 +52,8 @@ fgfs_LDADD = \
 	$(top_builddir)/Lib/Bucket/libBucket.a \
 	$(top_builddir)/Lib/Debug/libDebug.a \
 	$(top_builddir)/Lib/PUI/libPUI.a \
-	$(top_builddir)/Lib/zlib/libz.a
+	$(top_builddir)/Lib/zlib/libz.a \
+	$(top_builddir)/Lib/Misc/libMisc.a
 
 INCLUDES += \
 	-I$(top_builddir) \
diff --git a/Objects/fragment.cxx b/Objects/fragment.cxx
index 089ac15bc..645a5c5ea 100644
--- a/Objects/fragment.cxx
+++ b/Objects/fragment.cxx
@@ -30,46 +30,39 @@
 #include "fragment.hxx"
 
 
-// return the sign of a value
-#define FG_SIGN( x )  ((x) < 0 ? -1 : 1)
+template <class T>
+inline const int FG_SIGN(const T& x) {
+    return x < T(0) ? -1 : 1;
+}
 
-// return min or max of two values
-#define FG_MIN(A,B)	((A) < (B) ? (A) :  (B))
-#define FG_MAX(A,B)	((A) > (B) ? (A) :  (B))
+template <class T>
+inline const T& FG_MIN(const T& a, const T& b) {
+    return b < a ? b : a;
+}
 
+template <class T>
+inline const T& FG_MAX(const T& a, const T& b) {
+    return  a < b ? b : a;
+}
 
-fgFACE :: fgFACE () : 
-    n1(0), n2(0), n3(0)
+// return the minimum of the three values
+template <class T>
+inline const T& fg_min3( const T& a, const T& b, const T& c)
 {
+    return (a > b ? FG_MIN (b, c) : FG_MIN (a, c));
 }
 
-fgFACE :: ~fgFACE()
+
+// return the maximum of the three values
+template <class T>
+inline const T& fg_max3 (const T& a, const T& b, const T& c)
 {
+    return (a < b ? FG_MAX (b, c) : FG_MAX (a, c));
 }
 
-fgFACE :: fgFACE( const fgFACE & image ) :
-    n1( image.n1), n2( image.n2), n3( image.n3)
-{
-}
-
-bool fgFACE :: operator < (const fgFACE & rhs )
-{
-    return ( n1 < rhs.n1 ? true : false);
-}
-
-bool fgFACE :: operator == (const fgFACE & rhs )
-{
-    return ((n1 == rhs.n1) && (n2 == rhs.n2) && ( n3 == rhs.n3));
-}
-
-
-// Constructor
-fgFRAGMENT::fgFRAGMENT ( void ) {
-}
-
-
+// Add a face to the face list
 // Copy constructor
-fgFRAGMENT ::   fgFRAGMENT ( const fgFRAGMENT & rhs ) :
+fgFRAGMENT::fgFRAGMENT ( const fgFRAGMENT & rhs ) :
     center         ( rhs.center          ),
     bounding_radius( rhs.bounding_radius ),
     material_ptr   ( rhs.material_ptr    ),
@@ -80,7 +73,7 @@ fgFRAGMENT ::   fgFRAGMENT ( const fgFRAGMENT & rhs ) :
 {
 }
 
-fgFRAGMENT & fgFRAGMENT :: operator = ( const fgFRAGMENT & rhs )
+fgFRAGMENT & fgFRAGMENT::operator = ( const fgFRAGMENT & rhs )
 {
     if(!(this == &rhs )) {
 	center          = rhs.center;
@@ -94,41 +87,16 @@ fgFRAGMENT & fgFRAGMENT :: operator = ( const fgFRAGMENT & rhs )
 }
 
 
-// Add a face to the face list
-void fgFRAGMENT::add_face(int n1, int n2, int n3) {
-    fgFACE face;
-
-    face.n1 = n1;
-    face.n2 = n2;
-    face.n3 = n3;
-
-    faces.push_back(face);
-    num_faces++;
-}
-
-
-// return the minimum of the three values
-static double fg_min3 (double a, double b, double c)
-{
-    return (a > b ? FG_MIN (b, c) : FG_MIN (a, c));
-}
-
-
-// return the maximum of the three values
-static double fg_max3 (double a, double b, double c)
-{
-  return (a < b ? FG_MAX (b, c) : FG_MAX (a, c));
-}
-
-
 // test if line intesects with this fragment.  p0 and p1 are the two
 // line end points of the line.  If side_flag is true, check to see
 // that end points are on opposite sides of face.  Returns 1 if it
 // intersection found, 0 otherwise.  If it intesects, result is the
 // point of intersection
 
-int fgFRAGMENT::intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag,
-			   fgPoint3d *result)
+int fgFRAGMENT::intersect( const fgPoint3d *end0,
+			   const fgPoint3d *end1,
+			   int side_flag,
+			   fgPoint3d *result) const
 {
     fgTILE *t;
     fgFACE face;
@@ -141,8 +109,6 @@ int fgFRAGMENT::intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag,
     double xmin, xmax, ymin, ymax, zmin, zmax;
     double dx, dy, dz, min_dim, x2, y2, x3, y3, rx, ry;
     int side1, side2;
-    list < fgFACE > :: iterator current;
-    list < fgFACE > :: iterator last;
 
     // find the associated tile
     t = tile_ptr;
@@ -150,8 +116,8 @@ int fgFRAGMENT::intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag,
     // printf("Intersecting\n");
 
     // traverse the face list for this fragment
-    current = faces.begin();
-    last = faces.end();
+    const_iterator current = faces.begin();
+    const_iterator last = faces.end();
     while ( current != last ) {
 	face = *current;
 	current++;
@@ -367,44 +333,65 @@ int fgFRAGMENT::intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag,
     return(0);
 }
 
-
-// Destructor
-fgFRAGMENT::~fgFRAGMENT ( void ) {
-    // Step through the face list deleting the items until the list is
-    // empty
-
-    // printf("destructing a fragment with %d faces\n", faces.size());
-
-    while ( faces.size() ) {
-	//  printf("emptying face list\n");
-	faces.pop_front();
-    }
-}
-
-
-// equality operator
-bool  fgFRAGMENT :: operator == ( const fgFRAGMENT & rhs)
-{
-    if(( center.x - rhs.center.x ) < FG_EPSILON) {
-	if(( center.y - rhs.center.y) < FG_EPSILON) {
-	    if(( center.z - rhs.center.z) < FG_EPSILON) {
-		return true;
-	    }
-	}
-    }
-    return false;
-}
-
-// comparison operator
-bool  fgFRAGMENT :: operator < ( const fgFRAGMENT &rhs)
-{
-    // This is completely arbitrary. It satisfies RW's STL implementation
-
-    return bounding_radius < rhs.bounding_radius;
-}
-
-
 // $Log$
+// Revision 1.2  1998/09/01 19:03:07  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.1  1998/08/25 16:51:23  curt
 // Moved from ../Scenery
 //
diff --git a/Objects/fragment.hxx b/Objects/fragment.hxx
index 4b1b3d2ba..92d67675b 100644
--- a/Objects/fragment.hxx
+++ b/Objects/fragment.hxx
@@ -50,6 +50,7 @@ extern "C" void *memset(void *, int, size_t);
 
 #include <Bucket/bucketutils.h>
 #include <Include/fg_types.h>
+#include "Include/fg_constants.h"
 #include <Math/mat3.h>
 
 #ifdef NEEDNAMESPACESTD
@@ -70,13 +71,22 @@ class fgFACE {
 public:
     int n1, n2, n3;
 
-    fgFACE();
-    ~fgFACE();
-    fgFACE( const fgFACE & image );
-    bool operator < ( const fgFACE & rhs );
-    bool operator == ( const fgFACE & rhs );
+    explicit fgFACE( int a = 0, int b =0, int c =0 )
+	: n1(a), n2(b), n3(c) {}
+
+    fgFACE( const fgFACE & image )
+	: n1(image.n1), n2(image.n2), n3(image.n3) {}
+
+    ~fgFACE() {}
+
+    bool operator < ( const fgFACE & rhs ) { return n1 < rhs.n1; }
 };
 
+inline bool
+operator == ( const fgFACE& lhs, const fgFACE & rhs )
+{
+    return (lhs.n1 == rhs.n1) && (lhs.n2 == rhs.n2) && (lhs.n3 == rhs.n3);
+}
 
 // Object fragment data class
 class fgFRAGMENT {
@@ -106,40 +116,126 @@ public:
     GLint display_list;
 
     // face list (this indexes into the master tile vertex list)
-    list < fgFACE > faces;
+    typedef list < fgFACE > container;
+    typedef container::iterator iterator;
+    typedef container::const_iterator const_iterator;
+
+    container faces;
 
     // number of faces in this fragment
     int num_faces;
 
     // Add a face to the face list
-    void add_face(int n1, int n2, int n3);
+    void add_face(int n1, int n2, int n3) {
+	faces.push_back( fgFACE(n1,n2,n3) );
+	num_faces++;
+    }
 
     // test if line intesects with this fragment.  p0 and p1 are the
     // two line end points of the line.  If side_flag is true, check
     // to see that end points are on opposite sides of face.  Returns
     // 1 if it intersection found, 0 otherwise.  If it intesects,
     // result is the point of intersection
-    int intersect( fgPoint3d *end0, fgPoint3d *end1, int side_flag,
-		   fgPoint3d *result);
+    int intersect( const fgPoint3d *end0,
+		   const fgPoint3d *end1,
+		   int side_flag,
+		   fgPoint3d *result) const;
 
     // Constructors
-    fgFRAGMENT ();
+    fgFRAGMENT () {}
     fgFRAGMENT ( const fgFRAGMENT &image );
 
     // Destructor
-    ~fgFRAGMENT ( );
+    ~fgFRAGMENT() { faces.erase( faces.begin(), faces.end() ); }
 
     // operators
     fgFRAGMENT & operator = ( const fgFRAGMENT & rhs );
-    bool operator == ( const fgFRAGMENT & rhs );
-    bool operator <  ( const fgFRAGMENT & rhs );
+
+    bool operator <  ( const fgFRAGMENT & rhs ) {
+	// This is completely arbitrary. It satisfies RW's STL implementation
+	return bounding_radius < rhs.bounding_radius;
+    }
+
+    void init() {
+	faces.erase( faces.begin(), faces.end() );
+	num_faces = 0;
+    }
+
+    void deleteDisplayList() {
+	xglDeleteLists( display_list, 1 );
+    }
 };
 
+inline bool
+operator == ( const fgFRAGMENT & lhs, const fgFRAGMENT & rhs ) {
+    return (( lhs.center.x - rhs.center.x ) < FG_EPSILON &&
+	    ( lhs.center.y - rhs.center.y ) < FG_EPSILON &&
+	    ( lhs.center.z - rhs.center.z ) < FG_EPSILON    );
+}
+
 
 #endif // _FRAGMENT_HXX 
 
 
 // $Log$
+// Revision 1.2  1998/09/01 19:03:08  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.1  1998/08/25 16:51:23  curt
 // Moved from ../Scenery
 //
diff --git a/Objects/material.cxx b/Objects/material.cxx
index 27bd64c36..6625a334b 100644
--- a/Objects/material.cxx
+++ b/Objects/material.cxx
@@ -36,8 +36,8 @@
 #include <string.h>
 
 #include <Debug/fg_debug.h>
-#include <Include/fg_zlib.h>
 #include <Main/options.hxx>
+#include <Misc/fgstream.hxx>
 
 #include "material.hxx"
 #include "texload.h"
@@ -48,16 +48,165 @@ fgMATERIAL_MGR material_mgr;
 
 // Constructor
 fgMATERIAL::fgMATERIAL ( void ) {
-}
-
-
-// Sorting routines
-void fgMATERIAL::init_sort_list( void ) {
+    alpha = 0;
+    ambient[0]  = ambient[1]  = ambient[2]  = ambient[3]  = 0.0;
+    diffuse[0]  = diffuse[1]  = diffuse[2]  = diffuse[3]  = 0.0;
+    specular[0] = specular[1] = specular[2] = specular[3] = 0.0;
+    emissive[0] = emissive[1] = emissive[2] = emissive[3] = 0.0;
 }
 
 
 int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) {
-    return(0);
+    if ( list_size < FG_MAX_MATERIAL_FRAGS )
+    {
+	list[ list_size++ ] = object;
+	return 0;
+    }
+    else
+    {
+	return 1;
+    }
+}
+
+istream&
+operator >> ( istream& in, fgMATERIAL& m )
+{
+    string token;
+
+    for (;;)
+    {
+	in >> token;
+	if ( token == "texture" )
+	{
+	    in >> token >> m.texture_name;
+	}
+	else if ( token == "ambient" )
+	{
+	    in >> token >> m.ambient[0] >> m.ambient[1]
+			>> m.ambient[2] >> m.ambient[3];
+	}
+	else if ( token == "diffuse" )
+	{
+	    in >> token >> m.diffuse[0] >> m.diffuse[1]
+			>> m.diffuse[2] >> m.diffuse[3];
+	}
+	else if ( token == "specular" )
+	{
+	    in >> token >> m.specular[0] >> m.specular[1]
+			>> m.specular[2] >> m.specular[3];
+	}
+	else if ( token == "emissive" )
+	{
+	    in >> token >> m.emissive[0] >> m.emissive[1]
+			>> m.emissive[2] >> m.emissive[3];
+	}
+	else if ( token == "alpha" )
+	{
+	    in >> token >> token;
+	    if ( token == "yes" )
+		m.alpha = 1;
+	    else if ( token == "no" )
+		m.alpha = 0;
+	    else
+	    {
+		fgPrintf( FG_TERRAIN, FG_INFO,
+			  "Bad alpha value '%s'\n", token.c_str() );
+	    }
+	}
+	else if ( token[0] == '}' )
+	{
+	    break;
+	}
+    }
+
+    return in;
+}
+
+void
+fgMATERIAL::load_texture()
+{
+    if ( current_options.get_textures() )
+    {
+	GLubyte *texbuf;
+	int width, height;
+
+	// create the texture object and bind it
+#ifdef GL_VERSION_1_1
+	xglGenTextures(1, &texture_id );
+	xglBindTexture(GL_TEXTURE_2D, texture_id );
+#elif GL_EXT_texture_object
+	xglGenTexturesEXT(1, &texture_id );
+	xglBindTextureEXT(GL_TEXTURE_2D, texture_id );
+#else
+#  error port me
+#endif
+
+	// set the texture parameters for this texture
+	xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
+	xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
+	xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
+			  GL_LINEAR );
+	// xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+	//                   GL_NEAREST_MIPMAP_NEAREST );
+	xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
+			  /* GL_LINEAR */ 
+			  /* GL_NEAREST_MIPMAP_LINEAR */
+			  GL_LINEAR_MIPMAP_LINEAR ) ;
+
+	/* load in the texture data */
+	string tpath = current_options.get_fg_root() + "/Textures/" + 
+	    texture_name + ".rgb";
+	string fg_tpath = tpath + ".gz";
+
+	if ( alpha == 0 ) {
+	    // load rgb texture
+
+	    // Try uncompressed
+	    if ( (texbuf = 
+		  read_rgb_texture(tpath.c_str(), &width, &height)) == 
+		 NULL )
+	    {
+		// Try compressed
+		if ( (texbuf = 
+		      read_rgb_texture(fg_tpath.c_str(), &width, &height)) 
+		     == NULL )
+		{
+		    fgPrintf( FG_GENERAL, FG_EXIT, 
+			      "Error in loading texture %s\n", 
+			      tpath.c_str() );
+		    return;
+		} 
+	    } 
+
+	    /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
+	       GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
+
+	    gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, 
+			       GL_RGB, GL_UNSIGNED_BYTE, texbuf );
+	} else if ( alpha == 1 ) {
+	    // load rgba (alpha) texture
+
+	    // Try uncompressed
+	    if ( (texbuf = 
+		  read_alpha_texture(tpath.c_str(), &width, &height))
+		 == NULL )
+	    {
+		// Try compressed
+		if ((texbuf = 
+		     read_alpha_texture(fg_tpath.c_str(), &width, &height))
+		    == NULL )
+		{
+		    fgPrintf( FG_GENERAL, FG_EXIT, 
+			      "Error in loading texture %s\n",
+			      tpath.c_str() );
+		    return;
+		} 
+	    } 
+
+	    xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+			  GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
+	}
+    }
 }
 
 
@@ -73,211 +222,40 @@ fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
 
 // Load a library of material properties
 int fgMATERIAL_MGR::load_lib ( void ) {
-    fgMATERIAL m;
-    char material_name[256];
-    string mpath, fg_mpath, tpath, fg_tpath;
-    char line[256], *line_ptr, value[256];
-    GLubyte *texbuf;
-    fgFile f;
-    int width, height;
-    int alpha;
+    string material_name;
 
     // build the path name to the material db
-    mpath = current_options.get_fg_root() + "/materials";
-    fg_mpath = mpath + ".gz";
+    string mpath = current_options.get_fg_root() + "/materials";
+    fg_gzifstream in( mpath );
+    if ( ! in )
+	fgPrintf( FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", 
+		  mpath.c_str() );
 
-    // first try "path.gz"
-    if ( (f = fgopen(fg_mpath.c_str(), "rb")) == NULL ) {
-        // next try "path"    
-        if ( (f = fgopen(mpath.c_str(), "rb")) == NULL ) {
-            fgPrintf( FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", 
-		      mpath.c_str() );
-        }       
-    }
-
-    while ( fggets(f, line, 250) != NULL ) {
+    while ( ! in.eof() ) {
         // printf("%s", line);
 
-	// strip leading white space
-	line_ptr = line;
-	while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') ) &&
-		(line_ptr[0] != '\n') ) {
-	    line_ptr++;
-	    
-	}
+	// strip leading white space and comments
+	in.eat_comments();
 
-        if ( line_ptr[0] == '#' ) {
-	    // ignore lines that start with '#'
-	} else if ( line_ptr[0] == '\n' ) {
-	    // ignore blank lines
-	} else if ( strstr(line_ptr, "{") ) {
-	    // start of record
-	    alpha = 0;
-	    m.ambient[0]  = m.ambient[1]  = m.ambient[2]  = m.ambient[3]  = 0.0;
-	    m.diffuse[0]  = m.diffuse[1]  = m.diffuse[2]  = m.diffuse[3]  = 0.0;
-	    m.specular[0] = m.specular[1] = m.specular[2] = m.specular[3] = 0.0;
-	    m.emissive[0] = m.emissive[1] = m.emissive[2] = m.emissive[3] = 0.0;
+	// set to zero to prevent its value accidently being '{'
+	// after a failed >> operation.
+	char token = 0;
 
-	    material_name[0] = '\0';
-	    sscanf(line_ptr, "%s", material_name);
-	    if ( ! strlen(material_name) ) {
-		fgPrintf( FG_TERRAIN, FG_INFO, "Bad material name in '%s'\n",
-			  line );
-	    }
-	    printf("  Loading material = %s\n", material_name);
-	} else if ( strncmp(line_ptr, "alpha", 5) == 0 ) {
-	    line_ptr += 5;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    sscanf(line_ptr, "%s\n", value);
-	    if ( strcmp(value, "no") == 0 ) {
-		alpha = 0;
-	    } else if ( strcmp(value, "yes") == 0 ) {
-		alpha = 1;
-	    } else {
-		fgPrintf( FG_TERRAIN, FG_INFO, "Bad alpha value '%s'\n", line );
-	    }
-	} else if ( (strncmp(line_ptr, "texture", 7) == 0) &&
-		    !current_options.get_textures() ) {
-	    // do nothing
-	} else if ( strncmp(line_ptr, "texture", 7) == 0 ) {
-	    line_ptr += 7;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    // printf("texture name = %s\n", line_ptr);
-	    sscanf(line_ptr, "%s\n", m.texture_name);
+	in.stream() >> material_name >> token;
 
-	    // create the texture object and bind it
-#ifdef GL_VERSION_1_1
-	    xglGenTextures(1, &m.texture_id);
-	    xglBindTexture(GL_TEXTURE_2D, m.texture_id);
-#elif GL_EXT_texture_object
-	    xglGenTexturesEXT(1, &m.texture_id);
-	    xglBindTextureEXT(GL_TEXTURE_2D, m.texture_id);
-#else
-#  error port me
-#endif
-
-	    // set the texture parameters for this texture
-	    xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
-	    xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
-	    xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
-			      GL_LINEAR );
-	    // xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
-	    //                   GL_NEAREST_MIPMAP_NEAREST );
-	    xglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
-			      /* GL_LINEAR */ 
-			      /* GL_NEAREST_MIPMAP_LINEAR */
-			      GL_LINEAR_MIPMAP_LINEAR ) ;
-
-	    /* load in the texture data */
-	    tpath = current_options.get_fg_root() + "/Textures/" + 
-		m.texture_name + ".rgb";
-	    fg_tpath = tpath + ".gz";
-
-	    if ( alpha == 0 ) {
-		// load rgb texture
-
-		// Try uncompressed
-		if ( (texbuf = 
-		      read_rgb_texture(tpath.c_str(), &width, &height)) == 
-		     NULL )
-		{
-		    // Try compressed
-		    if ( (texbuf = 
-			  read_rgb_texture(fg_tpath.c_str(), &width, &height)) 
-			 == NULL )
-		    {
-			fgPrintf( FG_GENERAL, FG_EXIT, 
-				  "Error in loading texture %s\n", 
-				  tpath.c_str() );
-			return(0);
-		    } 
-		} 
-
-		/* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
-			      GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
-
-		gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, width, height, 
-				    GL_RGB, GL_UNSIGNED_BYTE, texbuf );
-	    } else if ( alpha == 1 ) {
-		// load rgba (alpha) texture
-
-		// Try uncompressed
-		if ( (texbuf = 
-		      read_alpha_texture(tpath.c_str(), &width, &height))
-		     == NULL )
-		{
-		    // Try compressed
-		    if ((texbuf = 
-			 read_alpha_texture(fg_tpath.c_str(), &width, &height))
-			== NULL )
-		    {
-			fgPrintf( FG_GENERAL, FG_EXIT, 
-				  "Error in loading texture %s\n",
-				  tpath.c_str() );
-			return(0);
-		    } 
-		} 
-
-		xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
-			      GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
-	    }
-
-	} else if ( strncmp(line_ptr, "ambient", 7) == 0 ) {
-	    line_ptr += 7;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    sscanf( line_ptr, "%f %f %f %f", 
-		    &m.ambient[0], &m.ambient[1], &m.ambient[2], &m.ambient[3]);
-	} else if ( strncmp(line_ptr, "diffuse", 7) == 0 ) {
-	    line_ptr += 7;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    sscanf( line_ptr, "%f %f %f %f", 
-		    &m.diffuse[0], &m.diffuse[1], &m.diffuse[2], &m.diffuse[3]);
-	} else if ( strncmp(line_ptr, "specular", 8) == 0 ) {
-	    line_ptr += 8;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    sscanf( line_ptr, "%f %f %f %f", 
-		    &m.specular[0], &m.specular[1], 
-		    &m.specular[2], &m.specular[3]);
-	} else if ( strncmp(line_ptr, "emissive", 8) == 0 ) {
-	    line_ptr += 8;
-	    while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') || 
-		      (line_ptr[0] == '=') ) &&
-		    (line_ptr[0] != '\n') ) {
-		line_ptr++;
-	    }
-	    sscanf( line_ptr, "%f %f %f %f", 
-		    &m.emissive[0], &m.emissive[1], 
-		    &m.emissive[2], &m.emissive[3]);
-	} else if ( line_ptr[0] == '}' ) {
-	    // end of record, lets add this one to the list
+	if ( token == '{' ) {
+	    cout << "Loading material " << material_name << endl;
+	    fgMATERIAL m;
+	    in.stream() >> m;
 	    material_mgr.material_map[material_name] = m;
-	} else {
-	    fgPrintf(FG_TERRAIN, FG_INFO, 
-		     "Unknown line in material properties file\n");
 	}
     }
 
-    fgclose(f);
+    for ( iterator it = material_map.begin();
+	  it != material_map.end(); ++it )
+    {
+	it->second.load_texture();
+    }
 
     return(1);
 }
@@ -285,20 +263,26 @@ int fgMATERIAL_MGR::load_lib ( void ) {
 
 // Initialize the transient list of fragments for each material property
 void fgMATERIAL_MGR::init_transient_material_lists( void ) {
-    map < string, fgMATERIAL, less<string> > :: iterator mapcurrent = 
-	material_mgr.material_map.begin();
-    map < string, fgMATERIAL, less<string> > :: iterator maplast = 
-	material_mgr.material_map.end();
-
-    while ( mapcurrent != maplast ) {
-        // (char *)key = (*mapcurrent).first;
-        // (fgMATERIAL)value = (*mapcurrent).second;
-	(*mapcurrent).second.list_size = 0;
-
-        *mapcurrent++;
+    for ( iterator it = material_map.begin();
+	  it != material_map.end(); ++it )
+    {
+	it->second.init_sort_list();
     }
 }
 
+bool
+fgMATERIAL_MGR::find( const string& material, fgMATERIAL*& mtl_ptr )
+{
+    iterator it = material_map.find( material );
+    if ( it != material_map.end() )
+    {
+	mtl_ptr = &(it->second);
+	return true;
+    }
+
+    return false;
+}
+
 
 // Destructor
 fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
@@ -306,6 +290,64 @@ fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
 
 
 // $Log$
+// Revision 1.4  1998/09/01 19:03:08  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.3  1998/08/27 17:02:09  curt
 // Contributions from Bernie Bright <bbright@c031.aone.net.au>
 // - use strings for fg_root and airport_id and added methods to return
diff --git a/Objects/material.hxx b/Objects/material.hxx
index a9428eea4..0e1302fd1 100644
--- a/Objects/material.hxx
+++ b/Objects/material.hxx
@@ -53,7 +53,8 @@ extern "C" void *memset(void *, int, size_t);
 using namespace std;
 #endif
 
-#include "fragment.hxx"
+// forward decl.
+class fgFRAGMENT;
 
 
 #define FG_MAX_MATERIAL_FRAGS 800
@@ -67,7 +68,10 @@ public:
     GLuint texture_id;
 
     // file name of texture
-    char texture_name[256];
+    string texture_name;
+
+    // alpha texture?
+    int alpha;
 
     // material properties
     GLfloat ambient[4], diffuse[4], specular[4], emissive[4];
@@ -82,13 +86,19 @@ public:
     fgMATERIAL ( void );
 
     // Sorting routines
-    void init_sort_list( void );
+    void init_sort_list( void ) {
+	list_size = 0;
+    }
+
     int append_sort_list( fgFRAGMENT *object );
 
+    void load_texture();
+
     // Destructor
     ~fgMATERIAL ( void );
 };
 
+istream& operator >> ( istream& in, fgMATERIAL& m );
 
 // Material management class
 class fgMATERIAL_MGR {
@@ -96,7 +106,11 @@ class fgMATERIAL_MGR {
 public:
 
     // associative array of materials
-    map < string, fgMATERIAL, less<string> > material_map;
+    typedef map < string, fgMATERIAL, less<string> > container;
+    typedef container::iterator iterator;
+    typedef container::const_iterator const_iterator;
+
+    container material_map;
 
     // Constructor
     fgMATERIAL_MGR ( void );
@@ -107,6 +121,8 @@ public:
     // Initialize the transient list of fragments for each material property
     void init_transient_material_lists( void );
 
+    bool find( const string& material, fgMATERIAL*& mtl_ptr );
+
     // Destructor
     ~fgMATERIAL_MGR ( void );
 };
@@ -120,6 +136,64 @@ extern fgMATERIAL_MGR material_mgr;
 
 
 // $Log$
+// Revision 1.2  1998/09/01 19:03:09  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.1  1998/08/25 16:51:24  curt
 // Moved from ../Scenery
 //
diff --git a/Objects/obj.cxx b/Objects/obj.cxx
index f51931bb1..ac1ab9a1b 100644
--- a/Objects/obj.cxx
+++ b/Objects/obj.cxx
@@ -42,6 +42,7 @@ extern "C" void *memset(void *, int, size_t);
 
 #include <string>       // Standard C++ library
 #include <map>          // STL
+#include <ctype.h>      // isdigit()
 
 #ifdef NEEDNAMESPACESTD
 using namespace std;
@@ -54,6 +55,8 @@ using namespace std;
 #include <Math/mat3.h>
 #include <Math/fg_random.h>
 #include <Math/polar3d.hxx>
+#include <Misc/stopwatch.hxx>
+#include <Misc/fgstream.hxx>
 #include <Scenery/tile.hxx>
 
 #include "material.hxx"
@@ -103,36 +106,30 @@ fgPoint3d calc_tex_coords(double *node, fgPoint3d *ref) {
 
 
 // Load a .obj file and build the GL fragment list
-int fgObjLoad(char *path, fgTILE *t) {
+int fgObjLoad( const string& path, fgTILE *t) {
     fgFRAGMENT fragment;
     fgPoint3d pp;
-    char fgpath[256], line[256], material[256];
     double approx_normal[3], normal[3], scale;
     // double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin;
     // GLfloat sgenparams[] = { 1.0, 0.0, 0.0, 0.0 };
     GLint display_list;
-    fgFile f;
     int shading;
     int in_fragment, in_faces, vncount, n1, n2, n3, n4;
     int last1, last2, odd;
     double (*nodes)[3];
     fgPoint3d *center;
 
-    // First try "path.gz" (compressed format)
-    strcpy(fgpath, path);
-    strcat(fgpath, ".gz");
-    if ( (f = fgopen(fgpath, "rb")) == NULL ) {
-	// Next try "path" (uncompressed format)
-	strcpy(fgpath, path);
-	if ( (f = fgopen(fgpath, "rb")) == NULL ) {
-	    // Next try "path.obj" (uncompressed format)
-	    strcat(fgpath, ".gz");
-	    if ( (f = fgopen(fgpath, "rb")) == NULL ) {
-		strcpy(fgpath, path);
-		fgPrintf( FG_TERRAIN, FG_ALERT, 
-			  "Cannot open file: %s\n", fgpath );
-		return(0);
-	    }
+    // Attempt to open "path.gz" or "path"
+    fg_gzifstream in( path );
+    if ( ! in )
+    {
+	// Attempt to open "path.obj" or "path.obj.gz"
+	in.open( path + ".obj" );
+	if ( ! in )
+	{
+	    fgPrintf( FG_TERRAIN, FG_ALERT, 
+		      "Cannot open file: %s\n", path.c_str() );
+	    return 0;
 	}
     }
 
@@ -145,48 +142,59 @@ int fgObjLoad(char *path, fgTILE *t) {
     nodes = t->nodes;
     center = &t->center;
 
-    while ( fggets(f, line, 250) != NULL ) {
-	if ( line[0] == '#' ) {
-	    // comment -- ignore
-	} else if ( line[0] == '\n' ) {
-	    // empty line -- ignore
-	} else if ( strncmp(line, "gbs ", 4) == 0 ) {
-	    // reference point (center offset)
-	    sscanf(line, "gbs %lf %lf %lf %lf\n", 
-		   &t->center.x, &t->center.y, &t->center.z, 
-		   &t->bounding_radius);
-	} else if ( strncmp(line, "bs ", 3) == 0 ) {
-	    // reference point (center offset)
-	    sscanf(line, "bs %lf %lf %lf %lf\n", 
-		   &fragment.center.x, &fragment.center.y, &fragment.center.z, 
-		   &fragment.bounding_radius);
-	} else if ( strncmp(line, "v ", 2) == 0 ) {
-	    // node (vertex)
-	    if ( t->ncount < MAX_NODES ) {
-		// fgPrintf( FG_TERRAIN, FG_DEBUG, "vertex = %s", line);
-		sscanf(line, "v %lf %lf %lf\n", 
-		       &(t->nodes[t->ncount][0]), &(t->nodes[t->ncount][1]), 
-		       &(t->nodes[t->ncount][2]));
+    StopWatch stopwatch;
+    stopwatch.start();
+    while ( ! in.eof() )
+    {
+	// ignore comments and blank lines.
+	in.eat_comments();
 
-		t->ncount++;
-
-	    } else {
-		fgPrintf( FG_TERRAIN, FG_EXIT, 
-			  "Read too many nodes ... dying :-(\n");
-	    }
-	} else if ( strncmp(line, "vn ", 3) == 0 ) {
+	string token;
+	in.stream() >> token;
+	if ( token == "gbs" )
+	{
+	    // reference point (center offset)
+	    in.stream() >> t->center.x
+			>> t->center.y
+			>> t->center.z
+			>> t->bounding_radius;
+	}
+	else if ( token == "bs" )
+	{
+	    // reference point (center offset)
+	    in.stream() >> fragment.center.x
+			>> fragment.center.y
+			>> fragment.center.z
+			>> fragment.bounding_radius;
+	}
+	else if ( token == "vn" )
+	{
 	    // vertex normal
 	    if ( vncount < MAX_NODES ) {
-		// fgPrintf( FG_TERRAIN, FG_DEBUG, "vertex normal = %s", line);
-		sscanf(line, "vn %lf %lf %lf\n", 
-		       &normals[vncount][0], &normals[vncount][1], 
-		       &normals[vncount][2]);
+		in.stream() >> normals[vncount][0]
+			    >> normals[vncount][1]
+			    >> normals[vncount][2];
 		vncount++;
 	    } else {
 		fgPrintf( FG_TERRAIN, FG_EXIT, 
 			  "Read too many vertex normals ... dying :-(\n");
 	    }
-	} else if ( strncmp(line, "usemtl ", 7) == 0 ) {
+	}
+	else if ( token[0] == 'v' )
+	{
+	    // node (vertex)
+	    if ( t->ncount < MAX_NODES ) {
+		in.stream() >> t->nodes[t->ncount][0]
+			    >> t->nodes[t->ncount][1]
+			    >> t->nodes[t->ncount][2];
+		t->ncount++;
+	    } else {
+		fgPrintf( FG_TERRAIN, FG_EXIT, 
+			  "Read too many nodes ... dying :-(\n");
+	    }
+	}
+	else if ( token == "usemtl" )
+	{
 	    // material property specification
 
 	    // this also signals the start of a new fragment
@@ -211,26 +219,18 @@ int fgObjLoad(char *path, fgTILE *t) {
 	    // reset the existing face list
 	    // printf("cleaning a fragment with %d faces\n", 
 	    //        fragment.faces.size());
-	    while ( fragment.faces.size() ) {
-		//  printf("emptying face list\n");
-		fragment.faces.pop_front();
-	    }
+	    fragment.init();
 
 	    // scan the material line
-	    sscanf(line, "usemtl %s\n", material);
-
-	    // give the fragment a pointer back to the tile
+	    string material;
+	    in.stream() >> material;
 	    fragment.tile_ptr = t;
 
 	    // find this material in the properties list
-	    map < string, fgMATERIAL, less<string> > :: iterator myfind = 
-		material_mgr.material_map.find(material);
-	    if ( myfind == material_mgr.material_map.end() ) {
+	    if ( ! material_mgr.find( material, fragment.material_ptr )) {
 		fgPrintf( FG_TERRAIN, FG_ALERT, 
 			  "Ack! unknown usemtl name = %s in %s\n",
-			  material, path);
-	    } else {
-		fragment.material_ptr = &((*myfind).second);
+			  material.c_str(), path.c_str() );
 	    }
 
 	    // initialize the fragment transformation matrix
@@ -241,18 +241,13 @@ int fgObjLoad(char *path, fgTILE *t) {
 	    fragment.matrix[0] = fragment.matrix[5] =
 		fragment.matrix[10] = fragment.matrix[15] = 1.0;
 	    */
-	
-	    // initialize fragment face counter
-	    fragment.num_faces = 0;
-		
-	} else if ( line[0] == 't' ) {
+	} else if ( token[0] == 't' ) {
 	    // start a new triangle strip
 
 	    n1 = n2 = n3 = n4 = 0;
 
 	    // fgPrintf( FG_TERRAIN, FG_DEBUG, "    new tri strip = %s", line);
-	    sscanf(line, "t %d %d %d %d\n", &n1, &n2, &n3, &n4);
-
+	    in.stream() >> n1 >> n2 >> n3;
 	    fragment.add_face(n1, n2, n3);
 
 	    // fgPrintf( FG_TERRAIN, FG_DEBUG, "(t) = ");
@@ -340,7 +335,7 @@ int fgObjLoad(char *path, fgTILE *t) {
 		last1 = n3;
 		last2 = n4;
 	    }
-	} else if ( line[0] == 'f' ) {
+	} else if ( token[0] == 'f' ) {
 	    // unoptimized face
 
 	    if ( !in_faces ) {
@@ -349,8 +344,7 @@ int fgObjLoad(char *path, fgTILE *t) {
 	    }
 
 	    // fgPrintf( FG_TERRAIN, FG_DEBUG, "new triangle = %s", line);*/
-	    sscanf(line, "f %d %d %d\n", &n1, &n2, &n3);
-
+	    in.stream() >> n1 >> n2 >> n3;
 	    fragment.add_face(n1, n2, n3);
 
             // xglNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]);
@@ -373,13 +367,28 @@ int fgObjLoad(char *path, fgTILE *t) {
             xglTexCoord2f(pp.lon, pp.lat);
 	    // xglVertex3d(t->nodes[n3][0], t->nodes[n3][1], t->nodes[n3][2]);
 	    xglVertex3dv(nodes[n3]);
-	} else if ( line[0] == 'q' ) {
+	} else if ( token[0] == 'q' ) {
 	    // continue a triangle strip
 	    n1 = n2 = 0;
 
 	    // fgPrintf( FG_TERRAIN, FG_DEBUG, "continued tri strip = %s ", 
 	    //           line);
-	    sscanf(line, "q %d %d\n", &n1, &n2);
+	    in.stream() >> n1;
+
+	    // There can be one or two values 
+	    char c;
+	    while ( in.get(c) )
+	    {
+		if ( c == '\n' )
+		    break; // only the one
+
+		if ( isdigit(c) )
+		{
+		    in.putback(c);
+		    in.stream() >> n2;
+		    break;
+		}
+	    }
 	    // fgPrintf( FG_TERRAIN, FG_DEBUG, "read %d %d\n", n1, n2);
 
 	    if ( odd ) {
@@ -450,10 +459,13 @@ int fgObjLoad(char *path, fgTILE *t) {
 		last2 = n2;
 	    }
 	} else {
-	    fgPrintf( FG_TERRAIN, FG_WARN, "Unknown line in %s = %s\n", 
-		      path, line);
+	    fgPrintf( FG_TERRAIN, FG_WARN, "Unknown token in %s = %s\n", 
+		      path.c_str(), token.c_str() );
 	}
     }
+    stopwatch.stop();
+    fgPrintf( FG_TERRAIN, FG_INFO, "Loaded %s in %f seconds\n",
+	      path.c_str(), stopwatch.elapsedSeconds() );
 
     if ( in_fragment ) {
 	// close out the previous structure and start the next
@@ -482,13 +494,69 @@ int fgObjLoad(char *path, fgTILE *t) {
     xglEnd();
     */   
 
-    fgclose(f);
-
     return(1);
 }
 
 
 // $Log$
+// Revision 1.2  1998/09/01 19:03:09  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.1  1998/08/25 16:51:25  curt
 // Moved from ../Scenery
 //
diff --git a/Objects/obj.hxx b/Objects/obj.hxx
index 96c6aedfd..c999a22ea 100644
--- a/Objects/obj.hxx
+++ b/Objects/obj.hxx
@@ -41,19 +41,79 @@
 
 #include <GL/glut.h>
 
+#include <string>
+
 #include <Include/fg_types.h>
 
 #include <Scenery/tile.hxx>
 
 
 // Load a .obj file and build the GL fragment list
-int fgObjLoad(char *path, fgTILE *tile);
+int fgObjLoad(const string& path, fgTILE *tile);
 
 
 #endif // _OBJ_HXX
 
 
 // $Log$
+// Revision 1.2  1998/09/01 19:03:10  curt
+// Changes contributed by Bernie Bright <bbright@c031.aone.net.au>
+//  - The new classes in libmisc.tgz define a stream interface into zlib.
+//    I've put these in a new directory, Lib/Misc.  Feel free to rename it
+//    to something more appropriate.  However you'll have to change the
+//    include directives in all the other files.  Additionally you'll have
+//    add the library to Lib/Makefile.am and Simulator/Main/Makefile.am.
+//
+//    The StopWatch class in Lib/Misc requires a HAVE_GETRUSAGE autoconf
+//    test so I've included the required changes in config.tgz.
+//
+//    There are a fair few changes to Simulator/Objects as I've moved
+//    things around.  Loading tiles is quicker but thats not where the delay
+//    is.  Tile loading takes a few tenths of a second per file on a P200
+//    but it seems to be the post-processing that leads to a noticeable
+//    blip in framerate.  I suppose its time to start profiling to see where
+//    the delays are.
+//
+//    I've included a brief description of each archives contents.
+//
+// Lib/Misc/
+//   zfstream.cxx
+//   zfstream.hxx
+//     C++ stream interface into zlib.
+//     Taken from zlib-1.1.3/contrib/iostream/.
+//     Minor mods for STL compatibility.
+//     There's no copyright associated with these so I assume they're
+//     covered by zlib's.
+//
+//   fgstream.cxx
+//   fgstream.hxx
+//     FlightGear input stream using gz_ifstream.  Tries to open the
+//     given filename.  If that fails then filename is examined and a
+//     ".gz" suffix is removed or appended and that file is opened.
+//
+//   stopwatch.hxx
+//     A simple timer for benchmarking.  Not used in production code.
+//     Taken from the Blitz++ project.  Covered by GPL.
+//
+//   strutils.cxx
+//   strutils.hxx
+//     Some simple string manipulation routines.
+//
+// Simulator/Airports/
+//   Load airports database using fgstream.
+//   Changed fgAIRPORTS to use set<> instead of map<>.
+//   Added bool fgAIRPORTS::search() as a neater way doing the lookup.
+//   Returns true if found.
+//
+// Simulator/Astro/
+//   Modified fgStarsInit() to load stars database using fgstream.
+//
+// Simulator/Objects/
+//   Modified fgObjLoad() to use fgstream.
+//   Modified fgMATERIAL_MGR::load_lib() to use fgstream.
+//   Many changes to fgMATERIAL.
+//   Some changes to fgFRAGMENT but I forget what!
+//
 // Revision 1.1  1998/08/25 16:51:26  curt
 // Moved from ../Scenery
 //