#include <utility>
#include <boost/foreach.hpp>
-#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
{
}
-class PassAttributeBuilder : public Referenced
-{
-public:
- virtual void buildAttribute(Effect* effect, Pass* pass,
- const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
- = 0;
-};
-
-typedef map<const string, ref_ptr<PassAttributeBuilder> > PassAttrMap;
-PassAttrMap passAttrMap;
-
-template<typename T>
-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)
{
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());
}
}
-// 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<bool>();
-}
-
struct LightingBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
InstallAttributeBuilder<AlphaTestBuilder> installAlphaTest("alpha-test");
-EffectNameValue<TexEnv::Mode> texEnvModesInit[] =
-{
- {"add", TexEnv::ADD},
- {"blend", TexEnv::BLEND},
- {"decal", TexEnv::DECAL},
- {"modulate", TexEnv::MODULATE},
- {"replace", TexEnv::REPLACE}
-};
-EffectPropertyMap<TexEnv::Mode> 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<SGVec4d>()));
- 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<int>();
- } else {
- const SGPropertyNode* pName = prop->getChild("name");
- if (pName)
- try {
- unit = boost::lexical_cast<int>(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> textureUnitBuilder("texture-unit");
typedef map<string, ref_ptr<Program> > ProgramMap;
namespace simgear
{
class Effect;
+class Pass;
/**
* Builder that returns an object, probably an OSG object.
BuilderException(const std::string& message, const std::string& = "");
virtual ~BuilderException() throw();
};
+
+class PassAttributeBuilder : public SGReferenced
+{
+protected:
+ typedef std::map<const std::string, SGSharedPtr<PassAttributeBuilder> >
+ PassAttrMap;
+
+ struct PassAttrMapSingleton : public simgear::Singleton<PassAttrMapSingleton>
+ {
+ 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<typename T> friend class InstallAttributeBuilder;
+};
+
+template<typename T>
+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
#include "TextureBuilder.hxx"
+#include "Pass.hxx"
+
+#include <osg/TexEnv>
+#include <osg/TexEnvCombine>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/TextureRectangle>
#include <osgDB/FileUtils>
+#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
Texture::WrapMode, Texture::WrapMode, Texture::WrapMode,
string> TexTuple;
+EffectNameValue<TexEnv::Mode> texEnvModesInit[] =
+{
+ {"add", TexEnv::ADD},
+ {"blend", TexEnv::BLEND},
+ {"decal", TexEnv::DECAL},
+ {"modulate", TexEnv::MODULATE},
+ {"replace", TexEnv::REPLACE}
+};
+EffectPropertyMap<TexEnv::Mode> 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<SGVec4d>()));
+ 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<int>();
+ } else {
+ const SGPropertyNode* pName = prop->getChild("name");
+ if (pName)
+ try {
+ unit = boost::lexical_cast<int>(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<Texture::FilterMode> filterModesInit[] =