From 5f21c75e02057d33dd960961d626465c0eaebd0c Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 2 Mar 2004 10:51:13 +0000 Subject: [PATCH] Make it possible to define multiple texture for a material (multiple entries in the materials.xml file). The code can return a random texture, or a pre defined texture upon request (default is random) --- simgear/scene/material/mat.cxx | 167 +++++++++++++++++++-------------- simgear/scene/material/mat.hxx | 28 ++++-- 2 files changed, 112 insertions(+), 83 deletions(-) diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 99d5753b..4efa7ad8 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -30,41 +30,18 @@ #include SG_USING_STD(map); -#include +#include #ifdef SG_MATH_EXCEPTION_CLASH # include #endif #include -#include #include #include #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 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(); - - // 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, + 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, " " << _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 diff --git a/simgear/scene/material/mat.hxx b/simgear/scene/material/mat.hxx index 62a46afc..084f736f 100644 --- a/simgear/scene/material/mat.hxx +++ b/simgear/scene/material/mat.hxx @@ -39,6 +39,7 @@ #include #include +#include #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 object_groups; // ref count so we can properly delete if we have multiple -- 2.39.5