Move Texture unit builder into TexBuilder.cxx
Do the refactoring necessary to make that work.
This commit is contained in:
@@ -31,7 +31,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <boost/tuple/tuple_comparison.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,
|
void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
|
||||||
const osgDB::ReaderWriter::Options* options)
|
const osgDB::ReaderWriter::Options* options)
|
||||||
{
|
{
|
||||||
@@ -162,9 +140,10 @@ void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
|
|||||||
tniq->passes.push_back(pass);
|
tniq->passes.push_back(pass);
|
||||||
for (int i = 0; i < prop->nChildren(); ++i) {
|
for (int i = 0; i < prop->nChildren(); ++i) {
|
||||||
const SGPropertyNode* attrProp = prop->getChild(i);
|
const SGPropertyNode* attrProp = prop->getChild(i);
|
||||||
PassAttrMap::iterator itr = passAttrMap.find(attrProp->getName());
|
PassAttributeBuilder* builder
|
||||||
if (itr != passAttrMap.end())
|
= PassAttributeBuilder::find(attrProp->getNameString());
|
||||||
itr->second->buildAttribute(effect, pass, attrProp, options);
|
if (builder)
|
||||||
|
builder->buildAttribute(effect, pass, attrProp, options);
|
||||||
else
|
else
|
||||||
SG_LOG(SG_INPUT, SG_ALERT,
|
SG_LOG(SG_INPUT, SG_ALERT,
|
||||||
"skipping unknown pass attribute " << attrProp->getName());
|
"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
|
struct LightingBuilder : public PassAttributeBuilder
|
||||||
{
|
{
|
||||||
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
|
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
|
||||||
@@ -566,89 +532,6 @@ struct AlphaTestBuilder : public PassAttributeBuilder
|
|||||||
|
|
||||||
InstallAttributeBuilder<AlphaTestBuilder> installAlphaTest("alpha-test");
|
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");
|
InstallAttributeBuilder<TextureUnitBuilder> textureUnitBuilder("texture-unit");
|
||||||
|
|
||||||
typedef map<string, ref_ptr<Program> > ProgramMap;
|
typedef map<string, ref_ptr<Program> > ProgramMap;
|
||||||
|
|||||||
@@ -56,5 +56,14 @@ BuilderException::BuilderException(const std::string& message,
|
|||||||
|
|
||||||
BuilderException::~BuilderException() throw()
|
BuilderException::~BuilderException() throw()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAttributeActive(Effect* effect, const SGPropertyNode* prop)
|
||||||
|
{
|
||||||
|
const SGPropertyNode* activeProp
|
||||||
|
= getEffectPropertyChild(effect, prop, "active");
|
||||||
|
return !activeProp || activeProp->getValue<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
namespace simgear
|
namespace simgear
|
||||||
{
|
{
|
||||||
class Effect;
|
class Effect;
|
||||||
|
class Pass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder that returns an object, probably an OSG object.
|
* Builder that returns an object, probably an OSG object.
|
||||||
@@ -212,5 +213,49 @@ public:
|
|||||||
BuilderException(const std::string& message, const std::string& = "");
|
BuilderException(const std::string& message, const std::string& = "");
|
||||||
virtual ~BuilderException() throw();
|
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
|
#endif
|
||||||
|
|||||||
@@ -20,12 +20,17 @@
|
|||||||
|
|
||||||
#include "TextureBuilder.hxx"
|
#include "TextureBuilder.hxx"
|
||||||
|
|
||||||
|
#include "Pass.hxx"
|
||||||
|
|
||||||
|
#include <osg/TexEnv>
|
||||||
|
#include <osg/TexEnvCombine>
|
||||||
#include <osg/Texture1D>
|
#include <osg/Texture1D>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
#include <osg/Texture3D>
|
#include <osg/Texture3D>
|
||||||
#include <osg/TextureRectangle>
|
#include <osg/TextureRectangle>
|
||||||
#include <osgDB/FileUtils>
|
#include <osgDB/FileUtils>
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include <boost/tuple/tuple_comparison.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,
|
Texture::WrapMode, Texture::WrapMode, Texture::WrapMode,
|
||||||
string> TexTuple;
|
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
|
namespace
|
||||||
{
|
{
|
||||||
EffectNameValue<Texture::FilterMode> filterModesInit[] =
|
EffectNameValue<Texture::FilterMode> filterModesInit[] =
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ public:
|
|||||||
const osgDB::ReaderWriter::Options* options);
|
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);
|
bool makeTextureParameters(SGPropertyNode* paramRoot, const osg::StateSet* ss);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user