# include <simgear_config.h>
#endif
-#if defined ( __CYGWIN__ )
-#include <ieeefp.h>
-#endif
-
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/structure/exception.hxx>
#include <string.h>
#include <string>
-#include <osg/AlphaFunc>
-#include <osg/BlendFunc>
-#include <osg/CullFace>
-#include <osg/Material>
-#include <osg/Point>
-#include <osg/PointSprite>
-#include <osg/PolygonMode>
-#include <osg/PolygonOffset>
-#include <osg/StateSet>
-#include <osg/TexEnv>
-#include <osg/TexGen>
-#include <osg/Texture2D>
+#include <osgDB/Registry>
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
#include "mat.hxx"
using std::string;
+
+class SGMaterialLib::MatLibPrivate
+{
+public:
+ SGMutex mutex;
+};
+
// Constructor
-SGMaterialLib::SGMaterialLib ( void ) {
+SGMaterialLib::SGMaterialLib ( void ) :
+ d(new MatLibPrivate)
+{
}
// Load a library of material properties
<< ex.getMessage() );
throw;
}
-
+ osg::ref_ptr<osgDB::Options> options
+ = new osgDB::Options;
+ options->setObjectCacheHint(osgDB::Options::CACHE_ALL);
+ options->setDatabasePath(fg_root);
int nMaterials = materials.nChildren();
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, prop_root);
- SGSharedPtr<SGMaterial> m = new SGMaterial(fg_root, node);
-
- vector<SGPropertyNode_ptr>names = node->getChildren("name");
+ std::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_INFO, " Loading material "
+ SG_LOG( SG_TERRAIN, SG_DEBUG, " Loading material "
<< names[j]->getStringValue() );
}
} else {
}
// find a material record by material name
-SGMaterial *SGMaterialLib::find( const string& material ) {
+SGMaterial *SGMaterialLib::find( const string& material ) const
+{
SGMaterial *result = NULL;
- material_map_iterator it = matlib.find( material );
- if ( it != end() ) {
- result = it->second;
- return result;
+ const_material_map_iterator it = matlib.find( material );
+ 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::const_iterator iter = it->second.begin();
+ while (iter != it->second.end()) {
+ result = *iter;
+ if (result->valid()) {
+ return result;
+ }
+ iter++;
+ }
}
return NULL;
}
+void SGMaterialLib::refreshActiveMaterials()
+{
+ active_material_cache newCache;
+ material_map_iterator it = matlib.begin();
+ for (; it != matlib.end(); ++it) {
+ newCache[it->first] = find(it->first);
+ }
+
+ // use this approach to minimise the time we're holding the lock
+ // lock on the mutex (and hence, would block findCached calls)
+ SGGuard<SGMutex> g(d->mutex);
+ active_cache = newCache;
+}
+
+SGMaterial *SGMaterialLib::findCached( const string& material ) const
+{
+ SGGuard<SGMutex> g(d->mutex);
+
+ active_material_cache::const_iterator it = active_cache.find(material);
+ if (it == active_cache.end())
+ return NULL;
+
+ return it->second;
+}
+
// Destructor
SGMaterialLib::~SGMaterialLib ( void ) {
SG_LOG( SG_GENERAL, SG_INFO, "SGMaterialLib::~SGMaterialLib() size=" << matlib.size());
}
-const SGMaterial*
-SGMaterialLib::findMaterial(const simgear::Effect* effect)
+const SGMaterial *SGMaterialLib::findMaterial(const osg::Geode* geode)
{
- if (!effect)
- return 0;
-
- const SGMaterialUserData* matUserData
- = dynamic_cast<const SGMaterialUserData*>(effect->getUserData());
- if (!matUserData)
- return 0;
- else
- return matUserData->getMaterial();
+ if (!geode)
+ return 0;
+ const simgear::EffectGeode* effectGeode;
+ effectGeode = dynamic_cast<const simgear::EffectGeode*>(geode);
+ if (!effectGeode)
+ return 0;
+ const simgear::Effect* effect = effectGeode->getEffect();
+ if (!effect)
+ return 0;
+ const SGMaterialUserData* userData;
+ userData = dynamic_cast<const SGMaterialUserData*>(effect->getUserData());
+ if (!userData)
+ return 0;
+ return userData->getMaterial();
}