Implement a cache of light effects

This commit is contained in:
Frederic Bouvier 2012-01-04 19:42:46 +01:00
parent ad6c04489c
commit b582cd230e
4 changed files with 40 additions and 23 deletions

View File

@ -19,6 +19,8 @@
# include <simgear_config.h> # include <simgear_config.h>
#endif #endif
#include <boost/lexical_cast.hpp>
#include "animation.hxx" #include "animation.hxx"
#include "ConditionNode.hxx" #include "ConditionNode.hxx"
@ -28,6 +30,9 @@
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <simgear/scene/util/CopyOp.hxx> #include <simgear/scene/util/CopyOp.hxx>
typedef std::map<string, osg::ref_ptr<simgear::Effect> > EffectMap;
static EffectMap lightEffectMap;
#define GET_COLOR_VALUE(n) \ #define GET_COLOR_VALUE(n) \
SGVec4d( getConfig()->getDoubleValue(n "/r"), \ SGVec4d( getConfig()->getDoubleValue(n "/r"), \
getConfig()->getDoubleValue(n "/g"), \ getConfig()->getDoubleValue(n "/g"), \
@ -35,7 +40,8 @@
getConfig()->getDoubleValue(n "/a") ) getConfig()->getDoubleValue(n "/a") )
SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode, SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot) : SGPropertyNode* modelRoot,
const string &path, int i) :
SGAnimation(configNode, modelRoot) SGAnimation(configNode, modelRoot)
{ {
_position = SGVec3d( getConfig()->getDoubleValue("position/x"), getConfig()->getDoubleValue("position/y"), getConfig()->getDoubleValue("position/z") ); _position = SGVec3d( getConfig()->getDoubleValue("position/x"), getConfig()->getDoubleValue("position/y"), getConfig()->getDoubleValue("position/z") );
@ -50,6 +56,7 @@ SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
_cutoff = getConfig()->getDoubleValue("cutoff"); _cutoff = getConfig()->getDoubleValue("cutoff");
_near = getConfig()->getDoubleValue("near-m"); _near = getConfig()->getDoubleValue("near-m");
_far = getConfig()->getDoubleValue("far-m"); _far = getConfig()->getDoubleValue("far-m");
_key = path + ";" + boost::lexical_cast<string>( i );
} }
osg::Group* osg::Group*
@ -91,7 +98,7 @@ cone->setUseDisplayList(false);
} }
osg::Vec4Array* colours = new osg::Vec4Array(1); osg::Vec4Array* colours = new osg::Vec4Array(1);
(*colours)[0] = osg::Vec4d(toOsg(getConfig()->getValue<SGVec3d>("diffuse")), 1.0f); (*colours)[0] = toOsg(_diffuse);
cone->setColorArray(colours); cone->setColorArray(colours);
cone->setColorBinding(osg::Geometry::BIND_OVERALL); cone->setColorBinding(osg::Geometry::BIND_OVERALL);
@ -109,23 +116,29 @@ cone->setUseDisplayList(false);
node.asGroup()->addChild( geode ); node.asGroup()->addChild( geode );
// TODO: build a cache - problem: what is the key ? simgear::Effect* effect = 0;
SGPropertyNode_ptr effectProp = new SGPropertyNode; EffectMap::iterator iter = lightEffectMap.find(_key);
makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot"); if (iter == lightEffectMap.end()) {
SGPropertyNode* params = makeChild(effectProp, "parameters"); SGPropertyNode_ptr effectProp = new SGPropertyNode;
params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0)); makeChild(effectProp, "inherits-from")->setStringValue("Effects/light-spot");
params->getNode("light-spot/direction",true)->setValue(SGVec4d(_direction.x(),_direction.y(),_direction.z(),0.0)); SGPropertyNode* params = makeChild(effectProp, "parameters");
params->getNode("light-spot/ambient",true)->setValue(_ambient); params->getNode("light-spot/position",true)->setValue(SGVec4d(_position.x(),_position.y(),_position.z(),1.0));
params->getNode("light-spot/diffuse",true)->setValue(_diffuse); params->getNode("light-spot/direction",true)->setValue(SGVec4d(_direction.x(),_direction.y(),_direction.z(),0.0));
params->getNode("light-spot/specular",true)->setValue(_specular); params->getNode("light-spot/ambient",true)->setValue(_ambient);
params->getNode("light-spot/attenuation",true)->setValue(_attenuation); params->getNode("light-spot/diffuse",true)->setValue(_diffuse);
params->getNode("light-spot/exponent",true)->setValue(_exponent); params->getNode("light-spot/specular",true)->setValue(_specular);
params->getNode("light-spot/cutoff",true)->setValue(_cutoff); params->getNode("light-spot/attenuation",true)->setValue(_attenuation);
params->getNode("light-spot/cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) ); params->getNode("light-spot/exponent",true)->setValue(_exponent);
params->getNode("light-spot/near",true)->setValue(_near); params->getNode("light-spot/cutoff",true)->setValue(_cutoff);
params->getNode("light-spot/far",true)->setValue(_far); params->getNode("light-spot/cosCutoff",true)->setValue( cos(_cutoff*SG_DEGREES_TO_RADIANS) );
params->getNode("light-spot/near",true)->setValue(_near);
params->getNode("light-spot/far",true)->setValue(_far);
simgear::Effect* effect = simgear::makeEffect(effectProp, true); effect = simgear::makeEffect(effectProp, true);
lightEffectMap.insert(EffectMap::value_type(_key, effect));
} else {
effect = iter->second.get();
}
geode->setEffect(effect); geode->setEffect(effect);
} }
} }

View File

@ -438,7 +438,7 @@ sgLoad3DModel_internal(const SGPath& path,
for (unsigned i = 0; i < animation_nodes.size(); ++i) for (unsigned i = 0; i < animation_nodes.size(); ++i)
/// OSGFIXME: duh, why not only model????? /// OSGFIXME: duh, why not only model?????
SGAnimation::animate(group.get(), animation_nodes[i], prop_root, SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
options.get()); options.get(), path.str(), i);
if (!needTransform && group->getNumChildren() < 2) { if (!needTransform && group->getNumChildren() < 2) {
model = group->getChild(0); model = group->getChild(0);

View File

@ -410,7 +410,8 @@ SGAnimation::~SGAnimation()
bool bool
SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode, SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode,
SGPropertyNode* modelRoot, SGPropertyNode* modelRoot,
const osgDB::Options* options) const osgDB::Options* options,
const string &path, int i)
{ {
std::string type = configNode->getStringValue("type", "none"); std::string type = configNode->getStringValue("type", "none");
if (type == "alpha-test") { if (type == "alpha-test") {
@ -466,7 +467,7 @@ SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode,
SGTranslateAnimation animInst(configNode, modelRoot); SGTranslateAnimation animInst(configNode, modelRoot);
animInst.apply(node); animInst.apply(node);
} else if (type == "light") { } else if (type == "light") {
SGLightAnimation animInst(configNode, modelRoot); SGLightAnimation animInst(configNode, modelRoot, path, i);
animInst.apply(node); animInst.apply(node);
} else if (type == "null" || type == "none" || type.empty()) { } else if (type == "null" || type == "none" || type.empty()) {
SGGroupAnimation animInst(configNode, modelRoot); SGGroupAnimation animInst(configNode, modelRoot);

View File

@ -46,7 +46,8 @@ public:
static bool animate(osg::Node* node, const SGPropertyNode* configNode, static bool animate(osg::Node* node, const SGPropertyNode* configNode,
SGPropertyNode* modelRoot, SGPropertyNode* modelRoot,
const osgDB::Options* options); const osgDB::Options* options,
const string &path, int i);
protected: protected:
void apply(osg::Node* node); void apply(osg::Node* node);
@ -351,7 +352,8 @@ private:
class SGLightAnimation : public SGAnimation { class SGLightAnimation : public SGAnimation {
public: public:
SGLightAnimation(const SGPropertyNode* configNode, SGLightAnimation(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot); SGPropertyNode* modelRoot,
const string &path, int i);
virtual osg::Group* createAnimationGroup(osg::Group& parent); virtual osg::Group* createAnimationGroup(osg::Group& parent);
virtual void install(osg::Node& node); virtual void install(osg::Node& node);
private: private:
@ -365,6 +367,7 @@ private:
double _cutoff; double _cutoff;
double _near; double _near;
double _far; double _far;
string _key;
}; };
#endif // _SG_ANIMATION_HXX #endif // _SG_ANIMATION_HXX