#include <simgear/debug/logstream.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
#include <simgear/scene/util/SGEnlargeBoundingBox.hxx>
+#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/StateAttributeFactory.hxx>
#include <simgear/scene/material/Effect.hxx>
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;
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, "DepthSortedBin");
spritePass->setTextureAttribute(0, attrFact->getStandardTexEnv());
Pass *combinedPass = clone(spritePass, CopyOp::SHALLOW_COPY);
combinedPass->setAttributeAndModes(point);
- Effect* effect = new Effect;
- std::vector<std::string> combinedExtensions;
- combinedExtensions.push_back("GL_ARB_point_sprite");
- combinedExtensions.push_back("GL_ARB_point_parameters");
- Technique* combinedTniq = new Technique;
- combinedTniq->passes.push_back(combinedPass);
- combinedTniq->setGLExtensionsPred(2.0, combinedExtensions);
- effect->techniques.push_back(combinedTniq);
- std::vector<std::string> spriteExtensions;
- spriteExtensions.push_back(combinedExtensions.front());
- Technique* spriteTniq = new Technique;
- spriteTniq->passes.push_back(spritePass);
- spriteTniq->setGLExtensionsPred(2.0, spriteExtensions);
- effect->techniques.push_back(spriteTniq);
+ ref_ptr<Effect> effect = new Effect;
std::vector<std::string> parameterExtensions;
- parameterExtensions.push_back(combinedExtensions.back());
+
+ if (SGSceneFeatures::instance()->getEnablePointSpriteLights())
+ {
+ std::vector<std::string> combinedExtensions;
+ combinedExtensions.push_back("GL_ARB_point_sprite");
+ combinedExtensions.push_back("GL_ARB_point_parameters");
+ Technique* combinedTniq = new Technique;
+ combinedTniq->passes.push_back(combinedPass);
+ combinedTniq->setGLExtensionsPred(2.0, combinedExtensions);
+ effect->techniques.push_back(combinedTniq);
+ std::vector<std::string> spriteExtensions;
+ spriteExtensions.push_back(combinedExtensions.front());
+ Technique* spriteTniq = new Technique;
+ spriteTniq->passes.push_back(spritePass);
+ spriteTniq->setGLExtensionsPred(2.0, spriteExtensions);
+ effect->techniques.push_back(spriteTniq);
+ parameterExtensions.push_back(combinedExtensions.back());
+ }
+
Technique* parameterTniq = new Technique;
parameterTniq->passes.push_back(attenuationPass);
parameterTniq->setGLExtensionsPred(1.4, parameterExtensions);
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();
}
drawable->addLight(lights.getLight(3).position,
lights.getLight(3).normal, up, 2.5);
return drawable;
- }
- else if (count == 12) {
+
+ } else if (count == 6) {
+ SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
+
+ // probably vasi, first 3 are downwind bar (2.5 deg)
+ for (unsigned i = 0; i < 3; ++i)
+ drawable->addLight(lights.getLight(i).position,
+ lights.getLight(i).normal, up, 2.5);
+ // last 3 are upwind bar (3.0 deg)
+ for (unsigned i = 3; i < 6; ++i)
+ drawable->addLight(lights.getLight(i).position,
+ lights.getLight(i).normal, up, 3.0);
+ return drawable;
+
+ } else if (count == 12) {
SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
// probably vasi, first 6 are downwind bar (2.5 deg)
for (unsigned i = 6; i < 12; ++i)
drawable->addLight(lights.getLight(i).position,
lights.getLight(i).normal, up, 3.0);
-
return drawable;
+
} else {
// fail safe
SG_LOG(SG_TERRAIN, SG_ALERT,
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;
+}