#include <osg/ShadeModel>
#include <osg/StateSet>
#include <osg/TexEnv>
+#include <osg/Texture>
#include <osg/Texture2D>
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
}
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());
}
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");
}
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);
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);
+ }
+
+
}
#include <simgear/props/props.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
+#include <simgear/props/condition.hxx>
#include "matmodel.hxx"
* 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.
*/
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.
// Object mask, a simple RGB texture used as a mask when placing
// random vegetation, objects and buildings
std::vector<osg::Texture2D*> _masks;
-\f
+
+ // 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);
};
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() );
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;
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;
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;
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 );