]> git.mxchange.org Git - flightgear.git/blobdiff - Objects/material.cxx
Converted to new logstream debugging facility. This allows release
[flightgear.git] / Objects / material.cxx
index 27bd64c362ee7d0e67f9e6feb6dcb28af4c3b809..a2dc6543e7f7f825bbd9e4ebd2b7a04473344e6a 100644 (file)
 #include <XGL/xgl.h>
 
 #include <string.h>
+#include <string>
 
-#include <Debug/fg_debug.h>
-#include <Include/fg_zlib.h>
+#include "Include/fg_stl_config.h"
+#include <Debug/logstream.hxx>
 #include <Main/options.hxx>
+#include <Misc/fgstream.hxx>
+#include <Main/views.hxx>
+#include <Scenery/tile.hxx>
 
 #include "material.hxx"
+#include "fragment.hxx"
 #include "texload.h"
 
+
 // global material management class
 fgMATERIAL_MGR material_mgr;
 
 
 // Constructor
-fgMATERIAL::fgMATERIAL ( void ) {
+fgMATERIAL::fgMATERIAL ( void )
+    : texture_name(""),
+      alpha(0)
+      // , list_size(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 )
+{
+    if ( list_size < FG_MAX_MATERIAL_FRAGS ) {
+       list[ list_size++ ] = object;
+       return 1;
+    } else {
+       return 0;
+    }
+}
+*/
+
+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
+           {
+               FG_LOG( FG_TERRAIN, FG_INFO, "Bad alpha value " << token );
+           }
+       }
+       else if ( token[0] == '}' )
+       {
+           break;
+       }
+    }
 
-// Sorting routines
-void fgMATERIAL::init_sort_list( void ) {
+    return in;
 }
 
+void
+fgMATERIAL::load_texture()
+{
+       GLubyte *texbuf;
+       int width, height;
 
-int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) {
-    return(0);
+       // 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 )
+               {
+                   FG_LOG( FG_GENERAL, FG_ALERT, 
+                           "Error in loading texture " << tpath );
+                   exit(-1);
+               } 
+           } 
+
+           /* 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 )
+               {
+                   FG_LOG( FG_GENERAL, FG_ALERT, 
+                           "Error in loading texture " << tpath );
+                   exit(-1);
+               } 
+           } 
+
+           xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+                         GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
+       }
 }
 
 
@@ -68,244 +219,247 @@ fgMATERIAL::~fgMATERIAL ( void ) {
 
 // Constructor
 fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
+    textures_loaded = false;
 }
 
 
-// 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;
-
-    // build the path name to the material db
-    mpath = current_options.get_fg_root() + "/materials";
-    fg_mpath = mpath + ".gz";
-
-    // 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 ) {
-        // printf("%s", line);
+void
+fgMATERIAL::render_fragments()
+{
+    // cout << "rendering " + texture_name + " = " << list_size << "\n";
 
-       // strip leading white space
-       line_ptr = line;
-       while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') ) &&
-               (line_ptr[0] != '\n') ) {
-           line_ptr++;
-           
-       }
+    if ( empty() )
+       return;
 
-        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;
-
-           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);
-
-           // create the texture object and bind it
+    if ( current_options.get_textures() )
+    {
 #ifdef GL_VERSION_1_1
-           xglGenTextures(1, &m.texture_id);
-           xglBindTexture(GL_TEXTURE_2D, m.texture_id);
+       xglBindTexture(GL_TEXTURE_2D, texture_id);
 #elif GL_EXT_texture_object
-           xglGenTexturesEXT(1, &m.texture_id);
-           xglBindTextureEXT(GL_TEXTURE_2D, m.texture_id);
+       xglBindTextureEXT(GL_TEXTURE_2D, texture_id);
 #else
 #  error port me
 #endif
+    } else {
+       xglMaterialfv (GL_FRONT, GL_AMBIENT, ambient);
+       xglMaterialfv (GL_FRONT, GL_DIFFUSE, diffuse);
+    }
 
-           // 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);
-                   } 
-               } 
+    fgTILE* last_tile_ptr = NULL;
+    frag_list_iterator current = list.begin();
+    frag_list_iterator last = list.end();
+
+    for ( ; current != last; ++current ) {
+       fgFRAGMENT* frag_ptr = *current;
+       current_view.tris_rendered += frag_ptr->num_faces();
+       if ( frag_ptr->tile_ptr != last_tile_ptr )
+       {
+           // new tile, new translate
+           last_tile_ptr = frag_ptr->tile_ptr;
+           xglLoadMatrixd( frag_ptr->tile_ptr->model_view );
+       }
 
-               /* xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
-                             GL_RGB, GL_UNSIGNED_BYTE, texbuf); */
+       // Woohoo!!!  We finally get to draw something!
+       // printf("  display_list = %d\n", frag_ptr->display_list);
+       xglCallList( frag_ptr->display_list );
+    }
+}
 
-               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);
-                   } 
-               } 
+// Load a library of material properties
+int
+fgMATERIAL_MGR::load_lib ( void )
+{
+    string material_name;
 
-               xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
-                             GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
-           }
+    // build the path name to the material db
+    string mpath = current_options.get_fg_root() + "/materials";
+    fg_gzifstream in( mpath );
+    if ( ! in ) {
+       FG_LOG( FG_GENERAL, FG_ALERT, "Cannot open file: " << mpath );
+       exit(-1);
+    }
 
-       } 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++;
+    while ( ! in.eof() ) {
+        // printf("%s", line);
+
+       // strip leading white space and comments
+       in >> skipcomment;
+
+       // set to zero to prevent its value accidently being '{'
+       // after a failed >> operation.
+       char token = 0;
+
+       in >> material_name >> token;
+
+       if ( token == '{' ) {
+           printf( "  Loading material %s\n", material_name.c_str() );
+           fgMATERIAL m;
+           in >> m;
+
+           if ( current_options.get_textures() ) {
+               m.load_texture();
            }
-           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
+
            material_mgr.material_map[material_name] = m;
-       } else {
-           fgPrintf(FG_TERRAIN, FG_INFO, 
-                    "Unknown line in material properties file\n");
        }
     }
 
-    fgclose(f);
+    if ( current_options.get_textures() ) {
+       textures_loaded = true;
+    }
 
     return(1);
 }
 
 
 // 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++;
+void
+fgMATERIAL_MGR::init_transient_material_lists( void )
+{
+    iterator last = end();
+    for ( iterator it = begin(); it != last; ++it )
+    {
+       (*it).second.init_sort_list();
     }
 }
 
 
+bool
+fgMATERIAL_MGR::find( const string& material, fgMATERIAL*& mtl_ptr )
+{
+    iterator it = material_map.find( material );
+    if ( it != end() )
+    {
+       mtl_ptr = &((*it).second);
+       return true;
+    }
+
+    return false;
+}
+
+
 // Destructor
 fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
 }
 
 
+void
+fgMATERIAL_MGR::render_fragments()
+{
+    current_view.tris_rendered = 0;
+    iterator last = end();
+    for ( iterator current = begin(); current != last; ++current )
+       (*current).second.render_fragments();
+}
+
+
 // $Log$
+// Revision 1.10  1998/11/06 21:18:17  curt
+// Converted to new logstream debugging facility.  This allows release
+// builds with no messages at all (and no performance impact) by using
+// the -DFG_NDEBUG flag.
+//
+// Revision 1.9  1998/11/06 14:47:05  curt
+// Changes to track Bernie's updates to fgstream.
+//
+// Revision 1.8  1998/10/12 23:49:17  curt
+// Changes from NHV to make the code more dynamic with fewer hard coded limits.
+//
+// Revision 1.7  1998/09/17 18:35:52  curt
+// Tweaks and optimizations by Norman Vine.
+//
+// Revision 1.6  1998/09/15 01:35:05  curt
+// cleaned up my fragment.num_faces hack :-) to use the STL (no need in
+// duplicating work.)
+// Tweaked fgTileMgrRender() do not calc tile matrix unless necessary.
+// removed some unneeded stuff from fgTileMgrCurElev()
+//
+// Revision 1.5  1998/09/10 19:07:11  curt
+// /Simulator/Objects/fragment.hxx
+//   Nested fgFACE inside fgFRAGMENT since its not used anywhere else.
+//
+// ./Simulator/Objects/material.cxx
+// ./Simulator/Objects/material.hxx
+//   Made fgMATERIAL and fgMATERIAL_MGR bona fide classes with private
+//   data members - that should keep the rabble happy :)
+//
+// ./Simulator/Scenery/tilemgr.cxx
+//   In viewable() delay evaluation of eye[0] and eye[1] in until they're
+//   actually needed.
+//   Change to fgTileMgrRender() to call fgMATERIAL_MGR::render_fragments()
+//   method.
+//
+// ./Include/fg_stl_config.h
+// ./Include/auto_ptr.hxx
+//   Added support for g++ 2.7.
+//   Further changes to other files are forthcoming.
+//
+// Brief summary of changes required for g++ 2.7.
+//   operator->() not supported by iterators: use (*i).x instead of i->x
+//   default template arguments not supported,
+//   <functional> doesn't have mem_fun_ref() needed by callbacks.
+//   some std include files have different names.
+//   template member functions not supported.
+//
+// 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