Make it possible to define multiple texture for a material (multiple <texture> entries in the materials.xml file). The code can return a random texture, or a pre defined texture upon request (default is random)

This commit is contained in:
ehofman
2004-03-02 10:51:13 +00:00
parent 79d72b6292
commit 5f21c75e02
2 changed files with 111 additions and 82 deletions

View File

@@ -30,41 +30,18 @@
#include <map>
SG_USING_STD(map);
#include <simgear/compiler.h>
#include <plib/ul.h>
#ifdef SG_MATH_EXCEPTION_CLASH
# include <math.h>
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sgstream.hxx>
#include "mat.hxx"
////////////////////////////////////////////////////////////////////////
// Local static functions.
////////////////////////////////////////////////////////////////////////
/**
* Internal method to test whether a file exists.
*
* TODO: this should be moved to a SimGear library of local file
* functions.
*/
static inline bool
local_file_exists( const string& path ) {
sg_gzifstream in( path );
if ( ! in.is_open() ) {
return false;
} else {
return true;
}
}
////////////////////////////////////////////////////////////////////////
// Constructors and destructor.
@@ -81,7 +58,10 @@ SGMaterial::SGMaterial( const string &fg_root, const SGPropertyNode *props )
SGMaterial::SGMaterial( const string &texpath )
{
init();
texture_path = texpath;
_internal_state st = { NULL, texpath, false };
_status.push_back( st );
build_ssg_state( true );
}
@@ -108,17 +88,34 @@ SGMaterial::~SGMaterial (void)
void
SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props )
{
// Get the path to the texture
string tname = props->getStringValue("texture", "unknown.rgb");
SGPath tpath( fg_root );
tpath.append("Textures.high");
tpath.append(tname);
if (!local_file_exists(tpath.str())) {
tpath = SGPath( fg_root );
// Gather the path(s) to the texture(s)
vector<SGPropertyNode_ptr> textures = props->getChildren("texture");
for (int i = 0; i < textures.size(); i++)
{
string tname = textures[i]->getStringValue();
if (tname == "")
tname = "unknown.rgb";
SGPath tpath( fg_root );
tpath.append("Textures.high");
tpath.append(tname);
if (!ulFileExists(tpath.c_str())) {
tpath = SGPath( fg_root );
tpath.append("Textures");
tpath.append(tname);
}
_internal_state st = { NULL, tpath.str(), false };
_status.push_back( st );
}
if (textures.size() == 0) {
string tname = "unknown.rgb";
SGPath tpath( fg_root );
tpath.append("Textures");
tpath.append(tname);
_internal_state st = { NULL, tpath.str(), true };
_status.push_back( st );
}
texture_path = tpath.str();
xsize = props->getDoubleValue("xsize", 0.0);
ysize = props->getDoubleValue("ysize", 0.0);
@@ -165,15 +162,13 @@ SGMaterial::read_properties( const string &fg_root, const SGPropertyNode * props
void
SGMaterial::init ()
{
texture_path = "";
state = NULL;
_status.clear();
xsize = 0;
ysize = 0;
wrapu = true;
wrapv = true;
mipmap = true;
light_coverage = 0.0;
texture_loaded = false;
refcount = 0;
shininess = 1.0;
for (int i = 0; i < 4; i++) {
@@ -185,17 +180,35 @@ SGMaterial::init ()
}
bool
SGMaterial::load_texture ()
SGMaterial::load_texture ( int n )
{
if ( texture_loaded ) {
return false;
} else {
SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture "
<< texture_path );
state->setTexture( (char *)texture_path.c_str(), wrapu, wrapv, mipmap );
texture_loaded = true;
return true;
int i = (n >= 0) ? n : 0 ;
int end = (n >= 0) ? n+1 : _status.size();
for (; i < end; i++)
{
if ( !_status[i].texture_loaded ) {
SG_LOG( SG_GENERAL, SG_INFO, "Loading deferred texture "
<< _status[i].texture_path );
_status[i].state->setTexture(
(char *)_status[i].texture_path.c_str(),
wrapu, wrapv, mipmap );
_status[i].texture_loaded = true;
}
}
return true;
}
ssgSimpleState *
SGMaterial::get_state (int n) const
{
if (_status.size() == 0) {
SG_LOG( SG_GENERAL, SG_WARN, "No state available.");
return NULL;
}
int r = int( sg_random() * _status.size() );
return (n >= 0) ? _status[n].state : _status[r].state;
}
@@ -204,45 +217,53 @@ SGMaterial::build_ssg_state( bool defer_tex_load )
{
GLenum shade_model = GL_SMOOTH;
state = new ssgSimpleState();
state->ref();
for (int i = 0; i < _status.size(); i++)
{
ssgSimpleState *state = new ssgSimpleState();
state->ref();
// Set up the textured state
state->setShadeModel( shade_model );
state->enable( GL_LIGHTING );
state->enable ( GL_CULL_FACE ) ;
state->enable( GL_TEXTURE_2D );
state->disable( GL_BLEND );
state->disable( GL_ALPHA_TEST );
if ( !defer_tex_load ) {
SG_LOG(SG_INPUT, SG_INFO, " " << texture_path );
state->setTexture( (char *)texture_path.c_str(), wrapu, wrapv );
texture_loaded = true;
} else {
texture_loaded = false;
}
state->enable( GL_COLOR_MATERIAL );
state->setMaterial ( GL_AMBIENT,
ambient[0], ambient[1],
ambient[2], ambient[3] ) ;
state->setMaterial ( GL_DIFFUSE,
// Set up the textured state
state->setShadeModel( shade_model );
state->enable( GL_LIGHTING );
state->enable ( GL_CULL_FACE ) ;
state->enable( GL_TEXTURE_2D );
state->disable( GL_BLEND );
state->disable( GL_ALPHA_TEST );
if ( !defer_tex_load ) {
SG_LOG(SG_INPUT, SG_INFO, " " << _status[i].texture_path );
state->setTexture( (char *)_status[i].texture_path.c_str(),
wrapu, wrapv );
_status[i].texture_loaded = true;
} else {
_status[i].texture_loaded = false;
}
state->enable( GL_COLOR_MATERIAL );
state->setMaterial ( GL_AMBIENT,
ambient[0], ambient[1],
ambient[2], ambient[3] ) ;
state->setMaterial ( GL_DIFFUSE,
diffuse[0], diffuse[1],
diffuse[2], diffuse[3] ) ;
state->setMaterial ( GL_SPECULAR,
state->setMaterial ( GL_SPECULAR,
specular[0], specular[1],
specular[2], specular[3] ) ;
state->setMaterial ( GL_EMISSION,
state->setMaterial ( GL_EMISSION,
emission[0], emission[1],
emission[2], emission[3] ) ;
state->setShininess ( shininess );
state->setShininess ( shininess );
_status[i].state = state;
}
}
void SGMaterial::set_ssg_state( ssgSimpleState *s )
{
state = s;
state->ref();
texture_loaded = true;
s->ref();
_internal_state st = { s, "", true };
_status.push_back( st );
}
// end of mat.cxx

View File

@@ -39,6 +39,7 @@
#include <plib/ssg.h>
#include <simgear/props/props.hxx>
#include <simgear/math/sg_random.h>
#include "matmodel.hxx"
@@ -111,13 +112,19 @@ public:
* @return true if the texture loaded, false if it was loaded
* already.
*/
virtual bool load_texture ();
virtual bool load_texture (int n = -1);
/**
* Get the textured state.
*/
virtual inline ssgSimpleState *get_state () const { return state; }
virtual ssgSimpleState *get_state (int n = -1) const;
/**
* Get the number of textures assigned to this material.
*/
virtual inline int get_num() const { return _status.size(); }
/**
@@ -190,6 +197,13 @@ protected:
*/
virtual void init();
protected:
typedef struct {
ssgSimpleState *state;
string texture_path;
bool texture_loaded;
} _internal_state;
private:
@@ -198,11 +212,8 @@ private:
// Internal state.
////////////////////////////////////////////////////////////////////
// names
string texture_path;
// pointers to ssg states
ssgSimpleState *state;
// texture status
vector<_internal_state> _status;
// texture size
double xsize, ysize;
@@ -220,9 +231,6 @@ private:
sgVec4 ambient, diffuse, specular, emission;
double shininess;
// true if texture loading deferred, and not yet loaded
bool texture_loaded;
vector<SGMatModelGroup *> object_groups;
// ref count so we can properly delete if we have multiple