From 6db9138eeb183d8ad00f0ccaf6a4e6ecb49e0197 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Sat, 15 Aug 2009 14:00:51 +0200 Subject: [PATCH] wip for effects in models multi-index for effect attributes --- simgear/scene/material/Effect.cxx | 14 ++- simgear/scene/material/EffectBuilder.hxx | 121 ++++++++++++++++------ simgear/scene/material/TextureBuilder.cxx | 9 +- simgear/scene/material/makeEffect.cxx | 1 + simgear/scene/model/ModelRegistry.cxx | 3 - simgear/scene/model/SGReaderWriterXML.cxx | 3 + 6 files changed, 110 insertions(+), 41 deletions(-) diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index 14ad2022..3bd14cc3 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -73,6 +73,8 @@ using namespace std; using namespace osg; using namespace osgUtil; +using namespace effect; + Effect::Effect() { } @@ -305,7 +307,7 @@ struct MaterialBuilder : public PassAttributeBuilder const osgDB::ReaderWriter::Options* options); }; -EffectNameValue colorModes[] = +EffectNameValue colorModeInit[] = { { "ambient", Material::AMBIENT }, { "ambient-and-diffuse", Material::AMBIENT_AND_DIFFUSE }, @@ -314,6 +316,7 @@ EffectNameValue colorModes[] = { "specular", Material::SPECULAR }, { "off", Material::OFF } }; +EffectPropertyMap colorModes(colorModeInit); void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop, @@ -394,7 +397,7 @@ struct AlphaTestBuilder : public PassAttributeBuilder InstallAttributeBuilder installAlphaTest("alpha-test"); -EffectNameValue texEnvModes[] = +EffectNameValue texEnvModesInit[] = { {"add", TexEnv::ADD}, {"blend", TexEnv::BLEND}, @@ -402,6 +405,7 @@ EffectNameValue texEnvModes[] = {"modulate", TexEnv::MODULATE}, {"replace", TexEnv::REPLACE} }; +EffectPropertyMap texEnvModes(texEnvModesInit); TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop) { @@ -564,7 +568,7 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass, InstallAttributeBuilder installShaderProgram("program"); -EffectNameValue uniformTypes[] = +EffectNameValue uniformTypesInit[] = { {"float", Uniform::FLOAT}, {"float-vec3", Uniform::FLOAT_VEC3}, @@ -573,6 +577,7 @@ EffectNameValue uniformTypes[] = {"sampler-2d", Uniform::SAMPLER_2D}, {"sampler-3d", Uniform::SAMPLER_3D} }; +EffectPropertyMap uniformTypes(uniformTypesInit); struct UniformBuilder :public PassAttributeBuilder { @@ -660,12 +665,13 @@ struct NameBuilder : public PassAttributeBuilder InstallAttributeBuilder installName("name"); -EffectNameValue polygonModeModes[] = +EffectNameValue polygonModeModesInit[] = { {"fill", PolygonMode::FILL}, {"line", PolygonMode::LINE}, {"point", PolygonMode::POINT} }; +EffectPropertyMap polygonModeModes(polygonModeModesInit); struct PolygonModeBuilder : public PassAttributeBuilder { diff --git a/simgear/scene/material/EffectBuilder.hxx b/simgear/scene/material/EffectBuilder.hxx index 831c9fab..e263f6ef 100644 --- a/simgear/scene/material/EffectBuilder.hxx +++ b/simgear/scene/material/EffectBuilder.hxx @@ -24,6 +24,10 @@ #include +#include +#include +#include + #include #include #include @@ -79,57 +83,112 @@ protected: } }; -// 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 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 -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 +struct bidirectional_map { + typedef std::pair 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, member >, + ordered_unique< + tag, member > + > + > type; +}; + +template +struct EffectPropertyMap +{ + typedef typename bidirectional_map::type BMap; + BMap _map; + template + EffectPropertyMap(const EffectNameValue (&attrs)[N]); +}; + +template +template +EffectPropertyMap::EffectPropertyMap(const EffectNameValue (&attrs)[N]) +{ + for (int i = 0; i < N; ++i) + _map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second)); +} + +} + +template +bool findAttr(const effect::EffectPropertyMap& pMap, + const SGPropertyNode* prop, + T& result) +{ + using namespace effect; if (!prop) return false; const char* name = prop->getStringValue(); if (!name) return false; - std::pair itrs - = std::equal_range(&attrs[0], &attrs[N], name, typename ENV::Compare()); - if (itrs.first == itrs.second) { + typename EffectPropertyMap::BMap::iterator itr + = pMap._map.get().find(name); + if (itr == pMap._map.end()) { return false; } else { - result = itrs.first->second; + result = itr->second; return true; } } +template +std::string findName(const effect::EffectPropertyMap& pMap, T value) +{ + using namespace effect; + std::string result; + typename EffectPropertyMap::BMap::template index_iterator::type itr + = pMap._map.get().find(value); + if (itr != pMap._map.get().end()) + result = itr->first; + return result; +} + +template +std::string findName(const effect::EffectPropertyMap& pMap, GLenum value) +{ + return findName(pMap, static_cast(value)); +} + /** * Given a property node from a pass, get its value either from it or * from the effect parameters. diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index a6490c92..cc927341 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -41,6 +41,8 @@ namespace simgear 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, @@ -56,7 +58,7 @@ typedef boost::tuple filterModes[] = +EffectNameValue filterModesInit[] = { { "linear", Texture::LINEAR }, { "linear-mipmap-linear", Texture::LINEAR_MIPMAP_LINEAR}, @@ -65,8 +67,9 @@ EffectNameValue filterModes[] = { "nearest-mipmap-linear", Texture::NEAREST_MIPMAP_LINEAR}, { "nearest-mipmap-nearest", Texture::NEAREST_MIPMAP_NEAREST} }; +EffectPropertyMap filterModes(filterModesInit); -EffectNameValue wrapModes[] = +EffectNameValue wrapModesInit[] = { {"clamp", Texture::CLAMP}, {"clamp-to-border", Texture::CLAMP_TO_BORDER}, @@ -74,7 +77,7 @@ EffectNameValue wrapModes[] = {"mirror", Texture::MIRROR}, {"repeat", Texture::REPEAT} }; - +EffectPropertyMap wrapModes(wrapModesInit); TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props, diff --git a/simgear/scene/material/makeEffect.cxx b/simgear/scene/material/makeEffect.cxx index b2d37ff2..786fc2f5 100644 --- a/simgear/scene/material/makeEffect.cxx +++ b/simgear/scene/material/makeEffect.cxx @@ -32,6 +32,7 @@ #include #include #include +#include #include namespace simgear diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index 1728020d..8a13c762 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -208,7 +208,6 @@ ModelRegistry::readImage(const string& fileName, ScopedLock 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); @@ -357,8 +356,6 @@ ModelRegistry::readNode(const string& fileName, { ScopedLock lock(readerMutex); - // XXX Workaround for OSG plugin bug. -// Registry* registry = Registry::instance(); ReaderWriter::ReadResult res; CallbackMap::iterator iter = nodeCallbackMap.find(getFileExtension(fileName)); diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx index 75026bcf..2a4d612e 100644 --- a/simgear/scene/model/SGReaderWriterXML.cxx +++ b/simgear/scene/model/SGReaderWriterXML.cxx @@ -193,6 +193,9 @@ sgLoad3DModel_internal(const string &path, 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 options -- 2.39.5