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

View File

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

View File

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

View File

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