]> git.mxchange.org Git - flightgear.git/commitdiff
Substantial rewrite of FGNewMat, the material class. Most of the
authordavid <david>
Fri, 28 Dec 2001 23:33:32 +0000 (23:33 +0000)
committerdavid <david>
Fri, 28 Dec 2001 23:33:32 +0000 (23:33 +0000)
material-specific logic is now removed from the material library and
encapsulated in the material class itself, and materials are loaded
from $FG_ROOT/materials.xml rather than $FG_ROOT/materials.  This also
removes a nasty bug in the old material-loading code that caused a
floating-point exception.

src/Main/fg_init.cxx
src/Objects/matlib.cxx
src/Objects/matlib.hxx
src/Objects/newmat.cxx
src/Objects/newmat.hxx

index 15c406282ca047295811be64ff1a2a6d39f87596..ec6039b60c138f5ac66a9391a186744215e5d224 100644 (file)
@@ -529,7 +529,7 @@ bool fgInitSubsystems( void ) {
     ////////////////////////////////////////////////////////////////////
 
     SGPath mpath( globals->get_fg_root() );
-    mpath.append( "materials" );
+    mpath.append( "materials.xml" );
     if ( material_lib.load( mpath.str() ) ) {
     } else {
        SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" );
index 9d110bd692d762b0fc86cfec8882faba095b882d..9c0ec1e593eca1209451a23c3eede2de1eb8675d 100644 (file)
@@ -37,6 +37,7 @@
 #include <GL/gl.h>
 
 #include <simgear/compiler.h>
+#include <simgear/misc/exception.hxx>
 
 #include <string.h>
 #include STL_STRING
@@ -65,105 +66,37 @@ FGMaterialLib::FGMaterialLib ( void ) {
 }
 
 
-static bool local_file_exists( const string& path ) {
-    sg_gzifstream in( path );
-    if ( ! in.is_open() ) {
-       return false;
-    } else {
-       return true;
-    }
-}
-
-
 // Load a library of material properties
 bool FGMaterialLib::load( const string& mpath ) {
-    string material_name;
 
-    sg_gzifstream in( mpath );
-    if ( ! in.is_open() ) {
-       SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << mpath );
-       exit(-1);
-    }
-
-#ifndef __MWERKS__
-    while ( ! in.eof() ) {
-#else
-    char c = '\0';
-    while ( in.get(c) && c != '\0' ) {
-       in.putback(c);
-#endif
-        // 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;
-
-       if ( material_name == "alias" ) {
-           string src_mat, dst_mat;
-           in >> dst_mat >> src_mat;
-           SG_LOG( SG_GENERAL, SG_INFO, "  Material alias: " << dst_mat <<
-                   " mapped to " << src_mat );
-           FGNewMat *m = matlib[src_mat];
-            if ( m != NULL ) {
-                matlib[dst_mat] = m;
-               m->ref();
-            } else {
-                SG_LOG( SG_GENERAL, SG_ALERT,
-                        "Bad material alias pointing to nonexistant material" );
-            }
-       } else {
-           in >> token;
-
-           if ( token == '{' ) {
-                // Read the data into a temporary but stack allocated
-                // copy of the structure
-                FGNewMat tmp;
-               in >> tmp;
-
-                // create a pointer to a heap allocated copy of the structure
-               FGNewMat *m = new FGNewMat;
-                *m = tmp;
-               m->ref();
-
-               // build the ssgSimpleState
-               SGPath tex_path( globals->get_fg_root() );
-               tex_path.append( "Textures.high" );
-               tex_path.append( m->get_texture_name() );
-               if ( ! local_file_exists(tex_path.str())
-                    || general.get_glMaxTexSize() < 512 ) {
-                   tex_path = SGPath( globals->get_fg_root() );
-                   tex_path.append( "Textures" );
-                   tex_path.append( m->get_texture_name() );
-               }
-           
-               SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
-                       << material_name << " (" << tex_path.c_str() << ")");
-
-               GLenum shade_model = GL_SMOOTH;
-               if ( fgGetBool("/sim/rendering/shading") ) {
-                   shade_model = GL_SMOOTH;
-               } else {
-                   shade_model = GL_FLAT;
-               }
-
-               m->set_texture_name( tex_path.str() );
-               m->build_ssg_state( shade_model,
-                                    fgGetBool("/sim/rendering/textures"),
-                                    false );
-
-#if EXTRA_DEBUG
-               m->dump_info();
-#endif
-           
-               matlib[material_name] = m;
-           }
-       }
+  SGPropertyNode materials;
+
+  cout << "Reading materials from " << mpath << endl;
+  try {
+    readProperties(mpath, &materials);
+  } catch (const sg_exception &ex) {
+    SG_LOG(SG_INPUT, SG_ALERT, "Error reading materials: " << ex.getMessage());
+    throw ex;
+  }
+
+  int nMaterials = materials.nChildren();
+  for (int i = 0; i < nMaterials; i++) {
+    const SGPropertyNode * node = materials.getChild(i);
+    if (node->getName() == "material") {
+      FGNewMat * m = new FGNewMat(node);
+
+      vector<const SGPropertyNode *>names = node->getChildren("name");
+      for (int j = 0; j < names.size(); j++) {
+       m->ref();
+       matlib[names[j]->getStringValue()] = m;
+       SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material "
+               << names[j]->getStringValue());
+      }
+    } else {
+      SG_LOG(SG_INPUT, SG_ALERT,
+            "Skipping bad material entry " << node->getName());
     }
+  }
 
     // hard coded light state
     ssgSimpleState *lights = new ssgSimpleState;
@@ -178,9 +111,7 @@ bool FGMaterialLib::load( const string& mpath ) {
     lights->disable( GL_ALPHA_TEST );
     lights->disable( GL_LIGHTING );
 
-    FGNewMat *m = new FGNewMat;
-    m->set_ssg_state( lights );
-    matlib["LIGHTS"] = m;
+    matlib["LIGHTS"] = new FGNewMat(lights);
 
     return true;
 }
@@ -204,27 +135,10 @@ bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
     string tex_name = full_path.substr( pos + 1 );
     string tex_path = full_path.substr( 0, pos );
 
-    FGNewMat *m = new FGNewMat( mat_name, full_path );
-
     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material " 
            << mat_name << " (" << full_path << ")");
 
-#if EXTRA_DEBUG
-    m->dump_info();
-#endif
-
-    GLenum shade_model = GL_SMOOTH;
-    if ( fgGetBool("/sim/rendering/shading") ) {
-       shade_model = GL_SMOOTH;
-    } else {
-       shade_model = GL_FLAT;
-    }
-
-    m->build_ssg_state( shade_model,
-                        fgGetBool("/sim/rendering/textures"),
-                        true );
-
-    material_lib.matlib[mat_name] = m;
+    material_lib.matlib[mat_name] = new FGNewMat(full_path);
 
     return true;
 }
@@ -233,16 +147,11 @@ bool FGMaterialLib::add_item ( const string &mat_name, const string &full_path )
 // Load a library of material properties
 bool FGMaterialLib::add_item ( const string &mat_name, ssgSimpleState *state )
 {
-    FGNewMat *m = new FGNewMat( mat_name );
-    m->set_ssg_state( state );
+    FGNewMat *m = new FGNewMat(state);
 
     SG_LOG( SG_TERRAIN, SG_INFO, "  Loading material given a premade "
            << "ssgSimpleState = " << mat_name );
 
-#if EXTRA_DEBUG
-    m->dump_info();
-#endif
-
     material_lib.matlib[mat_name] = m;
 
     return true;
@@ -304,18 +213,7 @@ void FGMaterialLib::load_next_deferred() {
     for ( material_map_iterator it = begin(); it != end(); it++ ) {
        const string &key = it->first;
        FGNewMat *slot = it->second;
-        // SG_LOG( SG_GENERAL, SG_INFO, "slot = " << slot );
-       if ( ! slot->get_texture_loaded() ) {
-            SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture for "
-                    << key );
-#ifdef PLIB_1_2_X
-            slot->get_textured()->
-                setTexture( (char *)slot->get_texture_name_c_str(), 0, 0 );
-#else
-            slot->get_textured()->
-                setTexture( (char *)slot->get_texture_name_c_str(), 0, 0, 1 );
-#endif
-            slot->set_texture_loaded( true );
-        }
+       if (slot->load_texture())
+         return;
     }
 }
index cfdca473c173a20daa66a626b17c682067d07bf6..ee1f65017cda6e46921d5506e1560f48f8142c60 100644 (file)
@@ -88,8 +88,9 @@ public:
     void set_step (int step);
     int get_step ();
 
-    // Load one pending "deferred" texture.  Return true if a texture
-    // loaded successfully, false if no pending, or error.
+    /**
+     * Load the next deferred texture, if there is any.
+     */
     void load_next_deferred();
 
     material_map_iterator begin() { return matlib.begin(); }
index 451b344ef59bf37c024834ac175afe283745b556..39da01c3964692fc079ced059fb41edec8c491cf 100644 (file)
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sgstream.hxx>
 
+#include <Main/globals.hxx>
+#include <Main/fg_props.hxx>
+
 #include "newmat.hxx"
 
 
-// Constructor
-FGNewMat::FGNewMat ( void ) {
-    wrapu = wrapv = 1;
-    mipmap = 1;
-    light_coverage = -1.0;
-    refcount = 0;
+static bool
+local_file_exists( const string& path ) {
+    sg_gzifstream in( path );
+    if ( ! in.is_open() ) {
+       return false;
+    } else {
+       return true;
+    }
 }
 
 
 // Constructor
-FGNewMat::FGNewMat ( const string &name )
+
+FGNewMat::FGNewMat ()
+  : texture_path(""),
+    state(0),
+    textured(0),
+    nontextured(0),
+    alpha(false),
+    xsize(0),
+    ysize(0),
+    wrapu(true),
+    wrapv(true),
+    mipmap(true),
+    texture_loaded(false),
+    refcount(0)
+{
+    for (int i = 0; i < 4; i++)
+      ambient[i] = diffuse[i] = specular[i] = emission[i] = 0.0;
+}
+
+FGNewMat::FGNewMat (const SGPropertyNode * props)
 {
-    FGNewMat( name, name );
+    FGNewMat();
+    read_properties(props);
+    build_ssg_state(false);
 }
 
+FGNewMat::FGNewMat (const string &texture_path)
+{
+    FGNewMat();
+    build_ssg_state(true);
+}
 
-// Constructor
-FGNewMat::FGNewMat ( const string &mat_name, const string &tex_name )
+FGNewMat::FGNewMat (ssgSimpleState * s)
+{
+    FGNewMat();
+    set_ssg_state(s);
+}
+
+
+bool
+FGNewMat::load_texture ()
 {
-    material_name = mat_name;
-    texture_name = tex_name;
-    xsize = ysize = 0;
-    wrapu = wrapv = 1;
-    mipmap = 1;
-    alpha = 0; 
-    ambient[0]  = ambient[1]  = ambient[2]  = ambient[3]  = 1.0;
-    diffuse[0]  = diffuse[1]  = diffuse[2]  = diffuse[3]  = 1.0;
-    specular[0] = specular[1] = specular[2] = specular[3] = 1.0;
-    emission[0] = emission[1] = emission[2] = emission[3] = 1.0;
-    light_coverage = -1.0;
-    refcount = 0;
+  if (texture_loaded) {
+    return false;
+  } else {
+    SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture " << texture_path );
+#ifdef PLIB_1_2_X
+    textured->setTexture((char *)texture_path.c_str(), wrapu, wrapv );
+#else
+    textured->setTexture((char *)texture_path.c_str(), wrapu, wrapv, mipmap );
+#endif
+    texture_loaded = true;
+    return true;
+  }
 }
 
 
-void FGNewMat::build_ssg_state( GLenum shade_model, bool texture_default,
-                               bool defer_tex_load )
+void FGNewMat::build_ssg_state( bool defer_tex_load )
 {
+    GLenum shade_model =
+      (fgGetBool("/sim/rendering/shading") ? GL_SMOOTH : GL_FLAT);
+    bool texture_default = fgGetBool("/sim/rendering/textures");
+
     state = new ssgStateSelector(2);
     state->ref();
 
@@ -92,12 +133,11 @@ void FGNewMat::build_ssg_state( GLenum shade_model, bool texture_default,
     textured->disable( GL_BLEND );
     textured->disable( GL_ALPHA_TEST );
     if ( !defer_tex_load ) {
-       textured->setTexture( (char *)texture_name.c_str(), wrapu, wrapv );
+       textured->setTexture( (char *)texture_path.c_str(), wrapu, wrapv );
        texture_loaded = true;
     } else {
        texture_loaded = false;
     }
-    // cout << "wrap u = " << wrapu << " wrapv = " << wrapv << endl;
     textured->enable( GL_COLOR_MATERIAL );
     textured->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
     textured->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
@@ -112,8 +152,6 @@ void FGNewMat::build_ssg_state( GLenum shade_model, bool texture_default,
     nontextured->disable( GL_ALPHA_TEST );
     nontextured->disable( GL_COLOR_MATERIAL );
 
-    /* cout << "ambient = " << ambient[0] << "," << ambient[1] 
-       << "," << ambient[2] << endl; */
     nontextured->setMaterial ( GL_AMBIENT, 
                               ambient[0], ambient[1], 
                               ambient[2], ambient[3] ) ;
@@ -180,75 +218,50 @@ void FGNewMat::set_ssg_state( ssgSimpleState *s ) {
 }
 
 
-void FGNewMat::dump_info () {
-    SG_LOG( SG_TERRAIN, SG_INFO, "{" << endl << "  texture = " 
-           << texture_name );
-    SG_LOG( SG_TERRAIN, SG_INFO, "  xsize = " << xsize );
-    SG_LOG( SG_TERRAIN, SG_INFO, "  ysize = " << ysize );
-    SG_LOG( SG_TERRAIN, SG_INFO, "  ambient = " << ambient[0] << " "
-           << ambient[1] <<" "<< ambient[2] <<" "<< ambient[3] );
-    SG_LOG( SG_TERRAIN, SG_INFO, "  diffuse = " << diffuse[0] << " " 
-           << diffuse[1] << " " << diffuse[2] << " " << diffuse[3] );
-    SG_LOG( SG_TERRAIN, SG_INFO, "  specular = " << specular[0] << " " 
-           << specular[1] << " " << specular[2] << " " << specular[3]);
-    SG_LOG( SG_TERRAIN, SG_INFO, "  emission = " << emission[0] << " " 
-           << emission[1] << " " << emission[2] << " " << emission[3]);
-    SG_LOG( SG_TERRAIN, SG_INFO, "  alpha = " << alpha << endl <<"}" );
-           
-}
-
-
 // Destructor
 FGNewMat::~FGNewMat ( void ) {
 }
 
 
-istream&
-operator >> ( istream& in, FGNewMat& m )
+void
+FGNewMat::read_properties (const SGPropertyNode * props)
 {
-    string token;
-
-    for (;;) {
-       in >> token;
-       if ( token == "texture" ) {
-           in >> token >> m.texture_name;
-       } else if ( token == "xsize" ) {
-           in >> token >> m.xsize;
-       } else if ( token == "ysize" ) {
-           in >> token >> m.ysize;
-       } else if ( token == "wrapu" ) {
-           in >> token >> m.wrapu;
-       } else if ( token == "wrapv" ) {
-           in >> token >> m.wrapv;
-       } else if ( token == "mipmap" ) {
-           in >> token >> m.mipmap;
-       } 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 == "emission" ) {
-           in >> token >> m.emission[0] >> m.emission[1]
-              >> m.emission[2] >> m.emission[3];
-       } else if ( token == "alpha" ) {
-           in >> token >> token;
-           if ( token == "yes" ) {
-               m.alpha = 1;
-           } else if ( token == "no" ) {
-               m.alpha = 0;
-           } else {
-               SG_LOG( SG_TERRAIN, SG_INFO, "Bad alpha value " << token );
-           }
-       } else if ( token == "light-coverage" ) {
-           in >> token >> m.light_coverage;
-       } else if ( token[0] == '}' ) {
-           break;
-       }
-    }
-
-    return in;
+                               // Get the path to the texture
+  string tname = props->getStringValue("texture", "unknown.rgb");
+  SGPath tpath(globals->get_fg_root());
+  tpath.append("Textures.high");
+  tpath.append(tname);
+  if (!local_file_exists(tpath.str())) {
+    tpath = SGPath(globals->get_fg_root());
+    tpath.append("Textures");
+    tpath.append(tname);
+  }
+  texture_path = tpath.str();
+
+  xsize = props->getDoubleValue("xsize", 0.0);
+  ysize = props->getDoubleValue("ysize", 0.0);
+  wrapu = props->getBoolValue("wrapu", true);
+  wrapv = props->getBoolValue("wrapv", true);
+  mipmap = props->getBoolValue("mipmap", true);
+  light_coverage = props->getDoubleValue("light-coverage");
+
+  ambient[0] = props->getDoubleValue("ambient/r", 0.0);
+  ambient[1] = props->getDoubleValue("ambient/g", 0.0);
+  ambient[2] = props->getDoubleValue("ambient/b", 0.0);
+  ambient[3] = props->getDoubleValue("ambient/a", 0.0);
+
+  diffuse[0] = props->getDoubleValue("diffuse/r", 0.0);
+  diffuse[1] = props->getDoubleValue("diffuse/g", 0.0);
+  diffuse[2] = props->getDoubleValue("diffuse/b", 0.0);
+  diffuse[3] = props->getDoubleValue("diffuse/a", 0.0);
+
+  specular[0] = props->getDoubleValue("specular/r", 0.0);
+  specular[1] = props->getDoubleValue("specular/g", 0.0);
+  specular[2] = props->getDoubleValue("specular/b", 0.0);
+  specular[3] = props->getDoubleValue("specular/a", 0.0);
+
+  emission[0] = props->getDoubleValue("emissive/r", 0.0);
+  emission[1] = props->getDoubleValue("emissive/g", 0.0);
+  emission[2] = props->getDoubleValue("emissive/b", 0.0);
+  emission[3] = props->getDoubleValue("emissive/a", 0.0);
 }
index 72a92ecc3232815d5cbfb9cdf3406e91cfa80749..28199619e07d73661def82eba81bf5cafd552b8f 100644 (file)
@@ -1,6 +1,8 @@
-// newmat.hxx -- class to handle material properties
+// newmat.hxx -- a material in the scene graph.
+// TODO: this class needs to be renamed.
 //
 // Written by Curtis Olson, started May 1998.
+// Overhauled by David Megginson, December 2001
 //
 // Copyright (C) 1998 - 2000  Curtis L. Olson  - curt@flightgear.org
 //
@@ -24,7 +26,6 @@
 #ifndef _NEWMAT_HXX
 #define _NEWMAT_HXX
 
-
 #ifndef __cplusplus                                                          
 # error This library requires C++
 #endif                                   
@@ -41,6 +42,7 @@
 #include <plib/ssg.h>
 
 #include <simgear/compiler.h>
+#include <simgear/misc/props.hxx>
 
 #include <GL/glut.h>
 
 SG_USING_STD(string);
 
 
-// MSVC++ 6.0 kuldge - Need forward declaration of friends.
-class FGNewMat;
-istream& operator >> ( istream& in, FGNewMat& m );
-
-// Material property class
+/**
+ * A material in the scene graph.
+ *
+ * A material represents information about a single surface type
+ * in the 3D scene graph, including texture, colour, lighting,
+ * tiling, and so on; most of the materials in FlightGear are
+ * defined in the $FG_ROOT/materials.xml file, and can be changed
+ * at runtime.
+ */
 class FGNewMat {
 
-private:
+public:
 
-    // names
-    string material_name;
-    string texture_name;
+\f
+  ////////////////////////////////////////////////////////////////////
+  // Public Constructors.
+  ////////////////////////////////////////////////////////////////////
 
-    // pointers to ssg states
-    ssgStateSelector *state;
-    ssgSimpleState *textured;
-    ssgSimpleState *nontextured;
+  /**
+   * Construct a material from a set of properties.
+   *
+   * @param props A property node containing subnodes with the
+   * state information for the material.  This node is usually
+   * loaded from the $FG_ROOT/materials.xml file.
+   */
+  FGNewMat (const SGPropertyNode * props);
 
-    // alpha texture?
-    int alpha;
 
-    // texture size
-    double xsize, ysize;
+  /**
+   * Construct a material from an absolute texture path.
+   *
+   * @param texture_path A string containing an absolute path
+   * to a texture file (usually RGB).
+   */
+  FGNewMat (const string &texture_path);
 
-    // wrap texture?
-    int wrapu, wrapv;
 
-    // use mipmapping?
-    int mipmap;
+  /**
+   * Construct a material around an existing SSG state.
+   *
+   * This constructor allows the application to create a custom,
+   * low-level state for the scene graph and wrap a material around
+   * it.  Note: the pointer ownership is transferred to the material.
+   *
+   * @param s The SSG state for this material.
+   */
+  FGNewMat (ssgSimpleState * s);
 
-    // coverage of night lighting.  This number is specifically the
-    // amount of area coverage we give a single light.  The size of a
-    // triangle is divided by this number and that is the number of
-    // lights assigned to that triangle.  Lower numbers mean more
-    // dense light ocverage.
-    double light_coverage;
+  /**
+   * Destructor.
+   */
+  virtual ~FGNewMat ( void );
 
-    // material properties
-    sgVec4 ambient, diffuse, specular, emission;
 
-    // true if texture loading deferred, and not yet loaded
-    bool texture_loaded;
+\f
+  ////////////////////////////////////////////////////////////////////
+  // Public methods.
+  ////////////////////////////////////////////////////////////////////
 
-    // ref count so we can properly delete if we have multiple
-    // pointers to this record
-    int refcount;
+  /**
+   * Force the texture to load if it hasn't already.
+   *
+   * @return true if the texture loaded, false if it was loaded
+   * already.
+   */
+  virtual bool load_texture ();
 
-public:
 
-    // Constructor
-    FGNewMat ( void );
-    FGNewMat ( const string& name );
-    FGNewMat ( const string &mat_name, const string &tex_name );
+  /**
+   * Get the textured state.
+   */
+  virtual inline ssgSimpleState *get_textured () { return textured; }
 
-    // Destructor
-    ~FGNewMat ( void );
 
-    friend istream& operator >> ( istream& in, FGNewMat& m );
+  /**
+   * Get the xsize of the texture, in meters.
+   */
+  virtual inline double get_xsize() const { return xsize; }
 
-    // void load_texture( const string& root );
-    void build_ssg_state( GLenum shade_model, bool texture_default,
-                         bool defer_tex_load = false );
-    void set_ssg_state( ssgSimpleState *s );
 
-    inline string get_material_name() const { return material_name; }
-    inline void set_material_name( const string& n ) { material_name = n; }
+  /**
+   * Get the ysize of the texture, in meters.
+   */
+  virtual inline double get_ysize() const { return ysize; }
 
-    inline string get_texture_name() const { return texture_name; }
-    inline const char *get_texture_name_c_str() const {
-        return texture_name.c_str();
-    }
-    inline void set_texture_name( const string& n ) { texture_name = n; }
 
-    inline ssgSimpleState *get_textured() { return textured; }
+  /**
+   * Get the light coverage.
+   *
+   * A smaller number means more generated night lighting.
+   *
+   * @return The area (m^2?) covered by each light.
+   */
+  virtual inline double get_light_coverage () const { return light_coverage; }
 
-    inline double get_xsize() const { return xsize; }
-    inline double get_ysize() const { return ysize; }
-    inline void set_xsize( double x ) { xsize = x; }
-    inline void set_ysize( double y ) { ysize = y; }
 
-    inline float *get_ambient() { return ambient; }
-    inline float *get_diffuse() { return diffuse; }
-    inline float *get_specular() { return specular; }
-    inline float *get_emission() { return emission; }
-    inline void set_ambient( sgVec4 a ) { sgCopyVec4( ambient, a ); }
-    inline void set_diffuse( sgVec4 d ) { sgCopyVec4( diffuse, d ); }
-    inline void set_specular( sgVec4 s ) { sgCopyVec4( specular, s ); }
-    inline void set_emission( sgVec4 e ) { sgCopyVec4( emission, e ); }
+  /**
+   * Get the current state.
+   */
+  virtual inline ssgStateSelector *get_state() const { return state; }
 
-    inline bool get_texture_loaded() const { return texture_loaded; }
-    inline void set_texture_loaded( bool val ) { texture_loaded = val; }
 
-    inline double get_light_coverage () const { return light_coverage; }
-    inline void set_light_coverage (double coverage) {
-       light_coverage = coverage;
-    }
+  /**
+   * Add a reference to the texture.
+   */
+  virtual inline void ref() { refcount++; }
 
-    inline ssgStateSelector *get_state() const { return state; }
 
-    inline void ref() { refcount++; }
-    inline void deRef() { refcount--; }
-    inline int getRef() const { return refcount; }
+  /**
+   * Remove a reference from the texture.
+   */
+  virtual inline void deRef() { refcount--; }
 
-    void dump_info();
-};
 
+  /**
+   * Get the number of references to the texture.
+   */
+  virtual inline int getRef() const { return refcount; }
 
-#endif // _NEWMAT_HXX 
 
+private:
+
+\f
+  ////////////////////////////////////////////////////////////////////
+  // Internal state.
+  ////////////////////////////////////////////////////////////////////
+
+  // names
+  string texture_path;
+
+  // pointers to ssg states
+  ssgStateSelector *state;
+  ssgSimpleState *textured;
+  ssgSimpleState *nontextured;
+
+  // alpha texture?
+  bool alpha;
+  
+  // texture size
+  double xsize, ysize;
+
+  // wrap texture?
+  bool wrapu, wrapv;
 
+  // use mipmapping?
+  int mipmap;
+
+  // coverage of night lighting.
+  double light_coverage;
+
+  // material properties
+  sgVec4 ambient, diffuse, specular, emission;
+
+  // true if texture loading deferred, and not yet loaded
+  bool texture_loaded;
+
+  // ref count so we can properly delete if we have multiple
+  // pointers to this record
+  int refcount;
+
+
+\f
+  ////////////////////////////////////////////////////////////////////
+  // Internal constructors and methods.
+  ////////////////////////////////////////////////////////////////////
+
+  FGNewMat ();
+  FGNewMat (const FGNewMat &mat); // unimplemented
+
+  void read_properties (const SGPropertyNode * props);
+  void build_ssg_state(bool defer_tex_load = false);
+  void set_ssg_state( ssgSimpleState *s );
+
+};
+
+#endif // _NEWMAT_HXX