Substantial rewrite of FGNewMat, the material class. Most of the
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.
This commit is contained in:
parent
1fa4c88d0e
commit
d4aea05246
5 changed files with 301 additions and 321 deletions
|
@ -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!" );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -35,46 +35,87 @@
|
|||
#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)
|
||||
{
|
||||
FGNewMat( name, name );
|
||||
for (int i = 0; i < 4; i++)
|
||||
ambient[i] = diffuse[i] = specular[i] = emission[i] = 0.0;
|
||||
}
|
||||
|
||||
FGNewMat::FGNewMat (const SGPropertyNode * props)
|
||||
{
|
||||
FGNewMat();
|
||||
read_properties(props);
|
||||
build_ssg_state(false);
|
||||
}
|
||||
|
||||
FGNewMat::FGNewMat (const string &texture_path)
|
||||
{
|
||||
FGNewMat();
|
||||
build_ssg_state(true);
|
||||
}
|
||||
|
||||
FGNewMat::FGNewMat (ssgSimpleState * s)
|
||||
{
|
||||
FGNewMat();
|
||||
set_ssg_state(s);
|
||||
}
|
||||
|
||||
|
||||
// Constructor
|
||||
FGNewMat::FGNewMat ( const string &mat_name, const string &tex_name )
|
||||
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;
|
||||
// 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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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");
|
||||
|
||||
return in;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -49,113 +51,179 @@
|
|||
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:
|
||||
|
||||
// names
|
||||
string material_name;
|
||||
string texture_name;
|
||||
|
||||
// pointers to ssg states
|
||||
ssgStateSelector *state;
|
||||
ssgSimpleState *textured;
|
||||
ssgSimpleState *nontextured;
|
||||
|
||||
// alpha texture?
|
||||
int alpha;
|
||||
|
||||
// texture size
|
||||
double xsize, ysize;
|
||||
|
||||
// wrap texture?
|
||||
int wrapu, wrapv;
|
||||
|
||||
// use mipmapping?
|
||||
int mipmap;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
FGNewMat ( void );
|
||||
FGNewMat ( const string& name );
|
||||
FGNewMat ( const string &mat_name, const string &tex_name );
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Public Constructors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Destructor
|
||||
~FGNewMat ( void );
|
||||
/**
|
||||
* 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);
|
||||
|
||||
friend istream& operator >> ( istream& in, FGNewMat& m );
|
||||
|
||||
// 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 );
|
||||
/**
|
||||
* 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);
|
||||
|
||||
inline string get_material_name() const { return material_name; }
|
||||
inline void set_material_name( const string& n ) { material_name = n; }
|
||||
|
||||
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; }
|
||||
/**
|
||||
* 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);
|
||||
|
||||
inline ssgSimpleState *get_textured() { return textured; }
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~FGNewMat ( void );
|
||||
|
||||
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 ); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Public methods.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool get_texture_loaded() const { return texture_loaded; }
|
||||
inline void set_texture_loaded( bool val ) { texture_loaded = val; }
|
||||
/**
|
||||
* 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 ();
|
||||
|
||||
inline double get_light_coverage () const { return light_coverage; }
|
||||
inline void set_light_coverage (double coverage) {
|
||||
light_coverage = coverage;
|
||||
}
|
||||
|
||||
inline ssgStateSelector *get_state() const { return state; }
|
||||
/**
|
||||
* Get the textured state.
|
||||
*/
|
||||
virtual inline ssgSimpleState *get_textured () { return textured; }
|
||||
|
||||
inline void ref() { refcount++; }
|
||||
inline void deRef() { refcount--; }
|
||||
inline int getRef() const { return refcount; }
|
||||
|
||||
void dump_info();
|
||||
/**
|
||||
* Get the xsize of the texture, in meters.
|
||||
*/
|
||||
virtual inline double get_xsize() const { return xsize; }
|
||||
|
||||
|
||||
/**
|
||||
* Get the ysize of the texture, in meters.
|
||||
*/
|
||||
virtual inline double get_ysize() const { return ysize; }
|
||||
|
||||
|
||||
/**
|
||||
* 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; }
|
||||
|
||||
|
||||
/**
|
||||
* Get the current state.
|
||||
*/
|
||||
virtual inline ssgStateSelector *get_state() const { return state; }
|
||||
|
||||
|
||||
/**
|
||||
* Add a reference to the texture.
|
||||
*/
|
||||
virtual inline void ref() { refcount++; }
|
||||
|
||||
|
||||
/**
|
||||
* Remove a reference from the texture.
|
||||
*/
|
||||
virtual inline void deRef() { refcount--; }
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of references to the texture.
|
||||
*/
|
||||
virtual inline int getRef() const { return refcount; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue