From 30209901213cac34a70708feb3d6ff39dd1a5ad4 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Fri, 2 Mar 2012 23:04:18 +0000 Subject: [PATCH] Evaluate statements in materials.xml at tile loading time rather than on startup. This will allow changing between winter and summer textures in-sim, and also allow more interesting regional textures to be defined. --- simgear/scene/material/mat.cxx | 28 +++++++++++++++++++++----- simgear/scene/material/mat.hxx | 28 ++++++++++++++++++++++---- simgear/scene/material/matlib.cxx | 33 +++++++++++++++---------------- simgear/scene/material/matlib.hxx | 6 ++++-- 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index defab591..cf68c2d6 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -87,21 +88,23 @@ void SGMaterial::_internal_state::add_texture(const std::string &t, int i) } SGMaterial::SGMaterial( const SGReaderWriterOptions* options, - const SGPropertyNode *props ) + const SGPropertyNode *props, + SGPropertyNode *prop_root ) { init(); - read_properties( options, props ); + read_properties( options, props, prop_root ); buildEffectProperties(options); } SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options, - const SGPropertyNode *props ) + const SGPropertyNode *props, + SGPropertyNode *prop_root) { osg::ref_ptr sgOptions; if (options) sgOptions = new SGReaderWriterOptions(*options); init(); - read_properties( sgOptions.get(), props ); + read_properties( sgOptions.get(), props, prop_root); buildEffectProperties(sgOptions.get()); } @@ -116,7 +119,8 @@ SGMaterial::~SGMaterial (void) void SGMaterial::read_properties(const SGReaderWriterOptions* options, - const SGPropertyNode *props) + const SGPropertyNode *props, + SGPropertyNode *prop_root) { std::vector dds; std::vector textures = props->getChildren("texture"); @@ -226,6 +230,12 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, } object_mask->setImage(image); + + // We force the filtering to be nearest, as the red channel (rotation) + // in particular, doesn't make sense to be interpolated between pixels. + object_mask->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); + object_mask->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + object_mask->setDataVariance(osg::Object::STATIC); object_mask->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); object_mask->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); @@ -309,6 +319,14 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, if (name) glyphs[name] = new SGMaterialGlyph(glyph_nodes[i]); } + + // Read conditions node + const SGPropertyNode *conditionNode = props->getChild("condition"); + if (conditionNode) { + condition = sgReadCondition(prop_root, conditionNode); + } + + } diff --git a/simgear/scene/material/mat.hxx b/simgear/scene/material/mat.hxx index c6da6101..c3b7b3c3 100644 --- a/simgear/scene/material/mat.hxx +++ b/simgear/scene/material/mat.hxx @@ -52,6 +52,7 @@ class StateSet; #include #include #include +#include #include "matmodel.hxx" @@ -88,10 +89,13 @@ public: * state information for the material. This node is usually * loaded from the $FG_ROOT/materials.xml file. */ - SGMaterial( const osgDB::ReaderWriter::Options*, const SGPropertyNode *props); + SGMaterial( const osgDB::ReaderWriter::Options*, + const SGPropertyNode *props, + SGPropertyNode *prop_root); SGMaterial(const simgear::SGReaderWriterOptions*, - const SGPropertyNode *props); + const SGPropertyNode *props, + SGPropertyNode *prop_root); /** * Destructor. */ @@ -233,6 +237,18 @@ public: SGMatModelGroup * get_object_group (int index) const { return object_groups[index]; } + + /** + * Evaluate whether this material is valid given the current global + * property state. + */ + bool valid() { + if (condition) { + return condition->test(); + } else { + return true; + } + } /** * Return pointer to glyph class, or 0 if it doesn't exist. @@ -352,13 +368,17 @@ private: // Object mask, a simple RGB texture used as a mask when placing // random vegetation, objects and buildings std::vector _masks; - + + // Condition, indicating when this material is active + SGSharedPtr condition; + //////////////////////////////////////////////////////////////////// // Internal constructors and methods. //////////////////////////////////////////////////////////////////// void read_properties(const simgear::SGReaderWriterOptions* options, - const SGPropertyNode *props); + const SGPropertyNode *props, + SGPropertyNode *prop_root); void buildEffectProperties(const simgear::SGReaderWriterOptions* options); simgear::Effect* get_effect(int i); }; diff --git a/simgear/scene/material/matlib.cxx b/simgear/scene/material/matlib.cxx index 5de7e01c..e69fd60d 100644 --- a/simgear/scene/material/matlib.cxx +++ b/simgear/scene/material/matlib.cxx @@ -75,23 +75,13 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath, for (int i = 0; i < nMaterials; i++) { const SGPropertyNode *node = materials.getChild(i); if (!strcmp(node->getName(), "material")) { - const SGPropertyNode *conditionNode = node->getChild("condition"); - if (conditionNode) { - SGSharedPtr condition = sgReadCondition(prop_root, conditionNode); - if (!condition->test()) { - SG_LOG(SG_INPUT, SG_DEBUG, "Skipping material entry #" - << i << " (condition false)"); - continue; - } - } - - SGSharedPtr m = new SGMaterial(options.get(), node); + SGSharedPtr m = new SGMaterial(options.get(), node, prop_root); vectornames = node->getChildren("name"); for ( unsigned int j = 0; j < names.size(); j++ ) { string name = names[j]->getStringValue(); // cerr << "Material " << name << endl; - matlib[name] = m; + matlib[name].push_back(m); m->add_name(name); SG_LOG( SG_TERRAIN, SG_DEBUG, " Loading material " << names[j]->getStringValue() ); @@ -109,9 +99,19 @@ bool SGMaterialLib::load( const string &fg_root, const string& mpath, SGMaterial *SGMaterialLib::find( const string& material ) { SGMaterial *result = NULL; material_map_iterator it = matlib.find( material ); - if ( it != end() ) { - result = it->second; - return result; + if ( it != end() ) { + // We now have a list of materials that match this + // name. Find the first one that either doesn't have + // a condition, or has a condition that evaluates + // to true. + material_list_iterator iter = it->second.begin(); + while (iter != it->second.end()) { + result = *iter; + if (result->valid()) { + return result; + } + iter++; + } } return NULL; @@ -122,8 +122,7 @@ SGMaterialLib::~SGMaterialLib ( void ) { SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size()); } -const SGMaterial* -SGMaterialLib::findMaterial(const osg::Geode* geode) +const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode) { if (!geode) return 0; diff --git a/simgear/scene/material/matlib.hxx b/simgear/scene/material/matlib.hxx index b3e8c900..7d52e5c1 100644 --- a/simgear/scene/material/matlib.hxx +++ b/simgear/scene/material/matlib.hxx @@ -58,7 +58,9 @@ class SGMaterialLib { private: // associative array of materials - typedef map < string, SGSharedPtr > material_map; + typedef std::vector< SGSharedPtr > material_list; + typedef material_list::iterator material_list_iterator; + typedef map < string, material_list> material_map; typedef material_map::iterator material_map_iterator; typedef material_map::const_iterator const_material_map_iterator; @@ -81,7 +83,7 @@ public: material_map_iterator end() { return matlib.end(); } const_material_map_iterator end() const { return matlib.end(); } - static const SGMaterial* findMaterial(const osg::Geode* geode); + static const SGMaterial *findMaterial(const osg::Geode* geode); // Destructor ~SGMaterialLib ( void ); -- 2.39.5