From 747bc7c6b4756398a3a4732c0956e5421ef11288 Mon Sep 17 00:00:00 2001 From: curt <curt> Date: Tue, 1 Sep 1998 19:02:53 +0000 Subject: [PATCH] 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! --- Airports/simple.cxx | 165 +++++++++++---- Airports/simple.hxx | 108 ++++++++-- Astro/stars.cxx | 155 +++++++++------ Main/Makefile.am | 3 +- Objects/fragment.cxx | 189 ++++++++---------- Objects/fragment.hxx | 122 ++++++++++-- Objects/material.cxx | 464 +++++++++++++++++++++++-------------------- Objects/material.hxx | 82 +++++++- Objects/obj.cxx | 230 +++++++++++++-------- Objects/obj.hxx | 62 +++++- 10 files changed, 1053 insertions(+), 527 deletions(-) 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 //