README.plib \
README.OpenAL \
README.OSG \
- projects \
- SimGear.dsp \
- SimGear.dsw
+ projects
SUBDIRS = simgear
}
-const char *
+string
SGPropertyNode::getPath (bool simplify) const
{
- // Calculate the complete path only once.
- if (_parent != 0 && _path.empty()) {
- _path = _parent->getPath(simplify);
- _path += '/';
- _path += getDisplayName(simplify);
+ typedef std::vector<SGConstPropertyNode_ptr> PList;
+ PList pathList;
+ for (const SGPropertyNode* node = this; node->_parent; node = node->_parent)
+ pathList.push_back(node);
+ string result;
+ for (PList::reverse_iterator itr = pathList.rbegin(),
+ rend = pathList.rend();
+ itr != rend;
+ ++itr) {
+ result += '/';
+ result += (*itr)->getDisplayName(simplify);
}
-
- return _path.c_str();
+ return result;
}
props::Type
/**
* Get the path to this node from the root.
*/
- const char * getPath (bool simplify = false) const;
+ std::string getPath (bool simplify = false) const;
/**
simgear::PropertyList _children;
simgear::PropertyList _removedChildren;
std::vector<hash_table *> _linkedNodes;
- mutable std::string _path;
mutable std::string _buffer;
hash_table * _path_cache;
simgear::props::Type _type;
#include <osg/RenderInfo>
#include <osg/ShadeModel>
#include <osg/StateSet>
+#include <osg/Stencil>
#include <osg/TexEnv>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
}
void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
Pass* pass = new Pass;
tniq->passes.push_back(pass);
}
}
+// Default names for vector property components
+const char* vec3Names[] = {"x", "y", "z"};
+const char* vec4Names[] = {"x", "y", "z", "w"};
+
osg::Vec4f getColor(const SGPropertyNode* prop)
{
if (prop->nChildren() == 0) {
struct LightingBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
void LightingBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
struct ShadeModelBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
struct CullFaceBuilder : PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp) {
InstallAttributeBuilder<CullFaceBuilder> installCullFace("cull-face");
+struct ColorMaskBuilder : PassAttributeBuilder
+{
+ void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+ const SGReaderWriterXMLOptions* options)
+ {
+ const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
+ if (!realProp)
+ return;
+
+ ColorMask *mask = new ColorMask;
+ Vec4 m = getColor(realProp);
+ mask->setMask(m.r(), m.g(), m.b(), m.a());
+ pass->setAttributeAndModes(mask);
+ }
+};
+
+InstallAttributeBuilder<ColorMaskBuilder> installColorMask("color-mask");
+
EffectNameValue<StateSet::RenderingHint> renderingHintInit[] =
{
{ "default", StateSet::DEFAULT_BIN },
struct HintBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
struct RenderBinBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
struct MaterialBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
EffectNameValue<Material::ColorMode> colorModeInit[] =
void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
struct BlendBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
InstallAttributeBuilder<BlendBuilder> installBlend("blend");
+
+EffectNameValue<Stencil::Function> stencilFunctionInit[] =
+{
+ {"never", Stencil::NEVER },
+ {"less", Stencil::LESS},
+ {"equal", Stencil::EQUAL},
+ {"less-or-equal", Stencil::LEQUAL},
+ {"greater", Stencil::GREATER},
+ {"not-equal", Stencil::NOTEQUAL},
+ {"greater-or-equal", Stencil::GEQUAL},
+ {"always", Stencil::ALWAYS}
+};
+
+EffectPropertyMap<Stencil::Function> stencilFunction(stencilFunctionInit);
+
+EffectNameValue<Stencil::Operation> stencilOperationInit[] =
+{
+ {"keep", Stencil::KEEP},
+ {"zero", Stencil::ZERO},
+ {"replace", Stencil::REPLACE},
+ {"increase", Stencil::INCR},
+ {"decrease", Stencil::DECR},
+ {"invert", Stencil::INVERT},
+ {"increase-wrap", Stencil::INCR_WRAP},
+ {"decrease-wrap", Stencil::DECR_WRAP}
+};
+
+EffectPropertyMap<Stencil::Operation> stencilOperation(stencilOperationInit);
+
+struct StencilBuilder : public PassAttributeBuilder
+{
+ void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+ const SGReaderWriterXMLOptions* options)
+ {
+ if (!isAttributeActive(effect, prop))
+ return;
+
+ const SGPropertyNode* pmode = getEffectPropertyChild(effect, prop,
+ "mode");
+ if (pmode && !pmode->getValue<bool>()) {
+ pass->setMode(GL_STENCIL, StateAttribute::OFF);
+ return;
+ }
+ const SGPropertyNode* pfunction
+ = getEffectPropertyChild(effect, prop, "function");
+ const SGPropertyNode* pvalue
+ = getEffectPropertyChild(effect, prop, "value");
+ const SGPropertyNode* pmask
+ = getEffectPropertyChild(effect, prop, "mask");
+ const SGPropertyNode* psfail
+ = getEffectPropertyChild(effect, prop, "stencil-fail");
+ const SGPropertyNode* pzfail
+ = getEffectPropertyChild(effect, prop, "z-fail");
+ const SGPropertyNode* ppass
+ = getEffectPropertyChild(effect, prop, "pass");
+
+ Stencil::Function func = Stencil::ALWAYS; // Always pass
+ int ref = 0;
+ unsigned int mask = ~0u; // All bits on
+ Stencil::Operation sfailop = Stencil::KEEP; // Keep the old values as default
+ Stencil::Operation zfailop = Stencil::KEEP;
+ Stencil::Operation passop = Stencil::KEEP;
+
+ ref_ptr<Stencil> stencilFunc = new Stencil;
+
+ if (pfunction)
+ findAttr(stencilFunction, pfunction, func);
+ if (pvalue)
+ ref = pvalue->getIntValue();
+ if (pmask)
+ mask = pmask->getIntValue();
+
+ if (psfail)
+ findAttr(stencilOperation, psfail, sfailop);
+ if (pzfail)
+ findAttr(stencilOperation, pzfail, zfailop);
+ if (ppass)
+ findAttr(stencilOperation, ppass, passop);
+
+ // Set the stencil operation
+ stencilFunc->setFunction(func, ref, mask);
+
+ // Set the operation, s-fail, s-pass/z-fail, s-pass/z-pass
+ stencilFunc->setOperation(sfailop, zfailop, passop);
+
+ // Add the operation to pass
+ pass->setAttributeAndModes(stencilFunc.get());
+ }
+};
+
+InstallAttributeBuilder<StencilBuilder> installStencil("stencil");
+
+
EffectNameValue<AlphaFunc::ComparisonFunction> alphaComparisonInit[] =
{
{"never", AlphaFunc::NEVER},
struct AlphaTestBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
struct ShaderProgramBuilder : PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options*
+ const SGReaderWriterXMLOptions*
options)
{
using namespace boost;
{"float-vec3", Uniform::FLOAT_VEC3},
{"float-vec4", Uniform::FLOAT_VEC4},
{"sampler-1d", Uniform::SAMPLER_1D},
+ {"sampler-1d-shadow", Uniform::SAMPLER_1D_SHADOW},
{"sampler-2d", Uniform::SAMPLER_2D},
- {"sampler-3d", Uniform::SAMPLER_3D}
+ {"sampler-2d-shadow", Uniform::SAMPLER_2D_SHADOW},
+ {"sampler-3d", Uniform::SAMPLER_3D},
+ {"sampler-cube", Uniform::SAMPLER_CUBE}
};
EffectPropertyMap<Uniform::Type> uniformTypes(uniformTypesInit);
struct UniformBuilder :public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
const SGPropertyNode* nameProp = prop->getChild("name");
const SGPropertyNode* typeProp = prop->getChild("type");
- const SGPropertyNode* valProp
- = getEffectPropertyChild(effect, prop, "value");
+ const SGPropertyNode* valProp = prop->getChild("value");
string name;
Uniform::Type uniformType = Uniform::FLOAT;
if (nameProp) {
uniform->setType(uniformType);
switch (uniformType) {
case Uniform::FLOAT:
- uniform->set(valProp->getValue<float>());
+ initFromParameters(effect, valProp, uniform.get(),
+ static_cast<bool (Uniform::*)(float)>(&Uniform::set),
+ options);
break;
case Uniform::FLOAT_VEC3:
- uniform->set(toOsg(valProp->getValue<SGVec3d>()));
+ initFromParameters(effect, valProp, uniform.get(),
+ static_cast<bool (Uniform::*)(const Vec3&)>(&Uniform::set),
+ vec3Names, options);
break;
case Uniform::FLOAT_VEC4:
- uniform->set(toOsg(valProp->getValue<SGVec4d>()));
+ initFromParameters(effect, valProp, uniform.get(),
+ static_cast<bool (Uniform::*)(const Vec4&)>(&Uniform::set),
+ vec4Names, options);
break;
case Uniform::SAMPLER_1D:
case Uniform::SAMPLER_2D:
case Uniform::SAMPLER_3D:
- uniform->set(valProp->getValue<int>());
+ case Uniform::SAMPLER_1D_SHADOW:
+ case Uniform::SAMPLER_2D_SHADOW:
+ case Uniform::SAMPLER_CUBE:
+ initFromParameters(effect, valProp, uniform.get(),
+ static_cast<bool (Uniform::*)(int)>(&Uniform::set),
+ options);
break;
default: // avoid compiler warning
break;
struct NameBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
// name can't use <use>
string name = prop->getStringValue();
struct PolygonModeBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
struct VertexProgramTwoSideBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
struct VertexProgramPointSizeBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
struct DepthBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
InstallAttributeBuilder<DepthBuilder> installDepth("depth");
void buildTechnique(Effect* effect, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
Technique* tniq = new Technique;
effect->techniques.push_back(tniq);
// Walk the techniques property tree, building techniques and
// passes.
-bool Effect::realizeTechniques(const osgDB::ReaderWriter::Options* options)
+bool Effect::realizeTechniques(const SGReaderWriterXMLOptions* options)
{
if (_isRealized)
return true;
{
class Technique;
class Effect;
+class SGReaderWriterXMLOptions;
/**
* Object to be initialized at some point after an effect -- and its
/**
* Build the techniques from the effect properties.
*/
- bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
+ bool realizeTechniques(const SGReaderWriterXMLOptions* options = 0);
/**
* Updaters that should be derefed when the effect is
* deleted. Updaters arrange to be run by listening on properties
Cache* _cache;
friend size_t hash_value(const Key& key);
friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
bool _isRealized;
};
// Automatic support for boost hash function
Effect* makeEffect(const std::string& name,
bool realizeTechniques,
- const osgDB::ReaderWriter::Options* options = 0);
+ const SGReaderWriterXMLOptions* options = 0);
Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques,
- const osgDB::ReaderWriter::Options* options = 0);
+ const SGReaderWriterXMLOptions* options = 0);
bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
const osg::StateSet* ss);
# include <simgear_config.h>
#endif
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/math/SGMath.hxx>
return getEffectPropertyNode(effect, child);
}
-string getGlobalProperty(const SGPropertyNode* prop)
+string getGlobalProperty(const SGPropertyNode* prop,
+ const SGReaderWriterXMLOptions* options)
{
if (!prop)
return string();
const SGPropertyNode* useProp = prop->getChild("use");
if (!useProp)
return string();
+ string propName = useProp->getStringValue();
+ SGPropertyNode_ptr propRoot;
+ if (propName[0] == '/') {
+ return propName;
+ } else if ((propRoot = options->getPropRoot())) {
+ string result = propRoot->getPath();
+ result.append("/");
+ result.append(propName);
+ return result;
+ } else {
+ throw effect::
+ BuilderException("No property root to use with relative name "
+ + propName);
+ }
+
return useProp->getStringValue();
}
#include <simgear/math/SGMath.hxx>
#include <simgear/props/AtomicChangeListener.hxx>
#include <simgear/props/props.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/structure/Singleton.hxx>
{
class Effect;
class Pass;
+class SGReaderWriterXMLOptions;
/**
* Builder that returns an object, probably an OSG object.
public:
virtual ~EffectBuilder() {}
virtual T* build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options) = 0;
+ const SGReaderWriterXMLOptions* options) = 0;
static T* buildFromType(Effect* effect, const std::string& type,
const SGPropertyNode*props,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
BuilderMap& builderMap = getMap();
typename BuilderMap::iterator iter = builderMap.find(type);
_map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second));
}
+// A one-way map that can be initialized using an array
+template<typename T>
+struct SimplePropertyMap
+{
+ typedef std::map<string, T> map_type;
+ map_type _map;
+ template<int N>
+ SimplePropertyMap(const EffectNameValue<T> (&attrs)[N])
+ {
+ for (int i = 0; i < N; ++i)
+ _map.insert(typename map_type::value_type(attrs[i].first,
+ attrs[i].second));
+ }
+};
+
class BuilderException : public sg_exception
{
public:
findAttr(pMap, name, result);
}
+// Versions that don't throw an error
+
+template<typename T>
+const T* findAttr(const effect::EffectPropertyMap<T>& pMap,
+ const char* name)
+{
+ using namespace effect;
+ typename EffectPropertyMap<T>::BMap::iterator itr
+ = pMap._map.get<from>().find(name);
+ if (itr == pMap._map.end())
+ return 0;
+ else
+ return &itr->second;
+}
+
+template<typename T>
+const T* findAttr(const effect::SimplePropertyMap<T>& pMap,
+ const char* name)
+{
+ using namespace effect;
+ typename SimplePropertyMap<T>::map_type::const_iterator itr
+ = pMap._map.find(name);
+ if (itr == pMap._map.end())
+ return 0;
+ else
+ return &itr->second;
+}
+
+template<typename T, template<class> class Map>
+const T* findAttr(const Map<T>& pMap,
+ const std::string& name)
+{
+ return findAttr(pMap, name.c_str());
+}
+
+
template<typename T>
std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
{
* @return empty if prop doesn't contain a <use> clause; otherwise the
* mentioned node name.
*/
-std::string getGlobalProperty(const SGPropertyNode* prop);
+std::string getGlobalProperty(const SGPropertyNode* prop,
+ const SGReaderWriterXMLOptions *);
+
+template<typename NameItr>
+std::vector<std::string>
+getVectorProperties(const SGPropertyNode* prop,
+ const SGReaderWriterXMLOptions *options, size_t vecSize,
+ NameItr defaultNames)
+{
+ using namespace std;
+ vector<string> result;
+ if (!prop)
+ return result;
+ PropertyList useProps = prop->getChildren("use");
+ if (useProps.size() == 1) {
+ string parentName = useProps[0]->getStringValue();
+ if (parentName.size() == 0 || parentName[0] != '/')
+ parentName = options->getPropRoot()->getPath() + "/" + parentName;
+ if (parentName[parentName.size() - 1] != '/')
+ parentName.append("/");
+ NameItr itr = defaultNames;
+ for (int i = 0; i < vecSize; ++i, ++itr)
+ result.push_back(parentName + *itr);
+ } else if (useProps.size() == vecSize) {
+ string parentName = useProps[0]->getStringValue();
+ parentName += "/";
+ for (PropertyList::const_iterator itr = useProps.begin(),
+ end = useProps.end();
+ itr != end;
+ ++itr) {
+ string childName = (*itr)->getStringValue();
+ if (childName.size() == 0 || childName[0] != '/')
+ result.push_back(parentName + childName);
+ else
+ result.push_back(childName);
+ }
+ }
+ return result;
+}
class PassAttributeBuilder : public SGReferenced
{
public:
virtual void buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
= 0;
static PassAttributeBuilder* find(const std::string& str)
{
namespace effect
{
/**
- * Bridge between types stored in properties and what OSG wants.
+ * Bridge between types stored in properties and what OSG or the
+ * effects code want.
*/
-template<typename T> struct OSGBridge;
+template<typename T> struct Bridge;
+
+/**
+ * Default just passes on the same type.
+ *
+ */
+template<typename T>
+struct Bridge
+{
+ typedef T sg_type;
+ static T get(const T& val) { return val; }
+};
template<typename T>
-struct OSGBridge<const T> : public OSGBridge<T>
+struct Bridge<const T> : public Bridge<T>
{
};
+// Save some typing...
+template<typename InType, typename OutType>
+struct BridgeOSGVec
+{
+ typedef InType sg_type;
+ static OutType get(const InType& val) { return toOsg(val); }
+};
template<>
-struct OSGBridge<osg::Vec3f>
+struct Bridge<osg::Vec3f> : public BridgeOSGVec<SGVec3d, osg::Vec3f>
{
- typedef SGVec3d sg_type;
- static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
};
template<>
-struct OSGBridge<osg::Vec3d>
+struct Bridge<osg::Vec3d> : public BridgeOSGVec<SGVec3d, osg::Vec3d>
{
- typedef SGVec3d sg_type;
- static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
};
template<>
-struct OSGBridge<osg::Vec4f>
+struct Bridge<osg::Vec4f> : public BridgeOSGVec<SGVec4d, osg::Vec4f>
{
- typedef SGVec4d sg_type;
- static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
};
template<>
-struct OSGBridge<osg::Vec4d>
+struct Bridge<osg::Vec4d> : public BridgeOSGVec<SGVec4d, osg::Vec4d>
{
- typedef SGVec4d sg_type;
- static osg::Vec4d getOsgType(const SGVec4d& val) { return toOsg(val); }
};
-template<typename Obj, typename OSGParam>
-struct OSGFunctor : public OSGBridge<OSGParam>
+/**
+ * Functor for calling a function on an osg::Referenced object and a
+ * value (e.g., an SGVec4d from a property) which will be converted to
+ * the equivalent OSG type.
+ *
+ * General version, function takes obj, val
+ */
+template<typename OSGParam, typename Obj, typename Func>
+struct OSGFunctor : public Bridge<OSGParam>
+{
+ OSGFunctor(Obj* obj, const Func& func)
+ : _obj(obj), _func(func) {}
+ void operator()(const typename Bridge<OSGParam>::sg_type& val) const
+ {
+ _func(_obj, this->get(val));
+ }
+ osg::ref_ptr<Obj>_obj;
+ const Func _func;
+};
+
+/**
+ * Version which uses a pointer to member function instead.
+ */
+template<typename OSGParam, typename Obj>
+struct OSGFunctor<OSGParam, Obj, void (Obj::* const)(const OSGParam&)>
+ : public Bridge<OSGParam>
{
- OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
+ typedef void (Obj::*const MemFunc)(const OSGParam&);
+ OSGFunctor(Obj* obj, MemFunc func)
: _obj(obj), _func(func) {}
- void operator()(const typename OSGBridge<OSGParam>::sg_type& val) const
+ void operator()(const typename Bridge<OSGParam>::sg_type& val) const
{
- ((_obj.get())->*_func)(this->getOsgType(val));
+ (_obj->*_func)(this->get(val));
}
osg::ref_ptr<Obj>_obj;
- void (Obj::*_func)(const OSGParam&);
+ MemFunc _func;
};
-template<typename ObjType, typename OSGParamType>
+/**
+ * Typical convenience constructors
+ */
+template<typename OSGParam, typename Obj, typename Func>
+OSGFunctor<OSGParam, Obj, Func> make_OSGFunctor(Obj* obj, const Func& func)
+{
+ return OSGFunctor<OSGParam, Obj, Func>(obj, func);
+}
+
+template<typename OSGParam, typename Obj>
+OSGFunctor<OSGParam, Obj, void (Obj::*const)(const OSGParam&)>
+make_OSGFunctor(Obj* obj, void (Obj::*const func)(const OSGParam&))
+{
+ return OSGFunctor<OSGParam, Obj,
+ void (Obj::* const)(const OSGParam&)>(obj, func);
+}
+
+template<typename OSGParamType, typename ObjType, typename F>
class ScalarChangeListener
: public SGPropertyChangeListener, public InitializeWhenAdded,
public Effect::Updater
{
public:
- typedef void (ObjType::*setter_type)(const OSGParamType);
- ScalarChangeListener(ObjType* obj, setter_type setter,
+ ScalarChangeListener(ObjType* obj, const F& setter,
const std::string& propName)
: _obj(obj), _setter(setter)
{
}
void valueChanged(SGPropertyNode* node)
{
- _obj->*setter(node->getValue<OSGParamType>());
+ _setter(_obj.get(), node->getValue<OSGParamType>());
}
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
{
}
private:
osg::ref_ptr<ObjType> _obj;
- setter_type _setter;
+ F _setter;
std::string* _propName;
};
public:
template<typename Itr>
EffectExtendedPropListener(const Func& func,
- const std::string& propName, Itr childNamesBegin,
+ const std::string* propName, Itr childNamesBegin,
Itr childNamesEnd)
- : _func(func)
+ : _propName(0), _func(func)
{
- _propName = new std::string(propName);
+ if (propName)
+ _propName = new std::string(*propName);
_childNames = new std::vector<std::string>(childNamesBegin,
childNamesEnd);
}
}
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
{
- SGPropertyNode* parent = propRoot->getNode(*_propName, true);
+ SGPropertyNode* parent = 0;
+ if (_propName)
+ parent = propRoot->getNode(*_propName, true);
+ else
+ parent = propRoot;
_propListener
= new ExtendedPropListener<T, Func>(parent, _childNames->begin(),
_childNames->end(),
Func _func;
};
+template<typename T, typename Func, typename Itr>
+Effect::Updater*
+new_EEPropListener(const Func& func, const std::string* propName,
+ const Itr& namesBegin, const Itr& namesEnd)
+{
+ return new EffectExtendedPropListener<T, Func>
+ (func, 0, namesBegin, namesEnd);
+}
+
/**
* Initialize the value and the possible updating of an effect
* attribute. If the value is specified directly, set it. Otherwise,
* own <use> tag referring to a property in the global property tree;
* install a change listener that will set the attribute when the
* property changes.
+ *
+ * For relative property names, the property root found in options is
+ * used.
*/
-template<typename ObjType, typename OSGParamType>
+template<typename OSGParamType, typename ObjType, typename F>
void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
- void (ObjType::*setter)(const OSGParamType))
+ const F& setter, const SGReaderWriterXMLOptions* options)
{
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
if (!valProp)
return;
if (valProp->nChildren() == 0) {
- obj->*setter(valProp->getValue<OSGParamType>());
+ setter(obj, valProp->getValue<OSGParamType>());
} else {
- std::string propName = getGlobalProperty(prop);
- ScalarChangeListener<ObjType, OSGParamType>* listener
- = new ScalarChangeListener<ObjType, OSGParamType>(obj, setter,
- propName);
+ std::string propName = getGlobalProperty(valProp, options);
+ ScalarChangeListener<OSGParamType, ObjType, F>* listener
+ = new ScalarChangeListener<OSGParamType, ObjType, F>(obj, setter,
+ propName);
effect->addUpdater(listener);
}
}
-template<typename ObjType, typename OSGParamType, typename NameItrType>
+template<typename OSGParamType, typename ObjType, typename SetterReturn>
+inline void
+initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
+ SetterReturn (ObjType::*setter)(const OSGParamType),
+ const SGReaderWriterXMLOptions* options)
+{
+ initFromParameters<OSGParamType>(effect, prop, obj,
+ boost::bind(setter, _1, _2), options);
+}
+
+/*
+ * Initialize vector parameters from individual properties.
+ * The parameter may be updated at runtime.
+ *
+ * If the value is specified directly, set it. Otherwise, use the
+ * <use> tag to look at the parameters. Again, if there is a value
+ * there set it directly. Otherwise, the parameter contains one or several
+ * <use> tags. If there is one tag, it is a property that is the root
+ * for the values needed to update the parameter; nameIter holds the
+ * names of the properties relative to the root. If there are several
+ * <use> tags, they each hold the name of the property holding the
+ * value for the corresponding vector member.
+ *
+ * Install a change listener that will set the attribute when the
+ * property changes.
+ *
+ * For relative property names, the property root found in options is
+ * used.
+ */
+template<typename OSGParamType, typename ObjType, typename NameItrType,
+ typename F>
void
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
- void (ObjType::*setter)(const OSGParamType&),
- NameItrType nameItr)
+ const F& setter,
+ NameItrType nameItr, const SGReaderWriterXMLOptions* options)
{
- typedef typename OSGBridge<OSGParamType>::sg_type sg_type;
+ typedef typename Bridge<OSGParamType>::sg_type sg_type;
+ const int numComponents = props::NumComponents<sg_type>::num_components;
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
if (!valProp)
return;
- if (valProp->nChildren() == 0) {
- (obj->*setter)(OSGBridge<OSGParamType>
- ::getOsgType(valProp->getValue<sg_type>()));
+ if (valProp->nChildren() == 0) { // Has <use>?
+ setter(obj, Bridge<OSGParamType>::get(valProp->getValue<sg_type>()));
} else {
- string listenPropName = getGlobalProperty(valProp);
- if (listenPropName.empty())
- return;
- typedef OSGFunctor<ObjType, OSGParamType> Functor;
+ std::vector<std::string> paramNames
+ = getVectorProperties(valProp, options,numComponents, nameItr);
+ if (paramNames.empty())
+ throw BuilderException();
+ std::vector<std::string>::const_iterator pitr = paramNames.begin();
Effect::Updater* listener
- = new EffectExtendedPropListener<sg_type, Functor>
- (Functor(obj, setter), listenPropName, nameItr,
- nameItr + props::NumComponents<sg_type>::num_components);
+ = new_EEPropListener<sg_type>(make_OSGFunctor<OSGParamType>
+ (obj, setter),
+ 0, pitr, pitr + numComponents);
effect->addUpdater(listener);
}
}
+template<typename OSGParamType, typename ObjType, typename NameItrType,
+ typename SetterReturn>
+inline void
+initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
+ SetterReturn (ObjType::*setter)(const OSGParamType&),
+ NameItrType nameItr, const SGReaderWriterXMLOptions* options)
+{
+ initFromParameters<OSGParamType>(effect, prop, obj,
+ boost::bind(setter, _1, _2), nameItr,
+ options);
+}
extern const char* colorFields[];
}
}
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/math/SGMath.hxx>
using namespace effect;
TexEnvCombine* buildTexEnvCombine(Effect* effect,
- const SGPropertyNode* envProp);
+ const SGPropertyNode* envProp,
+ const SGReaderWriterXMLOptions* options);
TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
// Hack to force inclusion of TextureBuilder.cxx in library
osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
const SGPropertyNode*props,
- const osgDB::ReaderWriter::Options*
+ const SGReaderWriterXMLOptions*
options)
{
return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
}
const SGPropertyNode* combineProp = prop->getChild("texenv-combine");
TexEnvCombine* combiner = 0;
- if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp))))
+ if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp,
+ options))))
pass->setTextureAttributeAndModes(unit, combiner);
const SGPropertyNode* tgenProp = prop->getChild("texgen");
TexGen* tgen = 0;
TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
- const osgDB::ReaderWriter::Options* options,
+ const SGReaderWriterXMLOptions* options,
const string& texType)
{
Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
}
void setAttrs(const TexTuple& attrs, Texture* tex,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
const string& imageName = attrs.get<0>();
if (imageName.empty()) {
public:
TexBuilder(const string& texType) : _type(texType) {}
Texture* build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
protected:
typedef map<TexTuple, ref_ptr<T> > TexMap;
TexMap texMap;
template<typename T>
Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
TexTuple attrs = makeTexTuple(effect, props, options, _type);
typename TexMap::iterator itr = texMap.find(attrs);
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
return StateAttributeFactory::instance()->getWhiteTexture();
}
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
return StateAttributeFactory::instance()->getTransparentTexture();
}
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
protected:
typedef map<int, ref_ptr<Texture3D> > NoiseMap;
NoiseMap _noises;
};
Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
int texSize = 64;
const SGPropertyNode* sizeProp = getEffectPropertyChild(effect, props,
EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
-TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
+TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp,
+ const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, envProp))
return 0;
const SGPropertyNode* colorNode = envProp->getChild("constant-color");
if (colorNode)
initFromParameters(effect, colorNode, result,
- &TexEnvCombine::setConstantColor, colorFields);
+ &TexEnvCombine::setConstantColor, colorFields,
+ options);
return result;
}
// Hack to force inclusion of TextureBuilder.cxx in library
static osg::Texture* buildFromType(Effect* effect, const std::string& type,
const SGPropertyNode*props,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
struct TextureUnitBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
};
#include <osgDB/Registry>
#include <simgear/debug/logstream.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include <simgear/scene/util/SplicingVisitor.hxx>
Effect* makeEffect(const string& name,
bool realizeTechniques,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
{
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
Effect* makeEffect(SGPropertyNode* prop,
bool realizeTechniques,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
// Give default names to techniques and passes
vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique");
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sgstream.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/scene/model/model.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
////////////////////////////////////////////////////////////////////////
SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l,
- const osgDB::ReaderWriter::Options* o ) :
- effect(e), texture_path(t), effect_realized(l), options(o)
+ const SGReaderWriterXMLOptions* o)
+ : effect(e), texture_path(t), effect_realized(l), options(o)
{
}
-SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
+SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options,
const SGPropertyNode *props )
{
init();
buildEffectProperties(options);
}
+SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
+ const SGPropertyNode *props )
+{
+ osg::ref_ptr<const SGReaderWriterXMLOptions> sgOptions;
+ if (options)
+ sgOptions = new SGReaderWriterXMLOptions(*options);
+ init();
+ read_properties( sgOptions.get(), props );
+ buildEffectProperties(sgOptions.get());
+}
+
SGMaterial::~SGMaterial (void)
{
}
////////////////////////////////////////////////////////////////////////
void
-SGMaterial::read_properties(const osgDB::ReaderWriter::Options* options,
+SGMaterial::read_properties(const SGReaderWriterXMLOptions* options,
const SGPropertyNode *props)
{
// Gather the path(s) to the texture(s)
return _status[i].effect.get();
}
-void SGMaterial::buildEffectProperties(const osgDB::ReaderWriter::Options*
- options)
+void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options)
{
using namespace osg;
+ ref_ptr<SGReaderWriterXMLOptions> xmlOptions;
+ if (options)
+ xmlOptions = new SGReaderWriterXMLOptions(*options);
ref_ptr<SGMaterialUserData> user = new SGMaterialUserData(this);
SGPropertyNode_ptr propRoot = new SGPropertyNode();
makeChild(propRoot, "inherits-from")->setStringValue(effect);
->setStringValue(wrapu ? "repeat" : "clamp");
makeChild(texProp, "wrap-t")
->setStringValue(wrapv ? "repeat" : "clamp");
- matState.effect = makeEffect(effectProp, false, options);
+ matState.effect = makeEffect(effectProp, false, xmlOptions.get());
matState.effect->setUserData(user.get());
}
}
#include <simgear/math/SGMath.hxx>
#include <osg/ref_ptr>
-#include <osgDB/ReaderWriter>
namespace osg
{
class StateSet;
}
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/props/props.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
*/
SGMaterial( const osgDB::ReaderWriter::Options*, const SGPropertyNode *props);
+ SGMaterial(const simgear::SGReaderWriterXMLOptions*,
+ const SGPropertyNode *props);
/**
* Destructor.
*/
struct _internal_state {
_internal_state(simgear::Effect *e, const std::string &t, bool l,
- const osgDB::ReaderWriter::Options *o);
+ const simgear::SGReaderWriterXMLOptions *o);
osg::ref_ptr<simgear::Effect> effect;
std::string texture_path;
bool effect_realized;
- osg::ref_ptr<const osgDB::ReaderWriter::Options> options;
+ osg::ref_ptr<const simgear::SGReaderWriterXMLOptions> options;
};
private:
// Internal constructors and methods.
////////////////////////////////////////////////////////////////////
- void read_properties(const osgDB::ReaderWriter::Options* options,
+ void read_properties(const simgear::SGReaderWriterXMLOptions* options,
const SGPropertyNode *props);
- void buildEffectProperties(const osgDB::ReaderWriter::Options* options);
+ void buildEffectProperties(const simgear::SGReaderWriterXMLOptions* options);
};
osg::ref_ptr<osg::RefMatrix> mModelView;
};
-osgUtil::RegisterRenderBinProxy
-SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
+struct SGClipGroup::ClipBinRegistrar
+{
+ ClipBinRegistrar()
+ {
+ osgUtil::RenderBin
+ ::addRenderBinPrototype("ClipRenderBin",
+ new SGClipGroup::ClipRenderBin);
+ }
+ static ClipBinRegistrar registrar;
+};
+
+SGClipGroup::ClipBinRegistrar SGClipGroup::ClipBinRegistrar::registrar;
class SGClipGroup::CullCallback : public osg::NodeCallback {
public:
protected:
class CullCallback;
class ClipRenderBin;
-
+ struct ClipBinRegistrar;
std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
-
- static osgUtil::RegisterRenderBinProxy clipBinProxy;
};
#endif
#ifndef SGREADERWRITERXMLOPTIONS_HXX
#define SGREADERWRITERXMLOPTIONS_HXX 1
-#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
+#include "SGReaderWriterXMLOptions.hxx"
#include "model.hxx"
using std::vector;
public:
typedef std::map<string, SGPropertyNode_ptr> EffectMap;
using SplicingVisitor::apply;
- MakeEffectVisitor(const osgDB::ReaderWriter::Options* options = 0)
+ MakeEffectVisitor(const SGReaderWriterXMLOptions* options = 0)
: _options(options)
{
}
protected:
EffectMap _effectMap;
SGPropertyNode_ptr _currentEffectParent;
- osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
+ osg::ref_ptr<const SGReaderWriterXMLOptions> _options;
};
void MakeEffectVisitor::apply(osg::Group& node)
ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
PropertyList& effectProps,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
SGPropertyNode_ptr defaultEffectPropRoot;
MakeEffectVisitor visitor(options);
#include <simgear/props/props.hxx>
#include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
+namespace simgear
+{
+class SGReaderWriterXMLOptions;
+}
+
osg::Texture2D*
SGLoadTexture2D(bool staticTexture, const std::string& path,
const osgDB::ReaderWriter::Options* options = 0,
osg::ref_ptr<osg::Node>
instantiateEffects(osg::Node* model,
PropertyList& effectProps,
- const osgDB::ReaderWriter::Options* options);
+ const SGReaderWriterXMLOptions* options);
/**
* Transform an OSG subgraph by substituting the Effects and
inline osg::ref_ptr<osg::Node>
instantiateEffects(osg::Node* model,
- const osgDB::ReaderWriter::Options* options)
+ const SGReaderWriterXMLOptions* options)
{
PropertyList effectProps;
return instantiateEffects(model, effectProps, options);
ref_ptr<Node> model = readRefNodeFile(path, options);
if (!model)
return 0;
- if (boost::iends_with(path, ".ac"))
- model = instantiateEffects(model.get(), options);
+ if (boost::iends_with(path, ".ac")) {
+ ref_ptr<SGReaderWriterXMLOptions> sgOptions;
+ if (options)
+ sgOptions = new SGReaderWriterXMLOptions(*options);
+ model = instantiateEffects(model.get(), sgOptions.get());
+ }
return model.release();
}
}
field_transform->setMatrix( LAT*LON*T );
}
- field_root->getStateSet()->setRenderBinDetails(asl, "DepthSortedBin");
+ // Render the clouds in order from farthest away layer to nearest one.
+ field_root->getStateSet()->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
return true;
}
#include <simgear/misc/PathOptions.hxx>
#include <simgear/props/props.hxx>
#include <simgear/scene/model/model.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/scene/util/SGUpdateVisitor.hxx>
"texture"),
"image"),
texture);
- osg::ref_ptr<osgDB::ReaderWriter::Options> options
+ ref_ptr<osgDB::ReaderWriter::Options> options
= makeOptionsFromPath(tex_path);
- if ((effect = makeEffect(pcloudEffect, true, options)))
+ ref_ptr<SGReaderWriterXMLOptions> sgOptions
+ = new SGReaderWriterXMLOptions(*options.get());
+ if ((effect = makeEffect(pcloudEffect, true, sgOptions.get())))
effectMap.insert(EffectMap::value_type(texture, effect));
} else {
effect = iter->second.get();