]> git.mxchange.org Git - simgear.git/commitdiff
Implement a cache of light effects
authorFrederic Bouvier <fredfgfs01@free.fr>
Wed, 4 Jan 2012 18:42:46 +0000 (19:42 +0100)
committerFrederic Bouvier <fredfgfs01@free.fr>
Sun, 4 Mar 2012 19:21:24 +0000 (20:21 +0100)
simgear/scene/model/SGLightAnimation.cxx
simgear/scene/model/SGReaderWriterXML.cxx
simgear/scene/model/animation.cxx
simgear/scene/model/animation.hxx

index 6d6257b47df2b49ec0d28d638ae4ab6ba25968e8..4e7c2a167d9da1f27778adc2c6823026a2a82662 100644 (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 = simgear::makeEffect(effectProp, true);
+        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);
+
+            effect = simgear::makeEffect(effectProp, true);
+            lightEffectMap.insert(EffectMap::value_type(_key, effect));
+        } else {
+            effect = iter->second.get();
+        }
         geode->setEffect(effect);
     }
 }
index 1a83f2043aebf3edae8c68ab5899acc841a64186..3a461328f9ad4943f4ed9db8b924caf869451c3d 100644 (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);
index b6748fe036c0bee7df286f530aab5401f1fad7f9..582046ea8d952f2b8824e2642f20e59e28533bdb 100644 (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);
index fcd81a97aae8c91767d7979ff7222de411e12cb0..331ff3cf1886137b180c057d5e7ca96adb6981e4 100644 (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