From cb07210bc7e61fe0a45836c4e614a0e43cfb33d1 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 16 Oct 2009 12:55:44 +0200 Subject: [PATCH] Move Texture unit builder into TexBuilder.cxx Do the refactoring necessary to make that work. --- simgear/scene/material/Effect.cxx | 125 +--------------------- simgear/scene/material/EffectBuilder.cxx | 9 ++ simgear/scene/material/EffectBuilder.hxx | 45 ++++++++ simgear/scene/material/TextureBuilder.cxx | 83 ++++++++++++++ simgear/scene/material/TextureBuilder.hxx | 7 ++ 5 files changed, 148 insertions(+), 121 deletions(-) diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index a94267fc..0ec20275 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -134,27 +133,6 @@ Effect::~Effect() { } -class PassAttributeBuilder : public Referenced -{ -public: - virtual void buildAttribute(Effect* effect, Pass* pass, - const SGPropertyNode* prop, - const osgDB::ReaderWriter::Options* options) - = 0; -}; - -typedef map > PassAttrMap; -PassAttrMap passAttrMap; - -template -struct InstallAttributeBuilder -{ - InstallAttributeBuilder(const string& name) - { - passAttrMap.insert(make_pair(name, new T)); - } -}; - void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop, const osgDB::ReaderWriter::Options* options) { @@ -162,9 +140,10 @@ void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop, tniq->passes.push_back(pass); for (int i = 0; i < prop->nChildren(); ++i) { const SGPropertyNode* attrProp = prop->getChild(i); - PassAttrMap::iterator itr = passAttrMap.find(attrProp->getName()); - if (itr != passAttrMap.end()) - itr->second->buildAttribute(effect, pass, attrProp, options); + PassAttributeBuilder* builder + = PassAttributeBuilder::find(attrProp->getNameString()); + if (builder) + builder->buildAttribute(effect, pass, attrProp, options); else SG_LOG(SG_INPUT, SG_ALERT, "skipping unknown pass attribute " << attrProp->getName()); @@ -197,19 +176,6 @@ osg::Vec4f getColor(const SGPropertyNode* prop) } } -// The description of an attribute may exist in a pass' XML, but a -// derived effect might want to disable the attribute altogether. So, -// some attributes have an "active" property; if it exists and is -// false, the OSG attribute is not built at all. This is different -// from any OSG mode settings that might be around. - -bool isAttributeActive(Effect* effect, const SGPropertyNode* prop) -{ - const SGPropertyNode* activeProp - = getEffectPropertyChild(effect, prop, "active"); - return !activeProp || activeProp->getValue(); -} - struct LightingBuilder : public PassAttributeBuilder { void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop, @@ -566,89 +532,6 @@ struct AlphaTestBuilder : public PassAttributeBuilder InstallAttributeBuilder installAlphaTest("alpha-test"); -EffectNameValue texEnvModesInit[] = -{ - {"add", TexEnv::ADD}, - {"blend", TexEnv::BLEND}, - {"decal", TexEnv::DECAL}, - {"modulate", TexEnv::MODULATE}, - {"replace", TexEnv::REPLACE} -}; -EffectPropertyMap texEnvModes(texEnvModesInit); - -TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop) -{ - const SGPropertyNode* modeProp = getEffectPropertyChild(effect, prop, - "mode"); - const SGPropertyNode* colorProp = getEffectPropertyChild(effect, prop, - "color"); - if (!modeProp) - return 0; - TexEnv::Mode mode = TexEnv::MODULATE; - findAttr(texEnvModes, modeProp, mode); - if (mode == TexEnv::MODULATE) { - return StateAttributeFactory::instance()->getStandardTexEnv(); - } - TexEnv* env = new TexEnv(mode); - if (colorProp) - env->setColor(toOsg(colorProp->getValue())); - return env; - } - - -struct TextureUnitBuilder : PassAttributeBuilder -{ - void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop, - const osgDB::ReaderWriter::Options* options); -}; - -void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass, - const SGPropertyNode* prop, - const osgDB::ReaderWriter::Options* options) -{ - if (!isAttributeActive(effect, prop)) - return; - // Decode the texture unit - int unit = 0; - const SGPropertyNode* pUnit = prop->getChild("unit"); - if (pUnit) { - unit = pUnit->getValue(); - } else { - const SGPropertyNode* pName = prop->getChild("name"); - if (pName) - try { - unit = boost::lexical_cast(pName->getStringValue()); - } catch (boost::bad_lexical_cast& lex) { - SG_LOG(SG_INPUT, SG_ALERT, "can't decode name as texture unit " - << lex.what()); - } - } - const SGPropertyNode* pType = getEffectPropertyChild(effect, prop, "type"); - string type; - if (!pType) - type = "2d"; - else - type = pType->getStringValue(); - Texture* texture = 0; - try { - texture = TextureBuilder::buildFromType(effect, type, prop, - options); - } - catch (BuilderException& e) { - SG_LOG(SG_INPUT, SG_ALERT, "No image file for texture, using white "); - texture = StateAttributeFactory::instance()->getWhiteTexture(); - } - pass->setTextureAttributeAndModes(unit, texture); - const SGPropertyNode* envProp = prop->getChild("environment"); - if (envProp) { - TexEnv* env = buildTexEnv(effect, envProp); - if (env) - pass->setTextureAttributeAndModes(unit, env); - } -} - - - InstallAttributeBuilder textureUnitBuilder("texture-unit"); typedef map > ProgramMap; diff --git a/simgear/scene/material/EffectBuilder.cxx b/simgear/scene/material/EffectBuilder.cxx index 32168a9c..a485f110 100644 --- a/simgear/scene/material/EffectBuilder.cxx +++ b/simgear/scene/material/EffectBuilder.cxx @@ -56,5 +56,14 @@ BuilderException::BuilderException(const std::string& message, BuilderException::~BuilderException() throw() { + } + +bool isAttributeActive(Effect* effect, const SGPropertyNode* prop) +{ + const SGPropertyNode* activeProp + = getEffectPropertyChild(effect, prop, "active"); + return !activeProp || activeProp->getValue(); +} + } diff --git a/simgear/scene/material/EffectBuilder.hxx b/simgear/scene/material/EffectBuilder.hxx index e263f6ef..4b2ebad3 100644 --- a/simgear/scene/material/EffectBuilder.hxx +++ b/simgear/scene/material/EffectBuilder.hxx @@ -40,6 +40,7 @@ namespace simgear { class Effect; +class Pass; /** * Builder that returns an object, probably an OSG object. @@ -212,5 +213,49 @@ public: BuilderException(const std::string& message, const std::string& = ""); virtual ~BuilderException() throw(); }; + +class PassAttributeBuilder : public SGReferenced +{ +protected: + typedef std::map > + PassAttrMap; + + struct PassAttrMapSingleton : public simgear::Singleton + { + PassAttrMap passAttrMap; + }; +public: + virtual void buildAttribute(Effect* effect, Pass* pass, + const SGPropertyNode* prop, + const osgDB::ReaderWriter::Options* options) + = 0; + static PassAttributeBuilder* find(const std::string& str) + { + PassAttrMap::iterator itr + = PassAttrMapSingleton::instance()->passAttrMap.find(str); + if (itr == PassAttrMapSingleton::instance()->passAttrMap.end()) + return 0; + else + return itr->second.ptr(); + } + template friend class InstallAttributeBuilder; +}; + +template +struct InstallAttributeBuilder +{ + InstallAttributeBuilder(const string& name) + { + PassAttributeBuilder::PassAttrMapSingleton::instance() + ->passAttrMap.insert(make_pair(name, new T)); + } +}; + +// The description of an attribute may exist in a pass' XML, but a +// derived effect might want to disable the attribute altogether. So, +// some attributes have an "active" property; if it exists and is +// false, the OSG attribute is not built at all. This is different +// from any OSG mode settings that might be around. +bool isAttributeActive(Effect* effect, const SGPropertyNode* prop); } #endif diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index 2623c4a7..0db435de 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -20,12 +20,17 @@ #include "TextureBuilder.hxx" +#include "Pass.hxx" + +#include +#include #include #include #include #include #include +#include #include #include @@ -56,6 +61,84 @@ typedef boost::tuple TexTuple; +EffectNameValue texEnvModesInit[] = +{ + {"add", TexEnv::ADD}, + {"blend", TexEnv::BLEND}, + {"decal", TexEnv::DECAL}, + {"modulate", TexEnv::MODULATE}, + {"replace", TexEnv::REPLACE} +}; +EffectPropertyMap texEnvModes(texEnvModesInit); + +TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop) +{ + const SGPropertyNode* modeProp = getEffectPropertyChild(effect, prop, + "mode"); + const SGPropertyNode* colorProp = getEffectPropertyChild(effect, prop, + "color"); + if (!modeProp) + return 0; + TexEnv::Mode mode = TexEnv::MODULATE; + findAttr(texEnvModes, modeProp, mode); + if (mode == TexEnv::MODULATE) { + return StateAttributeFactory::instance()->getStandardTexEnv(); + } + TexEnv* env = new TexEnv(mode); + if (colorProp) + env->setColor(toOsg(colorProp->getValue())); + return env; + } + + +void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass, + const SGPropertyNode* prop, + const osgDB::ReaderWriter::Options* options) +{ + if (!isAttributeActive(effect, prop)) + return; + // Decode the texture unit + int unit = 0; + const SGPropertyNode* pUnit = prop->getChild("unit"); + if (pUnit) { + unit = pUnit->getValue(); + } else { + const SGPropertyNode* pName = prop->getChild("name"); + if (pName) + try { + unit = boost::lexical_cast(pName->getStringValue()); + } catch (boost::bad_lexical_cast& lex) { + SG_LOG(SG_INPUT, SG_ALERT, "can't decode name as texture unit " + << lex.what()); + } + } + const SGPropertyNode* pType = getEffectPropertyChild(effect, prop, "type"); + string type; + if (!pType) + type = "2d"; + else + type = pType->getStringValue(); + Texture* texture = 0; + try { + texture = TextureBuilder::buildFromType(effect, type, prop, + options); + } + catch (BuilderException& e) { + SG_LOG(SG_INPUT, SG_ALERT, "No image file for texture, using white "); + texture = StateAttributeFactory::instance()->getWhiteTexture(); + } + pass->setTextureAttributeAndModes(unit, texture); + const SGPropertyNode* envProp = prop->getChild("environment"); + if (envProp) { + TexEnv* env = buildTexEnv(effect, envProp); + if (env) + pass->setTextureAttributeAndModes(unit, env); + } +} + +// InstallAttributeBuilder call is in Effect.cxx to force this file to +// be linked in. + namespace { EffectNameValue filterModesInit[] = diff --git a/simgear/scene/material/TextureBuilder.hxx b/simgear/scene/material/TextureBuilder.hxx index 395ca382..ca6c5494 100644 --- a/simgear/scene/material/TextureBuilder.hxx +++ b/simgear/scene/material/TextureBuilder.hxx @@ -32,6 +32,13 @@ public: const osgDB::ReaderWriter::Options* options); }; +struct TextureUnitBuilder : public PassAttributeBuilder +{ + void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop, + const osgDB::ReaderWriter::Options* options); +}; + + bool makeTextureParameters(SGPropertyNode* paramRoot, const osg::StateSet* ss); } #endif -- 2.39.5