Evaluate <condition> 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.
This commit is contained in:
Stuart Buchanan
2012-03-02 23:04:18 +00:00
parent 27219e0f58
commit 3020990121
4 changed files with 67 additions and 28 deletions

View File

@@ -40,6 +40,7 @@
#include <osg/ShadeModel>
#include <osg/StateSet>
#include <osg/TexEnv>
#include <osg/Texture>
#include <osg/Texture2D>
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
@@ -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<const SGReaderWriterOptions> 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<bool> dds;
std::vector<SGPropertyNode_ptr> 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);
}
}

View File

@@ -52,6 +52,7 @@ class StateSet;
#include <simgear/props/props.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/props/condition.hxx>
#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<osg::Texture2D*> _masks;
// Condition, indicating when this material is active
SGSharedPtr<const SGCondition> 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);
};

View File

@@ -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<const SGCondition> condition = sgReadCondition(prop_root, conditionNode);
if (!condition->test()) {
SG_LOG(SG_INPUT, SG_DEBUG, "Skipping material entry #"
<< i << " (condition false)");
continue;
}
}
SGSharedPtr<SGMaterial> m = new SGMaterial(options.get(), node);
SGSharedPtr<SGMaterial> m = new SGMaterial(options.get(), node, prop_root);
vector<SGPropertyNode_ptr>names = 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;

View File

@@ -58,7 +58,9 @@ class SGMaterialLib {
private:
// associative array of materials
typedef map < string, SGSharedPtr<SGMaterial> > material_map;
typedef std::vector< SGSharedPtr<SGMaterial> > 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 );