diff --git a/Scenery/material.cxx b/Scenery/material.cxx index ff105035d..8f4a56761 100644 --- a/Scenery/material.cxx +++ b/Scenery/material.cxx @@ -40,6 +40,10 @@ #include "material.hxx" +// global material management class +fgMATERIAL_MGR material_mgr; + + // Constructor fgMATERIAL::fgMATERIAL ( void ) { } @@ -64,8 +68,11 @@ fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) { // Load a library of material properties int fgMATERIAL_MGR::load_lib ( void ) { + fgMATERIAL m; fgOPTIONS *o; + char material_name[256]; char path[256], fgpath[256]; + char line[256], *line_ptr; fgFile f; o = ¤t_options; @@ -86,18 +93,123 @@ int fgMATERIAL_MGR::load_lib ( void ) { } } + while ( fggets(f, line, 250) != NULL ) { + // printf("%s", line); + + // strip leading white space + line_ptr = line; + while ( ( (line_ptr[0] == ' ') || (line_ptr[0] == '\t') ) && + (line_ptr[0] != '\n') ) { + line_ptr++; + + } + + 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 + 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, "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); + } 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 + material_mgr.material_map[material_name] = m; + } else { + fgPrintf(FG_TERRAIN, FG_INFO, + "Unknown line in material properties file\n"); + } + } + fgclose(f); return(1); } +// Initialize the transient list of fragments for each material property +void fgMATERIAL_MGR::init_transient_material_lists( void ) { + map < string, fgMATERIAL, less > :: iterator mapcurrent = + material_mgr.material_map.begin(); + map < string, fgMATERIAL, less > :: iterator maplast = + material_mgr.material_map.end(); + + while ( mapcurrent != maplast ) { + // (char *)key = (*mapcurrent).first; + // (fgMATERIAL)value = (*mapcurrent).second; + (*mapcurrent).second.list_size = 0; + + *mapcurrent++; + } +} + + // Destructor fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) { } // $Log$ +// Revision 1.3 1998/06/05 22:39:53 curt +// Working on sorting by, and rendering by material properties. +// // Revision 1.2 1998/06/01 17:56:20 curt // Incremental additions to material.cxx (not fully functional) // Tweaked vfc_ratio math to avoid divide by zero. diff --git a/Scenery/material.hxx b/Scenery/material.hxx index 40a5fdf68..e599fd286 100644 --- a/Scenery/material.hxx +++ b/Scenery/material.hxx @@ -54,9 +54,11 @@ class fgMATERIAL { public: + // file name of texture + char texture_name[256]; // material properties - GLfloat ambient[4], diffuse[4], specular[4]; + GLfloat ambient[4], diffuse[4], specular[4], emissive[4]; GLint texture_ptr; // transient list of objects with this material type (used for sorting @@ -82,7 +84,7 @@ class fgMATERIAL_MGR { public: // associative array of materials - map < string, fgMATERIAL, less > materials; + map < string, fgMATERIAL, less > material_map; // Constructor fgMATERIAL_MGR ( void ); @@ -90,15 +92,25 @@ public: // Load a library of material properties int load_lib ( void ); + // Initialize the transient list of fragments for each material property + void init_transient_material_lists( void ); + // Destructor ~fgMATERIAL_MGR ( void ); }; +// global material management class +extern fgMATERIAL_MGR material_mgr; + + #endif // _MATERIAL_HXX // $Log$ +// Revision 1.4 1998/06/05 22:39:53 curt +// Working on sorting by, and rendering by material properties. +// // Revision 1.3 1998/06/03 00:47:50 curt // No .h for STL includes. // Minor view culling optimizations. diff --git a/Scenery/obj.cxx b/Scenery/obj.cxx index fab7777f5..27a9207f2 100644 --- a/Scenery/obj.cxx +++ b/Scenery/obj.cxx @@ -35,6 +35,9 @@ #include #include +#include // STL +#include // Standard C++ library + #include #include #include @@ -43,6 +46,7 @@ #include #include +#include "material.hxx" #include "obj.hxx" #include "scenery.hxx" #include "tile.hxx" @@ -147,6 +151,7 @@ int fgObjLoad(char *path, fgTILE *tile) { sscanf(line, "bs %lf %lf %lf %lf\n", &fragment.center.x, &fragment.center.y, &fragment.center.z, &fragment.bounding_radius); + fragment.tile_center = tile->center; } else if ( strncmp(line, "v ", 2) == 0 ) { // node (vertex) if ( ncount < MAXNODES ) { @@ -196,6 +201,18 @@ int fgObjLoad(char *path, fgTILE *tile) { // scan the material line sscanf(line, "usemtl %s\n", material); + + // find this material in the properties list + map < string, fgMATERIAL, less > :: iterator myfind = + material_mgr.material_map.find(material); + if ( myfind == material_mgr.material_map.end() ) { + fgPrintf( FG_TERRAIN, FG_ALERT, + "Ack! unknown usemtl name = %s in %s\n", + material, path); + } else { + (fgMATERIAL *)fragment.material_ptr = &(*myfind).second; + } + } else if ( line[0] == 't' ) { // start a new triangle strip @@ -406,6 +423,9 @@ int fgObjLoad(char *path, fgTILE *tile) { // $Log$ +// Revision 1.9 1998/06/05 22:39:54 curt +// Working on sorting by, and rendering by material properties. +// // Revision 1.8 1998/06/05 18:19:18 curt // Recognize file, file.gz, and file.obj as scenery object files. // diff --git a/Scenery/tile.hxx b/Scenery/tile.hxx index b5743989a..ef3b3dcba 100644 --- a/Scenery/tile.hxx +++ b/Scenery/tile.hxx @@ -51,13 +51,15 @@ class fgFRAGMENT { public: + // positional data for this object fragment + fgCartesianPoint3d tile_center; // culling data for this object fragment (fine grain culling) fgCartesianPoint3d center; double bounding_radius; // material property pointer - int material_ptr; + void *material_ptr; // OpenGL display list for fragment data GLint display_list; @@ -99,6 +101,9 @@ public: // $Log$ +// Revision 1.3 1998/06/05 22:39:54 curt +// Working on sorting by, and rendering by material properties. +// // Revision 1.2 1998/06/03 00:47:50 curt // No .h for STL includes. // Minor view culling optimizations. diff --git a/Scenery/tilemgr.cxx b/Scenery/tilemgr.cxx index f4ad7c7b4..44cf6c834 100644 --- a/Scenery/tilemgr.cxx +++ b/Scenery/tilemgr.cxx @@ -35,10 +35,6 @@ #include -#include -#include -#include - #include #include #include @@ -47,6 +43,11 @@ #include
#include +#include "material.hxx" +#include "obj.hxx" +#include "scenery.hxx" +#include "tilecache.hxx" + #define FG_LOCAL_X_Y 81 // max(o->tile_diameter) ** 2 @@ -59,6 +60,10 @@ int tiles[FG_LOCAL_X_Y]; // Initialize the Tile Manager subsystem int fgTileMgrInit( void ) { fgPrintf( FG_TERRAIN, FG_INFO, "Initializing Tile Manager subsystem.\n"); + + // load default material library + material_mgr.load_lib(); + return 1; } @@ -295,11 +300,12 @@ void fgTileMgrRender( void ) { fgTILE *t; fgVIEW *v; struct fgBUCKET p; - fgCartesianPoint3d offset; - fgFRAGMENT fragment; + fgCartesianPoint3d offset, last_center; + fgFRAGMENT fragment, *frag_ptr; + fgMATERIAL *mtl_ptr; list < fgFRAGMENT > :: iterator current; list < fgFRAGMENT > :: iterator last; - int i; + int i, size; int index; int culled = 0; int drawn = 0; @@ -319,6 +325,10 @@ void fgTileMgrRender( void ) { FG_Longitude * RAD_TO_DEG, FG_Latitude * RAD_TO_DEG, p.lon, p.lat, p.x, p.y, fgBucketGenIndex(&p) ); + // initialize the transient per-material fragment lists + material_mgr.init_transient_material_lists(); + + // traverse the potentially viewable tile list for ( i = 0; i < (o->tile_diameter * o->tile_diameter); i++ ) { index = tiles[i]; // fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index); @@ -350,6 +360,14 @@ void fgTileMgrRender( void ) { offset.z = fragment.center.z - scenery.center.z; if ( viewable(&offset, fragment.bounding_radius * 2) ) { + // add to transient per-material property fragment list + mtl_ptr = (fgMATERIAL *)(fragment.material_ptr); + // printf(" lookup = %s\n", mtl_ptr->texture_name); + if ( mtl_ptr->list_size < FG_MAX_MATERIAL_FRAGS ) { + mtl_ptr->list[mtl_ptr->list_size] = &fragment; + (mtl_ptr->list_size)++; + } + xglCallList(fragment.display_list); drawn++; } else { @@ -374,10 +392,33 @@ void fgTileMgrRender( void ) { } // printf("drawn = %d culled = %d saved = %.2f\n", drawn, culled, // v->vfc_ratio); + + // traverse the transient per-material fragment lists and render + // out all fragments for each material property. + map < string, fgMATERIAL, less > :: iterator mapcurrent = + material_mgr.material_map.begin(); + map < string, fgMATERIAL, less > :: iterator maplast = + material_mgr.material_map.end(); + + while ( mapcurrent != maplast ) { + // (char *)key = (*mapcurrent).first; + // (fgMATERIAL)value = (*mapcurrent).second; + size = (*mapcurrent).second.list_size; + for ( i = 0; i < size; i++ ) { + // frag_ptr = &(*mapcurrent).second.list[i]; + // frag_ptr->tile_center + } + + *mapcurrent++; + } + } // $Log$ +// Revision 1.16 1998/06/05 22:39:55 curt +// Working on sorting by, and rendering by material properties. +// // Revision 1.15 1998/06/03 00:47:51 curt // No .h for STL includes. // Minor view culling optimizations.