1998-08-25 16:51:22 +00:00
|
|
|
// material.cxx -- class to handle material properties
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started May 1998.
|
|
|
|
//
|
|
|
|
// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
// (Log is kept at end of this file)
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
|
|
|
# include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <GL/glut.h>
|
|
|
|
#include <XGL/xgl.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <Debug/fg_debug.h>
|
|
|
|
#include <Include/fg_zlib.h>
|
|
|
|
#include <Main/options.hxx>
|
|
|
|
|
|
|
|
#include "material.hxx"
|
|
|
|
#include "texload.h"
|
|
|
|
|
|
|
|
// global material management class
|
|
|
|
fgMATERIAL_MGR material_mgr;
|
|
|
|
|
|
|
|
|
|
|
|
// Constructor
|
|
|
|
fgMATERIAL::fgMATERIAL ( void ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Sorting routines
|
|
|
|
void fgMATERIAL::init_sort_list( void ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fgMATERIAL::append_sort_list( fgFRAGMENT *object ) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Destructor
|
|
|
|
fgMATERIAL::~fgMATERIAL ( void ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Constructor
|
|
|
|
fgMATERIAL_MGR::fgMATERIAL_MGR ( void ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Load a library of material properties
|
|
|
|
int fgMATERIAL_MGR::load_lib ( void ) {
|
|
|
|
fgMATERIAL m;
|
|
|
|
char material_name[256];
|
|
|
|
char mpath[256], fg_mpath[256], tpath[256], fg_tpath[256];
|
|
|
|
char line[256], *line_ptr, value[256];
|
|
|
|
GLubyte *texbuf;
|
|
|
|
fgFile f;
|
|
|
|
int width, height;
|
|
|
|
int alpha;
|
|
|
|
|
|
|
|
// build the path name to the material db
|
|
|
|
current_options.get_fg_root(mpath);
|
1998-08-25 20:53:24 +00:00
|
|
|
strcat(mpath, "/");
|
|
|
|
strcat(mpath, "materials");
|
1998-08-25 16:51:22 +00:00
|
|
|
strcpy(fg_mpath, mpath);
|
|
|
|
strcat(fg_mpath, ".gz");
|
|
|
|
|
|
|
|
// first try "path.gz"
|
|
|
|
if ( (f = fgopen(fg_mpath, "rb")) == NULL ) {
|
|
|
|
// next try "path"
|
|
|
|
if ( (f = fgopen(mpath, "rb")) == NULL ) {
|
|
|
|
fgPrintf(FG_GENERAL, FG_EXIT, "Cannot open file: %s\n", mpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
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
|
|
|
|
#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 */
|
|
|
|
current_options.get_fg_root(tpath);
|
|
|
|
strcat(tpath, "/Textures/");
|
|
|
|
strcat(tpath, m.texture_name);
|
|
|
|
strcat(tpath, ".rgb");
|
|
|
|
|
|
|
|
if ( alpha == 0 ) {
|
|
|
|
// load rgb texture
|
|
|
|
|
|
|
|
// Try uncompressed
|
|
|
|
if ( (texbuf = read_rgb_texture(tpath, &width, &height))
|
|
|
|
== NULL ) {
|
|
|
|
// Try compressed
|
|
|
|
strcpy(fg_tpath, tpath);
|
|
|
|
strcat(fg_tpath, ".gz");
|
|
|
|
if ( (texbuf = read_rgb_texture(fg_tpath, &width, &height))
|
|
|
|
== NULL ) {
|
|
|
|
fgPrintf( FG_GENERAL, FG_EXIT,
|
|
|
|
"Error in loading texture %s\n", tpath );
|
|
|
|
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, &width, &height))
|
|
|
|
== NULL ) {
|
|
|
|
// Try compressed
|
|
|
|
strcpy(fg_tpath, tpath);
|
|
|
|
strcat(fg_tpath, ".gz");
|
|
|
|
if ((texbuf = read_alpha_texture(fg_tpath, &width, &height))
|
|
|
|
== NULL ) {
|
|
|
|
fgPrintf( FG_GENERAL, FG_EXIT,
|
|
|
|
"Error in loading texture %s\n", tpath );
|
|
|
|
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
|
|
|
|
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<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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Destructor
|
|
|
|
fgMATERIAL_MGR::~fgMATERIAL_MGR ( void ) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// $Log$
|
1998-08-25 20:53:24 +00:00
|
|
|
// Revision 1.2 1998/08/25 20:53:33 curt
|
|
|
|
// Shuffled $FG_ROOT file layout.
|
|
|
|
//
|
1998-08-25 16:51:22 +00:00
|
|
|
// Revision 1.1 1998/08/25 16:51:24 curt
|
|
|
|
// Moved from ../Scenery
|
|
|
|
//
|
|
|
|
// Revision 1.13 1998/08/24 20:11:39 curt
|
|
|
|
// Tweaks ...
|
|
|
|
//
|
|
|
|
// Revision 1.12 1998/08/12 21:41:27 curt
|
|
|
|
// Need to negate the test for textures so that textures aren't loaded when
|
|
|
|
// they are disabled rather than visa versa ... :-)
|
|
|
|
//
|
|
|
|
// Revision 1.11 1998/08/12 21:13:03 curt
|
|
|
|
// material.cxx: don't load textures if they are disabled
|
|
|
|
// obj.cxx: optimizations from Norman Vine
|
|
|
|
// tile.cxx: minor tweaks
|
|
|
|
// tile.hxx: addition of num_faces
|
|
|
|
// tilemgr.cxx: minor tweaks
|
|
|
|
//
|
|
|
|
// Revision 1.10 1998/07/24 21:42:06 curt
|
|
|
|
// material.cxx: whups, double method declaration with no definition.
|
|
|
|
// obj.cxx: tweaks to avoid errors in SGI's CC.
|
|
|
|
// tile.cxx: optimizations by Norman Vine.
|
|
|
|
// tilemgr.cxx: optimizations by Norman Vine.
|
|
|
|
//
|
|
|
|
// Revision 1.9 1998/07/13 21:01:57 curt
|
|
|
|
// Wrote access functions for current fgOPTIONS.
|
|
|
|
//
|
|
|
|
// Revision 1.8 1998/07/08 14:47:20 curt
|
|
|
|
// Fix GL_MODULATE vs. GL_DECAL problem introduced by splash screen.
|
|
|
|
// polare3d.h renamed to polar3d.hxx
|
|
|
|
// fg{Cartesian,Polar}Point3d consolodated.
|
|
|
|
// Added some initial support for calculating local current ground elevation.
|
|
|
|
//
|
|
|
|
// Revision 1.7 1998/07/04 00:54:28 curt
|
|
|
|
// Added automatic mipmap generation.
|
|
|
|
//
|
|
|
|
// When rendering fragments, use saved model view matrix from associated tile
|
|
|
|
// rather than recalculating it with push() translate() pop().
|
|
|
|
//
|
|
|
|
// Revision 1.6 1998/06/27 16:54:59 curt
|
|
|
|
// Check for GL_VERSION_1_1 or GL_EXT_texture_object to decide whether to use
|
|
|
|
// "EXT" versions of texture management routines.
|
|
|
|
//
|
|
|
|
// Revision 1.5 1998/06/17 21:36:39 curt
|
|
|
|
// Load and manage multiple textures defined in the Materials library.
|
|
|
|
// Boost max material fagments for each material property to 800.
|
|
|
|
// Multiple texture support when rendering.
|
|
|
|
//
|
|
|
|
// Revision 1.4 1998/06/12 00:58:04 curt
|
|
|
|
// Build only static libraries.
|
|
|
|
// Declare memmove/memset for Sloaris.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// Revision 1.1 1998/05/30 01:56:45 curt
|
|
|
|
// Added material.cxx material.hxx
|
|
|
|
//
|