Merge branch 'timoore/effects-anim-rebase' into next

This commit is contained in:
Tim Moore
2010-03-09 11:03:25 +01:00
16 changed files with 422 additions and 144 deletions

View File

@@ -1027,17 +1027,22 @@ SGPropertyNode::getDisplayName (bool simplify) const
}
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

View File

@@ -994,7 +994,7 @@ public:
/**
* Get the path to this node from the root.
*/
const char * getPath (bool simplify = false) const;
std::string getPath (bool simplify = false) const;
/**
@@ -1675,7 +1675,6 @@ private:
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;

View File

@@ -66,6 +66,7 @@
#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>
@@ -143,7 +144,7 @@ Effect::~Effect()
}
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);
@@ -159,6 +160,10 @@ void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
}
}
// 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) {
@@ -188,12 +193,12 @@ osg::Vec4f getColor(const SGPropertyNode* prop)
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)
@@ -207,7 +212,7 @@ InstallAttributeBuilder<LightingBuilder> installLighting("lighting");
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)
@@ -229,7 +234,7 @@ InstallAttributeBuilder<ShadeModelBuilder> installShadeModel("shade-model");
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) {
@@ -257,7 +262,7 @@ InstallAttributeBuilder<CullFaceBuilder> installCullFace("cull-face");
struct ColorMaskBuilder : 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)
@@ -284,7 +289,7 @@ EffectPropertyMap<StateSet::RenderingHint> renderingHints(renderingHintInit);
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)
@@ -300,7 +305,7 @@ InstallAttributeBuilder<HintBuilder> installHint("rendering-hint");
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;
@@ -327,7 +332,7 @@ InstallAttributeBuilder<RenderBinBuilder> installRenderBin("render-bin");
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[] =
@@ -343,7 +348,7 @@ EffectPropertyMap<Material::ColorMode> colorModes(colorModeInit);
void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
@@ -413,7 +418,7 @@ EffectPropertyMap<BlendFunc::BlendFuncMode> blendFuncModes(blendFuncModesInit);
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;
@@ -526,7 +531,7 @@ EffectPropertyMap<Stencil::Operation> stencilOperation(stencilOperationInit);
struct StencilBuilder : public PassAttributeBuilder
{
void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
@@ -604,7 +609,7 @@ alphaComparison(alphaComparisonInit);
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;
@@ -715,12 +720,12 @@ void reload_shaders()
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;
@@ -807,15 +812,18 @@ EffectNameValue<Uniform::Type> uniformTypesInit[] =
{"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;
@@ -861,18 +869,29 @@ struct UniformBuilder :public PassAttributeBuilder
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;
@@ -889,7 +908,7 @@ InstallAttributeBuilder<UniformBuilder> installUniform("uniform");
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();
@@ -911,7 +930,7 @@ EffectPropertyMap<PolygonMode::Mode> polygonModeModes(polygonModeModesInit);
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;
@@ -939,7 +958,7 @@ InstallAttributeBuilder<PolygonModeBuilder> installPolygonMode("polygon-mode");
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)
@@ -956,7 +975,7 @@ installTwoSide("vertex-program-two-side");
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)
@@ -986,7 +1005,7 @@ EffectPropertyMap<Depth::Function> depthFunction(depthFunctionInit);
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;
@@ -1017,7 +1036,7 @@ struct DepthBuilder : public PassAttributeBuilder
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);
@@ -1123,7 +1142,7 @@ bool makeParametersFromStateSet(SGPropertyNode* effectRoot, const StateSet* ss)
// 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;

View File

@@ -45,6 +45,7 @@ namespace simgear
{
class Technique;
class Effect;
class SGReaderWriterXMLOptions;
/**
* Object to be initialized at some point after an effect -- and its
@@ -89,7 +90,7 @@ public:
/**
* 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
@@ -144,7 +145,7 @@ protected:
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
@@ -153,11 +154,11 @@ size_t hash_value(const Effect::Key&);
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);

View File

@@ -2,6 +2,7 @@
# include <simgear_config.h>
#endif
#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
#include <simgear/scene/tgdb/userdata.hxx>
#include <simgear/math/SGMath.hxx>
@@ -41,13 +42,29 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
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();
}

View File

@@ -33,6 +33,7 @@
#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>
@@ -46,6 +47,7 @@ namespace simgear
{
class Effect;
class Pass;
class SGReaderWriterXMLOptions;
/**
* Builder that returns an object, probably an OSG object.
@@ -56,10 +58,10 @@ class EffectBuilder : public SGReferenced
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);
@@ -154,6 +156,21 @@ EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
_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:
@@ -201,6 +218,42 @@ void findAttr(const effect::EffectPropertyMap<T>& pMap,
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)
{
@@ -240,7 +293,45 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
* @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
{
@@ -255,7 +346,7 @@ protected:
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)
{
@@ -289,64 +380,116 @@ bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
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 Bridge<osg::Vec3f> : public BridgeOSGVec<SGVec3d, osg::Vec3f>
{
};
template<>
struct OSGBridge<osg::Vec3f>
struct Bridge<osg::Vec3d> : public BridgeOSGVec<SGVec3d, osg::Vec3d>
{
typedef SGVec3d sg_type;
static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
};
template<>
struct OSGBridge<osg::Vec3d>
struct Bridge<osg::Vec4f> : public BridgeOSGVec<SGVec4d, osg::Vec4f>
{
typedef SGVec3d sg_type;
static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
};
template<>
struct OSGBridge<osg::Vec4f>
struct Bridge<osg::Vec4d> : public BridgeOSGVec<SGVec4d, osg::Vec4d>
{
typedef SGVec4d sg_type;
static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
};
template<>
struct OSGBridge<osg::Vec4d>
/**
* 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>
{
typedef SGVec4d sg_type;
static osg::Vec4d getOsgType(const SGVec4d& val) { return toOsg(val); }
};
template<typename Obj, typename OSGParam>
struct OSGFunctor : public OSGBridge<OSGParam>
{
OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
OSGFunctor(Obj* obj, const Func& 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));
_func(_obj, this->get(val));
}
osg::ref_ptr<Obj>_obj;
void (Obj::*_func)(const OSGParam&);
const Func _func;
};
template<typename ObjType, typename OSGParamType>
/**
* 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>
{
typedef void (Obj::*const MemFunc)(const OSGParam&);
OSGFunctor(Obj* obj, MemFunc func)
: _obj(obj), _func(func) {}
void operator()(const typename Bridge<OSGParam>::sg_type& val) const
{
(_obj->*_func)(this->get(val));
}
osg::ref_ptr<Obj>_obj;
MemFunc _func;
};
/**
* 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)
{
@@ -359,7 +502,7 @@ public:
}
void valueChanged(SGPropertyNode* node)
{
_obj->*setter(node->getValue<OSGParamType>());
_setter(_obj.get(), node->getValue<OSGParamType>());
}
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
{
@@ -371,7 +514,7 @@ public:
}
private:
osg::ref_ptr<ObjType> _obj;
setter_type _setter;
F _setter;
std::string* _propName;
};
@@ -382,11 +525,12 @@ class EffectExtendedPropListener : public InitializeWhenAdded,
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);
}
@@ -397,7 +541,11 @@ public:
}
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(),
@@ -414,6 +562,15 @@ private:
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,
@@ -422,52 +579,97 @@ private:
* 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(prop, 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[];
}
}

View File

@@ -35,6 +35,7 @@
#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>
@@ -50,13 +51,14 @@ using namespace osg;
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);
@@ -98,7 +100,7 @@ TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop)
void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
const SGPropertyNode* prop,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
if (!isAttributeActive(effect, prop))
return;
@@ -141,7 +143,8 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
}
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;
@@ -177,7 +180,7 @@ EffectPropertyMap<Texture::WrapMode> wrapModes(wrapModesInit);
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;
@@ -213,7 +216,7 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
}
void setAttrs(const TexTuple& attrs, Texture* tex,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
const string& imageName = attrs.get<0>();
if (imageName.empty()) {
@@ -253,7 +256,7 @@ class TexBuilder : public TextureBuilder
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;
@@ -262,7 +265,7 @@ protected:
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);
@@ -286,11 +289,11 @@ class WhiteTextureBuilder : public TextureBuilder
{
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();
}
@@ -304,11 +307,11 @@ class TransparentTextureBuilder : public TextureBuilder
{
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();
}
@@ -368,14 +371,14 @@ class NoiseBuilder : public TextureBuilder
{
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,
@@ -443,7 +446,8 @@ EffectNameValue<TexEnvCombine::OperandParam> opParamInit[] =
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;
@@ -538,7 +542,8 @@ TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
const SGPropertyNode* colorNode = envProp->getChild("constant-color");
if (colorNode)
initFromParameters(effect, colorNode, result,
&TexEnvCombine::setConstantColor, colorFields);
&TexEnvCombine::setConstantColor, colorFields,
options);
return result;
}

View File

@@ -29,13 +29,13 @@ public:
// 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);
};

View File

@@ -31,6 +31,7 @@
#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>
@@ -116,7 +117,7 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
Effect* makeEffect(const string& name,
bool realizeTechniques,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
{
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
@@ -159,7 +160,7 @@ Effect* makeEffect(const string& name,
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");

View File

@@ -49,6 +49,7 @@
#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>
@@ -68,12 +69,12 @@ using namespace simgear;
////////////////////////////////////////////////////////////////////////
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();
@@ -81,6 +82,17 @@ SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
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)
{
}
@@ -91,7 +103,7 @@ 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)
@@ -245,10 +257,12 @@ Effect* SGMaterial::get_effect(int n)
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);
@@ -279,7 +293,7 @@ void SGMaterial::buildEffectProperties(const osgDB::ReaderWriter::Options*
->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());
}
}

View File

@@ -39,13 +39,13 @@
#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>
@@ -87,6 +87,8 @@ public:
*/
SGMaterial( const osgDB::ReaderWriter::Options*, const SGPropertyNode *props);
SGMaterial(const simgear::SGReaderWriterXMLOptions*,
const SGPropertyNode *props);
/**
* Destructor.
*/
@@ -271,11 +273,11 @@ protected:
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:
@@ -361,9 +363,9 @@ 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);
};

View File

@@ -18,7 +18,7 @@
#ifndef SGREADERWRITERXMLOPTIONS_HXX
#define SGREADERWRITERXMLOPTIONS_HXX 1
#include <osgDB/ReaderWriter>
#include <osgDB/Registry>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/props/props.hxx>

View File

@@ -33,6 +33,7 @@
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
#include "SGReaderWriterXMLOptions.hxx"
#include "model.hxx"
using std::vector;
@@ -209,7 +210,7 @@ class MakeEffectVisitor : public SplicingVisitor
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)
{
}
@@ -225,7 +226,7 @@ public:
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)
@@ -302,7 +303,7 @@ protected:
ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
PropertyList& effectProps,
const osgDB::ReaderWriter::Options* options)
const SGReaderWriterXMLOptions* options)
{
SGPropertyNode_ptr defaultEffectPropRoot;
MakeEffectVisitor visitor(options);

View File

@@ -23,6 +23,11 @@
#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,
@@ -97,7 +102,7 @@ public:
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
@@ -110,7 +115,7 @@ instantiateEffects(osg::Node* model,
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);

View File

@@ -71,8 +71,12 @@ osg::Node* loadFile(const string& path, osgDB::ReaderWriter::Options* 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();
}
}

View File

@@ -46,6 +46,7 @@
#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>
@@ -108,9 +109,11 @@ SGNewCloud::SGNewCloud(string type,
"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();