using namespace osg;
using namespace osgUtil;
+using namespace effect;
+
Effect::Effect()
{
}
const osgDB::ReaderWriter::Options* options);
};
-EffectNameValue<Material::ColorMode> colorModes[] =
+EffectNameValue<Material::ColorMode> colorModeInit[] =
{
{ "ambient", Material::AMBIENT },
{ "ambient-and-diffuse", Material::AMBIENT_AND_DIFFUSE },
{ "specular", Material::SPECULAR },
{ "off", Material::OFF }
};
+EffectPropertyMap<Material::ColorMode> colorModes(colorModeInit);
void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
InstallAttributeBuilder<AlphaTestBuilder> installAlphaTest("alpha-test");
-EffectNameValue<TexEnv::Mode> texEnvModes[] =
+EffectNameValue<TexEnv::Mode> texEnvModesInit[] =
{
{"add", TexEnv::ADD},
{"blend", TexEnv::BLEND},
{"modulate", TexEnv::MODULATE},
{"replace", TexEnv::REPLACE}
};
+EffectPropertyMap<TexEnv::Mode> texEnvModes(texEnvModesInit);
TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop)
{
InstallAttributeBuilder<ShaderProgramBuilder> installShaderProgram("program");
-EffectNameValue<Uniform::Type> uniformTypes[] =
+EffectNameValue<Uniform::Type> uniformTypesInit[] =
{
{"float", Uniform::FLOAT},
{"float-vec3", Uniform::FLOAT_VEC3},
{"sampler-2d", Uniform::SAMPLER_2D},
{"sampler-3d", Uniform::SAMPLER_3D}
};
+EffectPropertyMap<Uniform::Type> uniformTypes(uniformTypesInit);
struct UniformBuilder :public PassAttributeBuilder
{
InstallAttributeBuilder<NameBuilder> installName("name");
-EffectNameValue<PolygonMode::Mode> polygonModeModes[] =
+EffectNameValue<PolygonMode::Mode> polygonModeModesInit[] =
{
{"fill", PolygonMode::FILL},
{"line", PolygonMode::LINE},
{"point", PolygonMode::POINT}
};
+EffectPropertyMap<PolygonMode::Mode> polygonModeModes(polygonModeModesInit);
struct PolygonModeBuilder : public PassAttributeBuilder
{
#include <osgDB/Registry>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
#include <simgear/props/props.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
}
};
-// Simple tables of strings and constants. The table intialization
-// *must* be in alphabetical order.
+// Tables of strings and constants. We want to reconstruct the effect
+// property tree from OSG state sets, so the tables should be bi-directional.
+
+// two-way map for building StateSets from property descriptions, and
+// vice versa. Mostly copied from the boost documentation.
+
+namespace effect
+{
+using boost::multi_index_container;
+using namespace boost::multi_index;
+
+// tags for accessing both sides of a bidirectional map
+
+struct from{};
+struct to{};
+
template <typename T>
struct EffectNameValue
{
// Don't use std::pair because we want to use aggregate intialization.
-
const char* first;
T second;
- class Compare
- {
- private:
- static bool compare(const char* lhs, const char* rhs)
- {
- return std::strcmp(lhs, rhs) < 0;
- }
- public:
- bool operator()(const EffectNameValue& lhs,
- const EffectNameValue& rhs) const
- {
- return compare(lhs.first, rhs.first);
- }
- bool operator()(const char* lhs, const EffectNameValue& rhs) const
- {
- return compare(lhs, rhs.first);
- }
- bool operator()(const EffectNameValue& lhs, const char* rhs) const
- {
- return compare (lhs.first, rhs);
- }
- };
};
-template<typename ENV, typename T, int N>
-bool findAttr(const ENV (&attrs)[N], const SGPropertyNode* prop, T& result)
+// The class template bidirectional_map wraps the specification
+// of a bidirectional map based on multi_index_container.
+
+template<typename FromType,typename ToType>
+struct bidirectional_map
{
+ typedef std::pair<FromType,ToType> value_type;
+
+ /* A bidirectional map can be simulated as a multi_index_container
+ * of pairs of (FromType,ToType) with two unique indices, one
+ * for each member of the pair.
+ */
+
+ typedef multi_index_container<
+ value_type,
+ indexed_by<
+ ordered_unique<
+ tag<from>, member<value_type, FromType, &value_type::first> >,
+ ordered_unique<
+ tag<to>, member<value_type, ToType, &value_type::second> >
+ >
+ > type;
+};
+
+template<typename T>
+struct EffectPropertyMap
+{
+ typedef typename bidirectional_map<std::string, T>::type BMap;
+ BMap _map;
+ template<int N>
+ EffectPropertyMap(const EffectNameValue<T> (&attrs)[N]);
+};
+
+template<typename T>
+template<int N>
+EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
+{
+ for (int i = 0; i < N; ++i)
+ _map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second));
+}
+
+}
+
+template<typename T>
+bool findAttr(const effect::EffectPropertyMap<T>& pMap,
+ const SGPropertyNode* prop,
+ T& result)
+{
+ using namespace effect;
if (!prop)
return false;
const char* name = prop->getStringValue();
if (!name)
return false;
- std::pair<const ENV*, const ENV*> itrs
- = std::equal_range(&attrs[0], &attrs[N], name, typename ENV::Compare());
- if (itrs.first == itrs.second) {
+ typename EffectPropertyMap<T>::BMap::iterator itr
+ = pMap._map.get<from>().find(name);
+ if (itr == pMap._map.end()) {
return false;
} else {
- result = itrs.first->second;
+ result = itr->second;
return true;
}
}
+template<typename T>
+std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
+{
+ using namespace effect;
+ std::string result;
+ typename EffectPropertyMap<T>::BMap::template index_iterator<to>::type itr
+ = pMap._map.get<to>().find(value);
+ if (itr != pMap._map.get<to>().end())
+ result = itr->first;
+ return result;
+}
+
+template<typename T>
+std::string findName(const effect::EffectPropertyMap<T>& pMap, GLenum value)
+{
+ return findName(pMap, static_cast<T>(value));
+}
+
/**
* Given a property node from a pass, get its value either from it or
* from the effect parameters.
using namespace std;
using namespace osg;
+using namespace effect;
+
// Hack to force inclusion of TextureBuilder.cxx in library
osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
const SGPropertyNode*props,
namespace
{
-EffectNameValue<Texture::FilterMode> filterModes[] =
+EffectNameValue<Texture::FilterMode> filterModesInit[] =
{
{ "linear", Texture::LINEAR },
{ "linear-mipmap-linear", Texture::LINEAR_MIPMAP_LINEAR},
{ "nearest-mipmap-linear", Texture::NEAREST_MIPMAP_LINEAR},
{ "nearest-mipmap-nearest", Texture::NEAREST_MIPMAP_NEAREST}
};
+EffectPropertyMap<Texture::FilterMode> filterModes(filterModesInit);
-EffectNameValue<Texture::WrapMode> wrapModes[] =
+EffectNameValue<Texture::WrapMode> wrapModesInit[] =
{
{"clamp", Texture::CLAMP},
{"clamp-to-border", Texture::CLAMP_TO_BORDER},
{"mirror", Texture::MIRROR},
{"repeat", Texture::REPEAT}
};
-
+EffectPropertyMap<Texture::WrapMode> wrapModes(wrapModesInit);
TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
#include <simgear/debug/logstream.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
+#include <simgear/scene/util/SplicingVisitor.hxx>
#include <simgear/structure/SGExpression.hxx>
namespace simgear
ScopedLock<ReentrantMutex> lock(readerMutex);
CallbackMap::iterator iter
= imageCallbackMap.find(getFileExtension(fileName));
- // XXX Workaround for OSG plugin bug
{
if (iter != imageCallbackMap.end() && iter->second.valid())
return iter->second->readImage(fileName, opt);
{
ScopedLock<ReentrantMutex> lock(readerMutex);
- // XXX Workaround for OSG plugin bug.
-// Registry* registry = Registry::instance();
ReaderWriter::ReadResult res;
CallbackMap::iterator iter
= nodeCallbackMap.find(getFileExtension(fileName));
SGPropertyNode *mp = props->getNode("multiplay");
if (mp && prop_root && prop_root->getParent())
copyProperties(mp, prop_root);
+ } else {
+ SG_LOG(SG_INPUT, SG_DEBUG, "model without wrapper: "
+ << modelpath.str());
}
osg::ref_ptr<SGReaderWriterXMLOptions> options