]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/tgdb/pt_lights.cxx
pt_lights: softly fade in and out the blinking lights
[simgear.git] / simgear / scene / tgdb / pt_lights.cxx
index a072061ac056d1accac62247e8f0eabbabb2c2b2..7e123a475da55583f31b65ba2dd59e28ae846fa8 100644 (file)
@@ -159,7 +159,7 @@ gen_standard_light_sprite(void)
 namespace
 {
 typedef boost::tuple<float, osg::Vec3, float, float, bool> PointParams;
-typedef std::map<PointParams, ref_ptr<Effect> > EffectMap;
+typedef std::map<PointParams, observer_ptr<Effect> > EffectMap;
 
 EffectMap effectMap;
 
@@ -175,10 +175,14 @@ Effect* getLightEffect(float size, const Vec3& attenuation,
     ScopedLock<Mutex> lock(lightMutex);
     EffectMap::iterator eitr = effectMap.find(pointParams);
     if (eitr != effectMap.end())
-        return eitr->second.get();
+    {
+        ref_ptr<Effect> effect;
+        if (eitr->second.lock(effect))
+            return effect.release();
+    }
     // Basic stuff; no sprite or attenuation support
     Pass *basicPass = new Pass;
-    basicPass->setRenderBinDetails(POINT_LIGHTS_BIN, "RenderBin");
+    basicPass->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
     basicPass->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
     StateAttributeFactory *attrFact = StateAttributeFactory::instance();
     basicPass->setAttributeAndModes(attrFact->getStandardBlendFunc());
@@ -204,7 +208,7 @@ Effect* getLightEffect(float size, const Vec3& attenuation,
     spritePass->setTextureAttribute(0, attrFact->getStandardTexEnv());
     Pass *combinedPass = clone(spritePass, CopyOp::SHALLOW_COPY);
     combinedPass->setAttributeAndModes(point);
-    Effect* effect = new Effect;
+    ref_ptr<Effect> effect = new Effect;
     std::vector<std::string> parameterExtensions;
 
     if (SGSceneFeatures::instance()->getEnablePointSpriteLights())
@@ -232,8 +236,11 @@ Effect* getLightEffect(float size, const Vec3& attenuation,
     Technique* basicTniq = new Technique(true);
     basicTniq->passes.push_back(basicPass);
     effect->techniques.push_back(basicTniq);
-    effectMap.insert(std::make_pair(pointParams, effect));
-    return effect;
+    if (eitr == effectMap.end())
+        effectMap.insert(std::make_pair(pointParams, effect));
+    else
+        eitr->second = effect; // update existing, but empty observer
+    return effect.release();
 }
 
 
@@ -336,7 +343,7 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff
     if (!simpleLightSS.valid()) {
       StateAttributeFactory *attrFact = StateAttributeFactory::instance();
       simpleLightSS = new StateSet;
-      simpleLightSS->setRenderBinDetails(POINT_LIGHTS_BIN, "RenderBin");
+      simpleLightSS->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
       simpleLightSS->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
       simpleLightSS->setAttributeAndModes(attrFact->getStandardBlendFunc());
       simpleLightSS->setAttributeAndModes(attrFact->getStandardAlphaFunc());
@@ -452,7 +459,7 @@ SGLightFactory::getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
     return 0;
 
   osg::StateSet* stateSet = drawable->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "RenderBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 
   osg::BlendFunc* blendFunc = new osg::BlendFunc;
@@ -478,8 +485,8 @@ SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
   float flashTime = 2e-2 + 5e-3*sg_random();
   osg::Sequence* sequence = new osg::Sequence;
   sequence->setDefaultTime(flashTime);
-  Effect* effect = getLightEffect(40.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
-                                  10.0f, 40.0f, true);
+  Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
+                                  6.0f, 10.0f, true);
   for (int i = lights.getNumLights() - 1; 0 <= i; --i) {
     EffectGeode* egeode = new EffectGeode;
     egeode->setEffect(effect);
@@ -505,8 +512,8 @@ SGLightFactory::getOdal(const SGLightBin& lights)
   float flashTime = 2e-2 + 5e-3*sg_random();
   osg::Sequence* sequence = new osg::Sequence;
   sequence->setDefaultTime(flashTime);
-  Effect* effect = getLightEffect(40.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
-                                  10.0, 40.0, false);
+  Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
+                                  6.0, 10.0, false);
   // centerline lights
   for (int i = lights.getNumLights() - 1; 2 <= i; --i) {
     EffectGeode* egeode = new EffectGeode;
@@ -533,3 +540,35 @@ SGLightFactory::getOdal(const SGLightBin& lights)
 
   return sequence;
 }
+
+// Blinking hold short line lights
+osg::Node*
+SGLightFactory::getHoldShort(const SGDirectionalLightBin& lights)
+{
+  if (lights.getNumLights() < 2)
+    return 0;
+
+  sg_srandom(unsigned(lights.getLight(0).position[0]));
+  float flashTime = 2 + 0.1 * sg_random();
+  osg::Sequence* sequence = new osg::Sequence;
+
+  // start with lights off
+  sequence->addChild(new osg::Group, flashTime);
+  // ...and increase the lights in steps
+  for (int i = 2; i < 7; i+=2) {
+      Effect* effect = getLightEffect(i, osg::Vec3(1, 0.001, 0.000002),
+                                      0, i, true);
+      EffectGeode* egeode = new EffectGeode;
+      for (unsigned int j = 0; j < lights.getNumLights(); ++j) {
+          egeode->addDrawable(getLightDrawable(lights.getLight(j)));
+          egeode->setEffect(effect);
+      }
+      sequence->addChild(egeode, (i==6) ? flashTime : 0.1);
+  }
+
+  sequence->setInterval(osg::Sequence::SWING, 0, -1);
+  sequence->setDuration(1.0f, -1);
+  sequence->setMode(osg::Sequence::START);
+
+  return sequence;
+}