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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user