Move Texture unit builder into TexBuilder.cxx

Do the refactoring necessary to make that work.
This commit is contained in:
Tim Moore
2009-10-16 12:55:44 +02:00
parent 3e40d624a8
commit cb07210bc7
5 changed files with 148 additions and 121 deletions

View File

@@ -31,7 +31,6 @@
#include <utility>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
@@ -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<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)
{
@@ -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<bool>();
}
struct LightingBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
@@ -566,89 +532,6 @@ struct AlphaTestBuilder : public PassAttributeBuilder
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;

View File

@@ -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<bool>();
}
}

View File

@@ -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<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

View File

@@ -20,12 +20,17 @@
#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>
@@ -56,6 +61,84 @@ typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
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[] =

View File

@@ -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