_texCoords = new osg::Vec2Array(4);
_texCoords->setDataVariance(osg::Object::DYNAMIC);
- _geom->setTexCoordArray(0, _texCoords);
+ _geom->setTexCoordArray(0, _texCoords, osg::Array::BIND_PER_VERTEX);
_colors = new osg::Vec4Array(1);
_colors->setDataVariance(osg::Object::DYNAMIC);
- _geom->setColorArray(_colors);
- _geom->setColorBinding(osg::Geometry::BIND_OVERALL);
+ _geom->setColorArray(_colors, osg::Array::BIND_OVERALL);
_prim = new osg::DrawArrays(osg::PrimitiveSet::QUADS);
_prim->set(osg::PrimitiveSet::QUADS, 0, 4);
#include <osg/Math>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
+#include <osg/Point>
#include <osg/Program>
#include <osg/Referenced>
#include <osg/RenderInfo>
pass->setMode(GL_CULL_FACE, StateAttribute::OFF);
else
SG_LOG(SG_INPUT, SG_ALERT,
- "invalid cull face property " << propVal);
- }
+ "invalid cull face property " << propVal);
+ }
};
InstallAttributeBuilder<CullFaceBuilder> installCullFace("cull-face");
Vec4 m = getColor(realProp);
mask->setMask(m.r() > 0.0, m.g() > 0.0, m.b() > 0.0, m.a() > 0.0);
pass->setAttributeAndModes(mask);
- }
+ }
};
InstallAttributeBuilder<ColorMaskBuilder> installColorMask("color-mask");
StateSet::RenderingHint renderingHint = StateSet::DEFAULT_BIN;
findAttr(renderingHints, realProp, renderingHint);
pass->setRenderingHint(renderingHint);
- }
+ }
};
InstallAttributeBuilder<HintBuilder> installHint("rendering-hint");
if ((color = getEffectPropertyChild(effect, prop, "emissive")))
mat->setEmission(Material::FRONT_AND_BACK, getColor(color));
if ((color = getEffectPropertyChild(effect, prop, "emissive-front")))
- mat->setEmission(Material::FRONT, getColor(color));
+ mat->setEmission(Material::FRONT, getColor(color));
if ((color = getEffectPropertyChild(effect, prop, "emissive-back")))
- mat->setEmission(Material::BACK, getColor(color));
+ mat->setEmission(Material::BACK, getColor(color));
const SGPropertyNode* shininess = 0;
mat->setShininess(Material::FRONT_AND_BACK, 0.0f);
if ((shininess = getEffectPropertyChild(effect, prop, "shininess")))
findAttr(stencilFunction, pfunction, func);
if (pvalue)
ref = pvalue->getIntValue();
- if (pmask)
+ if (pmask)
mask = pmask->getIntValue();
if (psfail)
const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
if (!realProp)
return;
- pass->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, (realProp->getValue<bool>() ?
+ pass->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, (realProp->getValue<bool>() ?
StateAttribute::ON : StateAttribute::OFF));
}
{
if (!isAttributeActive(effect, prop))
return;
-
+
const SGPropertyNode* factor
= getEffectPropertyChild(effect, prop, "factor");
const SGPropertyNode* units
= getEffectPropertyChild(effect, prop, "units");
-
+
ref_ptr<PolygonOffset> polyoffset = new PolygonOffset;
-
+
polyoffset->setFactor(factor->getFloatValue());
polyoffset->setUnits(units->getFloatValue());
SG_LOG(SG_INPUT, SG_BULK,
- "Set PolygonOffset to " << polyoffset->getFactor() << polyoffset->getUnits() );
+ "Set PolygonOffset to " << polyoffset->getFactor() << polyoffset->getUnits() );
pass->setAttributeAndModes(polyoffset.get(),
StateAttribute::OVERRIDE|StateAttribute::ON);
InstallAttributeBuilder<VertexProgramPointSizeBuilder>
installPointSize("vertex-program-point-size");
+struct PointBuilder : public PassAttributeBuilder
+{
+ void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+ const SGReaderWriterOptions* options)
+ {
+ float minsize = 1.0;
+ float maxsize = 1.0;
+ float size = 1.0;
+ osg::Vec3f attenuation = osg::Vec3f(1.0, 1.0, 1.0);
+
+ const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
+ if (!realProp)
+ return;
+
+ const SGPropertyNode* pminsize
+ = getEffectPropertyChild(effect, prop, "min-size");
+ const SGPropertyNode* pmaxsize
+ = getEffectPropertyChild(effect, prop, "max-size");
+ const SGPropertyNode* psize
+ = getEffectPropertyChild(effect, prop, "size");
+ const SGPropertyNode* pattenuation
+ = getEffectPropertyChild(effect, prop, "attenuation");
+
+ if (pminsize)
+ minsize = pminsize->getFloatValue();
+ if (pmaxsize)
+ maxsize = pmaxsize->getFloatValue();
+ if (psize)
+ size = psize->getFloatValue();
+ if (pattenuation)
+ attenuation = osg::Vec3f(pattenuation->getChild("x")->getFloatValue(),
+ pattenuation->getChild("y")->getFloatValue(),
+ pattenuation->getChild("z")->getFloatValue());
+
+ osg::Point* point = new osg::Point;
+ point->setMinSize(minsize);
+ point->setMaxSize(maxsize);
+ point->setSize(size);
+ point->setDistanceAttenuation(attenuation);
+ pass->setAttributeAndModes(point);
+ }
+};
+
+InstallAttributeBuilder<PointBuilder>
+installPoint("point");
+
EffectNameValue<Depth::Function> depthFunctionInit[] =
{
{"never", Depth::NEVER},
{
public:
PropertyExpression(SGPropertyNode* pnode) : _pnode(pnode), _listener(NULL) {}
-
+
~PropertyExpression()
{
delete _listener;
}
-
+
void eval(T& value, const expression::Binding*) const
{
value = _pnode->getValue<T>();
}
-
+
void setListener(SGPropertyChangeListener* l)
{
_listener = l;
{
public:
EffectPropertyListener(Technique* tniq) : _tniq(tniq) {}
-
+
void valueChanged(SGPropertyNode* node)
{
if (_tniq.valid())
_tniq->refreshValidity();
}
-
+
virtual ~EffectPropertyListener() { }
-
+
protected:
osg::observer_ptr<Technique> _tniq;
};
#include "Pass.hxx"
+#include <osg/PointSprite>
#include <osg/TexEnv>
#include <osg/TexEnvCombine>
#include <osg/TexGen>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+
#include <boost/lexical_cast.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
namespace simgear
{
+
+using OpenThreads::Mutex;
+using OpenThreads::ScopedLock;
+
using namespace std;
using namespace osg;
<< "using white for type '" << type << "' on '" << pass->getName() << "', in " << prop->getPath() );
texture = StateAttributeFactory::instance()->getWhiteTexture();
}
+
+ const SGPropertyNode* pPoint = getEffectPropertyChild(effect, prop, "point-sprite");
+ if (pPoint && pPoint->getBoolValue()) {
+ ref_ptr<PointSprite> pointSprite = new PointSprite;
+ pass->setTextureAttributeAndModes(unit, pointSprite.get(), osg::StateAttribute::ON);
+ }
+
pass->setTextureAttributeAndModes(unit, texture);
+
const SGPropertyNode* envProp = prop->getChild("environment");
if (envProp) {
TexEnv* env = buildTexEnv(effect, envProp);
const SGPropertyNode* pMipmapControl
= getEffectPropertyChild(effect, props, "mipmap-control");
- MipMapTuple mipmapFunctions( AUTOMATIC, AUTOMATIC, AUTOMATIC, AUTOMATIC );
+ MipMapTuple mipmapFunctions( AUTOMATIC, AUTOMATIC, AUTOMATIC, AUTOMATIC );
if ( pMipmapControl )
mipmapFunctions = makeMipMapTuple(effect, pMipmapControl, options);
const SGReaderWriterOptions* options)
{
const string& imageName = attrs.get<0>();
- if (imageName.empty())
+ if (imageName.empty())
return false;
-
+
osgDB::ReaderWriter::ReadResult result;
result = osgDB::readImageFile(imageName, options);
osg::ref_ptr<osg::Image> image;
tex = new T;
if (!setAttrs(attrs, tex, options))
return NULL;
-
+
if (itr == texMap.end())
texMap.insert(make_pair(attrs, tex));
else
TextureBuilder::Registrar installNoise("noise", new NoiseBuilder);
}
+class LightSpriteBuilder : public TextureBuilder
+{
+public:
+ Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
+ const SGReaderWriterOptions* options);
+protected:
+ Mutex lightMutex;
+ void setPointSpriteImage(unsigned char* data, unsigned log2resolution,
+ unsigned charsPerPixel);
+ osg::Image* getPointSpriteImage(int logResolution);
+};
+
+Texture* LightSpriteBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
+ const SGReaderWriterOptions* options)
+{
+ ScopedLock<Mutex> lock(lightMutex);
+
+ // Always called from when the lightMutex is already taken
+ static osg::ref_ptr<osg::Texture2D> texture;
+
+ if (texture.valid())
+ return texture.get();
+
+ texture = new osg::Texture2D;
+ texture->setImage(getPointSpriteImage(6));
+ texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
+ texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
+
+ return texture.get();
+}
+
+void
+LightSpriteBuilder::setPointSpriteImage(unsigned char* data, unsigned log2resolution,
+ unsigned charsPerPixel)
+{
+ int env_tex_res = (1 << log2resolution);
+ for (int i = 0; i < env_tex_res; ++i) {
+ for (int j = 0; j < env_tex_res; ++j) {
+ int xi = 2*i + 1 - env_tex_res;
+ int yi = 2*j + 1 - env_tex_res;
+ if (xi < 0)
+ xi = -xi;
+ if (yi < 0)
+ yi = -yi;
+
+ xi -= 1;
+ yi -= 1;
+
+ if (xi < 0)
+ xi = 0;
+ if (yi < 0)
+ yi = 0;
+
+ float x = 1.5*xi/(float)(env_tex_res);
+ float y = 1.5*yi/(float)(env_tex_res);
+ // float x = 2*xi/(float)(env_tex_res);
+ // float y = 2*yi/(float)(env_tex_res);
+ float dist = sqrt(x*x + y*y);
+ float bright = SGMiscf::clip(255*(1-dist), 0, 255);
+ for (unsigned l = 0; l < charsPerPixel; ++l)
+ data[charsPerPixel*(i*env_tex_res + j) + l] = (unsigned char)bright;
+ }
+ }
+}
+
+osg::Image*
+LightSpriteBuilder::getPointSpriteImage(int logResolution)
+{
+ osg::Image* image = new osg::Image;
+
+ osg::Image::MipmapDataType mipmapOffsets;
+ unsigned off = 0;
+ for (int i = logResolution; 0 <= i; --i) {
+ unsigned res = 1 << i;
+ off += res*res;
+ mipmapOffsets.push_back(off);
+ }
+
+ int env_tex_res = (1 << logResolution);
+
+ unsigned char* imageData = new unsigned char[off];
+ image->setImage(env_tex_res, env_tex_res, 1,
+ GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, imageData,
+ osg::Image::USE_NEW_DELETE);
+ image->setMipmapLevels(mipmapOffsets);
+ for (int k = logResolution; 0 <= k; --k) {
+ setPointSpriteImage(image->getMipmapData(logResolution - k), k, 1);
+ }
+
+ return image;
+}
+
+namespace
+{
+TextureBuilder::Registrar installLightSprite("light-sprite", new LightSpriteBuilder);
+}
// Image names for all sides
typedef boost::tuple<string, string, string, string, string, string> CubeMapTuple;
// I use this until osg::CopyImage is fixed
// This one assumes images are the same format and sizes are correct
-void copySubImage(const osg::Image* srcImage, int src_s, int src_t, int width, int height,
+void copySubImage(const osg::Image* srcImage, int src_s, int src_t, int width, int height,
osg::Image* destImage, int dest_s, int dest_t)
{
for(int row = 0; row<height; ++row)
->getWhiteTexture(),
osg::StateAttribute::ON);
rootSet->setDataVariance(osg::Object::DYNAMIC);
-
+
// Ensure repeatability of the random seed within 10 minutes,
// to keep multi-computer systems in sync.
sg_srandom_time_10();
}
}
-SGCloudLayer::Coverage
+SGCloudLayer::Coverage
SGCloudLayer::getCoverageType( const std::string & coverage )
{
if( SG_CLOUD_OVERCAST_STRING == coverage ) {
SGCloudLayer::rebuild()
{
// Initialize states and sizes if necessary.
- if ( !state_initialized ) {
+ if ( !state_initialized ) {
state_initialized = true;
SG_LOG(SG_ASTRO, SG_INFO, "initializing cloud layers");
- // This bump mapping code was inspired by the tutorial available at
+ // This bump mapping code was inspired by the tutorial available at
// http://www.paulsprojects.net/tutorials/simplebump/simplebump.html
- // and a NVidia white paper
+ // and a NVidia white paper
// http://developer.nvidia.com/object/bumpmappingwithregistercombiners.html
// The normal map textures were generated by the normal map Gimp plugin :
// http://nifelheim.dyndns.org/~cocidius/normalmap/
-( i + offset - half_size ) );
tmp.normalize();
tmp = tmp*0.5 - zero_normal;
-
+
*ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
( i + offset - half_size ) );
tmp.normalize();
tmp = tmp*0.5 - zero_normal;
-
+
*ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
( j + offset - half_size ) );
tmp.normalize();
tmp = tmp*0.5 - zero_normal;
-
+
*ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
-( j + offset - half_size ), half_size );
tmp.normalize();
tmp = tmp*0.5 - zero_normal;
-
+
*ptr++ = (unsigned char)( tmp[ 0 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 1 ] * 255 );
*ptr++ = (unsigned char)( tmp[ 2 ] * 255 );
layer_states[SG_CLOUD_OVERCAST] = state;
state = SGMakeState(texture_path, "overcast_top.png", "overcast_top_n.png");
layer_states2[SG_CLOUD_OVERCAST] = state;
-
+
state = SGMakeState(texture_path, "broken.png", "broken_n.png");
layer_states[SG_CLOUD_BROKEN] = state;
layer_states2[SG_CLOUD_BROKEN] = state;
-
+
state = SGMakeState(texture_path, "scattered.png", "scattered_n.png");
layer_states[SG_CLOUD_SCATTERED] = state;
layer_states2[SG_CLOUD_SCATTERED] = state;
-
+
state = SGMakeState(texture_path, "few.png", "few_n.png");
layer_states[SG_CLOUD_FEW] = state;
layer_states2[SG_CLOUD_FEW] = state;
-
+
state = SGMakeState(texture_path, "cirrus.png", "cirrus_n.png");
layer_states[SG_CLOUD_CIRRUS] = state;
layer_states2[SG_CLOUD_CIRRUS] = state;
-
+
layer_states[SG_CLOUD_CLEAR] = 0;
layer_states2[SG_CLOUD_CLEAR] = 0;
#if 1
// build the cloud layer
const float layer_scale = layer_span / scale;
const float mpi = SG_PI/4;
-
- // caclculate the difference between a flat-earth model and
+
+ // caclculate the difference between a flat-earth model and
// a round earth model given the span and altutude ASL of
// the cloud layer. This is the difference in altitude between
// the top of the inverted bowl and the edge of the bowl.
const float layer_angle = 0.5*layer_span / layer_to_core; // The angle is half the span
const float border_to_core = layer_to_core * cos(layer_angle);
const float alt_diff = layer_to_core - border_to_core;
-
+
for (int i = 0; i < 4; i++) {
if ( layer[i] != NULL ) {
layer_transform->removeChild(layer[i].get()); // automatic delete
}
-
+
vl[i] = new osg::Vec3Array;
cl[i] = new osg::Vec4Array;
tl[i] = new osg::Vec2Array;
-
-
+
+
osg::Vec3 vertex(layer_span*(i-2)/2, -layer_span,
alt_diff * (sin(i*mpi) - 2));
osg::Vec2 tc(layer_scale * i/4, 0.0f);
osg::Vec4 color(cloudColors[0], (i == 0) ? 0.0f : 0.15f);
-
+
cl[i]->push_back(color);
vl[i]->push_back(vertex);
tl[i]->push_back(tc);
-
+
for (int j = 0; j < 4; j++) {
vertex = osg::Vec3(layer_span*(i-1)/2, layer_span*(j-2)/2,
alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2));
tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale * j/4);
color = osg::Vec4(cloudColors[0],
- ( (j == 0) || (i == 3)) ?
+ ( (j == 0) || (i == 3)) ?
( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );
-
+
cl[i]->push_back(color);
vl[i]->push_back(vertex);
tl[i]->push_back(tc);
-
+
vertex = osg::Vec3(layer_span*(i-2)/2, layer_span*(j-1)/2,
alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2) );
tc = osg::Vec2(layer_scale * i/4, layer_scale * (j+1)/4 );
vl[i]->push_back(vertex);
tl[i]->push_back(tc);
}
-
- vertex = osg::Vec3(layer_span*(i-1)/2, layer_span,
+
+ vertex = osg::Vec3(layer_span*(i-1)/2, layer_span,
alt_diff * (sin((i+1)*mpi) - 2));
-
+
tc = osg::Vec2(layer_scale * (i+1)/4, layer_scale);
-
+
color = osg::Vec4(cloudColors[0], (i == 3) ? 0.0f : 0.15f );
-
+
cl[i]->push_back( color );
vl[i]->push_back( vertex );
tl[i]->push_back( tc );
-
+
osg::Geometry* geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
geometry->setVertexArray(vl[i].get());
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
- geometry->setColorArray(cl[i].get());
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setTexCoordArray(0, tl[i].get());
+ geometry->setColorArray(cl[i].get(), osg::Array::BIND_PER_VERTEX);
+ geometry->setTexCoordArray(0, tl[i].get(), osg::Array::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, vl[i]->size()));
layer[i] = new osg::Geode;
-
+
std::stringstream sstr;
sstr << "Cloud Layer (" << i << ")";
geometry->setName(sstr.str());
layer[i]->addDrawable(geometry);
layer_transform->addChild(layer[i].get());
}
-
+
//OSGFIXME: true
if ( layer_states[layer_coverage].valid() ) {
osg::CopyOp copyOp; // shallow copy
bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
double alt, double dt )
{
-
+
if (getCoverage() != SGCloudLayer::SG_CLOUD_CLEAR)
{
// combine p and asl (meters) to get translation offset
// Point3D zero_elev = current_view.get_cur_zero_elev();
T.makeTranslate( asl_offset );
- // printf(" Translated to %.2f %.2f %.2f\n",
+ // printf(" Translated to %.2f %.2f %.2f\n",
// zero_elev.x, zero_elev.y, zero_elev.z );
// Rotate to proper orientation
- // printf(" lon = %.2f lat = %.2f\n",
+ // printf(" lon = %.2f lat = %.2f\n",
// lon * SGD_RADIANS_TO_DEGREES,
// lat * SGD_RADIANS_TO_DEGREES);
LON.makeRotate(lon, osg::Vec3(0, 0, 1));
} else {
layer_root->setAllChildrenOff();
}
-
+
// now calculate update texture coordinates
SGGeod pos = SGGeod::fromRad(lon, lat);
}
double sp_dist = speed*dt;
-
-
+
+
if ( lon != last_pos.getLongitudeRad() || lat != last_pos.getLatitudeRad() || sp_dist != 0 ) {
- double course = SGGeodesy::courseDeg(last_pos, pos) * SG_DEGREES_TO_RADIANS,
+ double course = SGGeodesy::courseDeg(last_pos, pos) * SG_DEGREES_TO_RADIANS,
dist = SGGeodesy::distanceM(last_pos, pos);
// if start and dest are too close together,
}
void SGCloudLayer::set_enable3dClouds(bool enable) {
-
+
if (layer3D->isDefined3D() && enable) {
cloud_root->setChildValue(layer3D->getNode(), true);
cloud_root->setChildValue(layer_root.get(), false);
geom->setName("Dome Elements");
geom->setUseDisplayList(false);
geom->setVertexArray(dome_vl.get());
- geom->setColorArray(dome_cl.get());
- geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+ geom->setColorArray(dome_cl.get(), osg::Array::BIND_PER_VERTEX);
geom->setNormalBinding(osg::Geometry::BIND_OFF);
geom->addPrimitiveSet(domeElements);
geode->addDrawable(geom);
outer_diff = SGVec3f(0, 0, 0);
middle_diff = SGVec3f(0, 0, 0);
}
- // printf(" outer_red_param = %.2f outer_red_diff = %.2f\n",
+ // printf(" outer_red_param = %.2f outer_red_diff = %.2f\n",
// outer_red_param, outer_red_diff);
// calculate transition colors between sky and fog
// xglTranslatef( zero_elev.x(), zero_elev.y(), zero_elev.z() );
T.makeTranslate( toOsg(p) );
- // printf(" Translated to %.2f %.2f %.2f\n",
+ // printf(" Translated to %.2f %.2f %.2f\n",
// zero_elev.x, zero_elev.y, zero_elev.z );
// Rotate to proper orientation
// oursun.hxx -- model earth's sun
//
-// Written by Durk Talsma. Originally started October 1997, for distribution
-// with the FlightGear project. Version 2 was written in August and
-// September 1998. This code is based upon algorithms and data kindly
-// provided by Mr. Paul Schlyter. (pausch@saaf.se).
+// Written by Durk Talsma. Originally started October 1997, for distribution
+// with the FlightGear project. Version 2 was written in August and
+// September 1998. This code is based upon algorithms and data kindly
+// provided by Mr. Paul Schlyter. (pausch@saaf.se).
//
// Separated out rendering pieces and converted to ssg by Curt Olson,
// March 2000
osg::TexEnv* texEnv = new osg::TexEnv;
texEnv->setMode(osg::TexEnv::MODULATE);
stateSet->setTextureAttribute(0, texEnv, osg::StateAttribute::ON);
-
+
osg::Material* material = new osg::Material;
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1));
osg::Geometry* geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
geometry->setVertexArray(sun_vl);
- geometry->setColorArray(sun_cl.get());
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setColorArray(sun_cl.get(), osg::Array::BIND_OVERALL);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
- geometry->setTexCoordArray(0, sun_tl);
+ geometry->setTexCoordArray(0, sun_tl, osg::Array::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
geode->addDrawable(geometry);
geode = new osg::Geode;
stateSet = geode->getOrCreateStateSet();
stateSet->setRenderBinDetails(-7, "RenderBin");
-
+
texture = SGLoadTexture2D("inner_halo.png", options.get());
stateSet->setTextureAttributeAndModes(0, texture);
geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
geometry->setVertexArray(ihalo_vl);
- geometry->setColorArray(ihalo_cl.get());
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setColorArray(ihalo_cl.get(), osg::Array::BIND_OVERALL);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
- geometry->setTexCoordArray(0, ihalo_tl);
+ geometry->setTexCoordArray(0, ihalo_tl, osg::Array::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
geode->addDrawable(geometry);
sun_transform->addChild( geode );
-
+
// set up the outer halo state
-
+
geode = new osg::Geode;
stateSet = geode->getOrCreateStateSet();
stateSet->setRenderBinDetails(-8, "RenderBin");
geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
geometry->setVertexArray(ohalo_vl);
- geometry->setColorArray(ohalo_cl.get());
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setColorArray(ohalo_cl.get(), osg::Array::BIND_OVERALL);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
- geometry->setTexCoordArray(0, ohalo_tl);
+ geometry->setTexCoordArray(0, ohalo_tl, osg::Array::BIND_PER_VERTEX);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
geode->addDrawable(geometry);
density_avg = 0.7;
}
else {
- rel_humidity = env_node->getFloatValue( "relative-humidity" );
+ rel_humidity = env_node->getFloatValue( "relative-humidity" );
density_avg = env_node->getFloatValue( "atmosphere/density-tropo-avg" );
}
// ok, now let's go and generate the sun and scene color
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color;
- // Some comments:
+ // Some comments:
// * When the sunangle changes, light has to travel a longer
// distance through the atmosphere. So it's scattered more due
// to raleigh scattering, which affects blue more than green
// * Visability also affects suncolor inasmuch as more particles
// are in the air that cause more scattering.
// * We base our calculation on the halo's color, which is most
- // scattered.
+ // scattered.
double red_scat_f, red_scat_corr_f, green_scat_f, blue_scat_f;
-
- // Red - is almost not scattered
+
+ // Red - is almost not scattered
// Lambda is 700 nm
-
+
red_scat_f = (aerosol_factor * path_distance * density_avg)/5E+07;
red_scat_corr_f = sun_exp2_punch_through / (1 - red_scat_f);
sun_color[0] = 1;
green_scat_f = (aerosol_factor * path_distance * density_avg)/8.8938E+06;
sun_color[1] = 1 - green_scat_f * red_scat_corr_f;
scene_color[1] = 1 - green_scat_f;
-
+
// Blue - 435.8 nm
blue_scat_f = (aerosol_factor * path_distance * density_avg)/3.607E+06;
sun_color[2] = 1 - blue_scat_f * red_scat_corr_f;
sun_color[3] = 1;
scene_color[3] = 1;
- // Now that we have the color calculated
+ // Now that we have the color calculated
// let's consider the saturation which is produced by mie scattering
double saturation = 1 - ( rel_humidity / 200 );
scene_color[1] += (( 1 - saturation ) * ( 1 - scene_color[1] ));
gamma_correct_rgb( i_halo_color._v );
gamma_correct_rgb( o_halo_color._v );
- gamma_correct_rgb( scene_color._v );
+ gamma_correct_rgb( scene_color._v );
gamma_correct_rgb( sun_color._v );
(*sun_cl)[0] = sun_color;
// fixed at a great distance from the viewer. Also add in an optional
// rotation (i.e. for the current time of day.)
// Then calculate stuff needed for the sun-coloring
-bool SGSun::reposition( double rightAscension, double declination,
+bool SGSun::reposition( double rightAscension, double declination,
double sun_dist, double lat, double alt_asl, double sun_angle)
{
- // GST - GMT sidereal time
+ // GST - GMT sidereal time
osg::Matrix T2, RA, DEC;
// xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
double r_tropo = r_tropo_pole / sqrt ( 1 - ( epsilon_tropo2 * pow ( cos( lat ), 2 )));
double r_earth = r_earth_pole / sqrt ( 1 - ( epsilon_earth2 * pow ( cos( lat ), 2 )));
-
+
double position_radius = r_earth + alt_asl;
double gamma = SG_PI - sun_angle;
// Set the vertex, texture and normals. Colors will be set per-instance
// later.
sharedGeometry->setVertexArray(v);
- sharedGeometry->setTexCoordArray(0, t);
- sharedGeometry->setNormalArray(n);
-
- // Work around a bug in OSG 3.2.0 where BIND_PER_VERTEX appears
- // not to take effect if the normal array is set subsequently.
- sharedGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ sharedGeometry->setTexCoordArray(0, t, Array::BIND_PER_VERTEX);
+ sharedGeometry->setNormalArray(n, Array::BIND_PER_VERTEX);
}
}
Geometry* createNewBuildingGeometryInstance(const BuildingInstance& building) const
{
Geometry* geom = simgear::clone(building.sharedGeometry.get(), CopyOp::SHALLOW_COPY);
- geom->setColorArray(new Vec4Array);
- geom->setColorBinding(Geometry::BIND_PER_VERTEX);
+ geom->setColorArray(new Vec4Array, Array::BIND_PER_VERTEX);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS));
return geom;
}
}
Geometry* result = new Geometry;
result->setVertexArray(v);
- result->setTexCoordArray(0, t);
+ result->setTexCoordArray(0, t, Array::BIND_PER_VERTEX);
result->setComputeBoundingBoxCallback(new TreesBoundingBoxCallback);
result->setUseDisplayList(false);
return result;
LOD* operator() () const
{
LOD* result = new LOD;
-
+
// Create a series of LOD nodes so trees cover decreases slightly
// gradually with distance from _range to 2*_range
for (float i = 0.0; i < SG_TREE_FADE_OUT_LEVELS; i++)
- {
+ {
EffectGeode* geode = createTreeGeode(_width, _height, _varieties);
geode->setEffect(_effect.get());
result->addChild(geode, 0, _range * (1.0 + i / (SG_TREE_FADE_OUT_LEVELS - 1.0)));
for (i = forestList.begin(); i != forestList.end(); ++i) {
TreeBin* forest = *i;
-
+
ref_ptr<Effect> effect;
EffectMap::iterator iter = treeEffectMap.find(forest->texture);
for (size_t i = 0; i < group->getNumChildren(); ++i)
mt->addChild(group->getChild(i));
-
+
delete forest;
}
-
+
forestList.clear();
QuadTreeCleaner cleaner;
mt->accept(cleaner);
if (!_tileGeometryBin->vasiLights.empty()) {
EffectGeode* vasiGeode = new EffectGeode;
Effect* vasiEffect
- = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true);
+ = getLightEffect(24, osg::Vec3(1, 0.0001, 0.000001), 1, 24, true, _options);
vasiGeode->setEffect(vasiEffect);
SGVec4f red(1, 0, 0, 1);
SGMaterial* mat = 0;
|| !_tileGeometryBin->reilLights.empty()
|| !_tileGeometryBin->odalLights.empty()
|| _tileGeometryBin->taxiLights.getNumLights() > 0)
- runwayEffect = getLightEffect(16, osg::Vec3(1, 0.001, 0.0002), 1, 16, true);
+ runwayEffect = getLightEffect(16, osg::Vec3(1, 0.001, 0.0002), 1, 16, true, _options);
if (_tileGeometryBin->runwayLights.getNumLights() > 0
|| !_tileGeometryBin->rabitLights.empty()
|| !_tileGeometryBin->reilLights.empty()
SGDirectionalLightListBin::const_iterator i;
for (i = _tileGeometryBin->rabitLights.begin();
i != _tileGeometryBin->rabitLights.end(); ++i) {
- rwyLights->addChild(SGLightFactory::getSequenced(*i));
+ rwyLights->addChild(SGLightFactory::getSequenced(*i, _options));
}
for (i = _tileGeometryBin->reilLights.begin();
i != _tileGeometryBin->reilLights.end(); ++i) {
- rwyLights->addChild(SGLightFactory::getSequenced(*i));
+ rwyLights->addChild(SGLightFactory::getSequenced(*i, _options));
}
for (i = _tileGeometryBin->holdshortLights.begin();
i != _tileGeometryBin->holdshortLights.end(); ++i) {
- rwyLights->addChild(SGLightFactory::getHoldShort(*i));
+ rwyLights->addChild(SGLightFactory::getHoldShort(*i, _options));
}
for (i = _tileGeometryBin->guardLights.begin();
i != _tileGeometryBin->guardLights.end(); ++i) {
- rwyLights->addChild(SGLightFactory::getGuard(*i));
+ rwyLights->addChild(SGLightFactory::getGuard(*i, _options));
}
SGLightListBin::const_iterator j;
for (j = _tileGeometryBin->odalLights.begin();
j != _tileGeometryBin->odalLights.end(); ++j) {
- rwyLights->addChild(SGLightFactory::getOdal(*j));
+ rwyLights->addChild(SGLightFactory::getOdal(*j, _options));
}
lightGroup->addChild(rwyLights);
}
#include <osg/BlendFunc>
#include <osg/TexEnv>
#include <osg/Sequence>
-#include <osg/PolygonMode>
#include <osg/Fog>
#include <osg/FragmentProgram>
#include <osg/VertexProgram>
#include <osg/Point>
-#include <osg/PointSprite>
#include <osg/Material>
#include <osg/Group>
#include <osg/StateSet>
using namespace osg;
using namespace simgear;
-static void
-setPointSpriteImage(unsigned char* data, unsigned log2resolution,
- unsigned charsPerPixel)
-{
- int env_tex_res = (1 << log2resolution);
- for (int i = 0; i < env_tex_res; ++i) {
- for (int j = 0; j < env_tex_res; ++j) {
- int xi = 2*i + 1 - env_tex_res;
- int yi = 2*j + 1 - env_tex_res;
- if (xi < 0)
- xi = -xi;
- if (yi < 0)
- yi = -yi;
-
- xi -= 1;
- yi -= 1;
-
- if (xi < 0)
- xi = 0;
- if (yi < 0)
- yi = 0;
-
- float x = 1.5*xi/(float)(env_tex_res);
- float y = 1.5*yi/(float)(env_tex_res);
- // float x = 2*xi/(float)(env_tex_res);
- // float y = 2*yi/(float)(env_tex_res);
- float dist = sqrt(x*x + y*y);
- float bright = SGMiscf::clip(255*(1-dist), 0, 255);
- for (unsigned l = 0; l < charsPerPixel; ++l)
- data[charsPerPixel*(i*env_tex_res + j) + l] = (unsigned char)bright;
- }
- }
-}
-
-static osg::Image*
-getPointSpriteImage(int logResolution)
-{
- osg::Image* image = new osg::Image;
-
- osg::Image::MipmapDataType mipmapOffsets;
- unsigned off = 0;
- for (int i = logResolution; 0 <= i; --i) {
- unsigned res = 1 << i;
- off += res*res;
- mipmapOffsets.push_back(off);
- }
-
- int env_tex_res = (1 << logResolution);
-
- unsigned char* imageData = new unsigned char[off];
- image->setImage(env_tex_res, env_tex_res, 1,
- GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, imageData,
- osg::Image::USE_NEW_DELETE);
- image->setMipmapLevels(mipmapOffsets);
-
- for (int k = logResolution; 0 <= k; --k) {
- setPointSpriteImage(image->getMipmapData(logResolution - k), k, 1);
- }
-
- return image;
-}
-
static Mutex lightMutex;
-static osg::Texture2D*
-gen_standard_light_sprite(void)
-{
- // Always called from when the lightMutex is already taken
- static osg::ref_ptr<osg::Texture2D> texture;
- if (texture.valid())
- return texture.get();
-
- texture = new osg::Texture2D;
- texture->setImage(getPointSpriteImage(6));
- texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
- texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
-
- return texture.get();
-}
-
namespace
{
typedef boost::tuple<float, osg::Vec3, float, float, bool> PointParams;
typedef std::map<PointParams, observer_ptr<Effect> > EffectMap;
EffectMap effectMap;
-
-ref_ptr<PolygonMode> polyMode = new PolygonMode(PolygonMode::FRONT,
- PolygonMode::POINT);
-ref_ptr<PointSprite> pointSprite = new PointSprite;
}
Effect* getLightEffect(float size, const Vec3& attenuation,
- float minSize, float maxSize, bool directional)
+ float minSize, float maxSize, bool directional,
+ const SGReaderWriterOptions* options)
{
PointParams pointParams(size, attenuation, minSize, maxSize, directional);
ScopedLock<Mutex> lock(lightMutex);
+ ref_ptr<Effect> effect;
EffectMap::iterator eitr = effectMap.find(pointParams);
if (eitr != effectMap.end())
{
- 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");
- basicPass->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
- StateAttributeFactory *attrFact = StateAttributeFactory::instance();
- basicPass->setAttributeAndModes(attrFact->getStandardBlendFunc());
- basicPass->setAttributeAndModes(attrFact->getStandardAlphaFunc());
- if (directional) {
- basicPass->setAttributeAndModes(attrFact->getCullFaceBack());
- basicPass->setAttribute(polyMode.get());
- }
- Pass *attenuationPass = clone(basicPass, CopyOp::SHALLOW_COPY);
- osg::Point* point = new osg::Point;
- point->setMinSize(minSize);
- point->setMaxSize(maxSize);
- point->setSize(size);
- point->setDistanceAttenuation(attenuation);
- attenuationPass->setAttributeAndModes(point);
- Pass *spritePass = clone(basicPass, CopyOp::SHALLOW_COPY);
- spritePass->setTextureAttributeAndModes(0, pointSprite.get(),
- osg::StateAttribute::ON);
- Texture2D* texture = gen_standard_light_sprite();
- spritePass->setTextureAttribute(0, texture);
- spritePass->setTextureMode(0, GL_TEXTURE_2D,
- osg::StateAttribute::ON);
- spritePass->setTextureAttribute(0, attrFact->getStandardTexEnv());
- Pass *combinedPass = clone(spritePass, CopyOp::SHALLOW_COPY);
- combinedPass->setAttributeAndModes(point);
- ref_ptr<Effect> effect = new Effect;
- std::vector<std::string> parameterExtensions;
-
- 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);
- effect->techniques.push_back(parameterTniq);
- Technique* basicTniq = new Technique(true);
- basicTniq->passes.push_back(basicPass);
- effect->techniques.push_back(basicTniq);
+ SGPropertyNode_ptr effectProp = new SGPropertyNode;
+ makeChild(effectProp, "inherits-from")->setStringValue("Effects/surface-lights");
+
+ SGPropertyNode* params = makeChild(effectProp, "parameters");
+ params->getNode("size",true)->setValue(size);
+ params->getNode("attenuation",true)->getNode("x", true)->setValue(attenuation.x());
+ params->getNode("attenuation",true)->getNode("y", true)->setValue(attenuation.y());
+ params->getNode("attenuation",true)->getNode("z", true)->setValue(attenuation.z());
+ params->getNode("min-size",true)->setValue(minSize);
+ params->getNode("max-size",true)->setValue(maxSize);
+ params->getNode("cull-face",true)->setValue(directional ? "back" : "off");
+
+ effect = makeEffect(effectProp, true, options);
+
if (eitr == effectMap.end())
effectMap.insert(std::make_pair(pointParams, effect));
else
vertices->push_back(toOsg(light.position));
colors->push_back(toOsg(light.color));
-
+
osg::Geometry* geometry = new osg::Geometry;
geometry->setDataVariance(osg::Object::STATIC);
geometry->setVertexArray(vertices);
// Enlarge the bounding box to avoid such light nodes being victim to
// small feature culling.
geometry->setComputeBoundingBoxCallback(new SGEnlargeBoundingBox(1));
-
+
osg::DrawArrays* drawArrays;
drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
0, vertices->size());
colors->push_back(toOsg(visibleColor));
colors->push_back(toOsg(invisibleColor));
colors->push_back(toOsg(invisibleColor));
-
+
osg::Geometry* geometry = new osg::Geometry;
geometry->setDataVariance(osg::Object::STATIC);
geometry->setVertexArray(vertices);
// Enlarge the bounding box to avoid such light nodes being victim to
// small feature culling.
geometry->setComputeBoundingBoxCallback(new SGEnlargeBoundingBox(1));
-
+
osg::DrawArrays* drawArrays;
drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
0, vertices->size());
{
if (lights.getNumLights() <= 0)
return 0;
-
+
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec4Array* colors = new osg::Vec4Array;
color[3] = SGMiscf::max(0, SGMiscf::min(1, color[3] + alphaOff));
colors->push_back(toOsg(color));
}
-
+
osg::Geometry* geometry = new osg::Geometry;
geometry->setDataVariance(osg::Object::STATIC);
geometry->setVertexArray(vertices);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
-
+
osg::DrawArrays* drawArrays;
drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
0, vertices->size());
{
if (lights.getNumLights() <= 0)
return 0;
-
+
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(toOsg(invisibleColor));
colors->push_back(toOsg(invisibleColor));
}
-
+
osg::Geometry* geometry = new osg::Geometry;
geometry->setDataVariance(osg::Object::STATIC);
geometry->setVertexArray(vertices);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
-
+
osg::DrawArrays* drawArrays;
drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
0, vertices->size());
} else if (count == 12) {
SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
-
+
// probably vasi, first 6 are downwind bar (2.5 deg)
for (unsigned i = 0; i < 6; ++i)
drawable->addLight(lights.getLight(i).position,
osg::BlendFunc* blendFunc = new osg::BlendFunc;
stateSet->setAttribute(blendFunc);
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-
+
osg::AlphaFunc* alphaFunc;
alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
stateSet->setAttribute(alphaFunc);
}
osg::Node*
-SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
+SGLightFactory::getSequenced(const SGDirectionalLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() <= 0)
return 0;
osg::Sequence* sequence = new osg::Sequence;
sequence->setDefaultTime(flashTime);
Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
- 6.0f, 10.0f, true);
+ 6.0f, 10.0f, true, options);
for (int i = lights.getNumLights() - 1; 0 <= i; --i) {
EffectGeode* egeode = new EffectGeode;
egeode->setEffect(effect);
}
osg::Node*
-SGLightFactory::getOdal(const SGLightBin& lights)
+SGLightFactory::getOdal(const SGLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() < 2)
return 0;
osg::Sequence* sequence = new osg::Sequence;
sequence->setDefaultTime(flashTime);
Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.0001, 0.00000001),
- 6.0, 10.0, false);
+ 6.0, 10.0, false, options);
// centerline lights
for (int i = lights.getNumLights(); i > 1; --i) {
EffectGeode* egeode = new EffectGeode;
// Blinking hold short line lights
osg::Node*
-SGLightFactory::getHoldShort(const SGDirectionalLightBin& lights)
+SGLightFactory::getHoldShort(const SGDirectionalLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() < 2)
return 0;
// ...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.0f, i, true);
+ 0.0f, i, true, options);
EffectGeode* egeode = new EffectGeode;
for (unsigned int j = 0; j < lights.getNumLights(); ++j) {
egeode->addDrawable(getLightDrawable(lights.getLight(j)));
// Alternating runway guard lights ("wig-wag")
osg::Node*
-SGLightFactory::getGuard(const SGDirectionalLightBin& lights)
+SGLightFactory::getGuard(const SGDirectionalLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() < 2)
return 0;
osg::Sequence* sequence = new osg::Sequence;
sequence->setDefaultTime(flashTime);
Effect* effect = getLightEffect(10.0f, osg::Vec3(1.0, 0.001, 0.000002),
- 0.0f, 8.0f, true);
+ 0.0f, 8.0f, true, options);
for (unsigned int i = 0; i < lights.getNumLights(); ++i) {
EffectGeode* egeode = new EffectGeode;
egeode->setEffect(effect);
#include <simgear/math/sg_types.hxx>
#include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/util/SGSceneFeatures.hxx>
#include "SGLightBin.hxx"
const SGVec4f& red, const SGVec4f& white);
static osg::Node*
- getSequenced(const SGDirectionalLightBin& lights);
+ getSequenced(const SGDirectionalLightBin& lights, const simgear::SGReaderWriterOptions* options);
static osg::Node*
- getOdal(const SGLightBin& lights);
+ getOdal(const SGLightBin& lights, const simgear::SGReaderWriterOptions* options);
static osg::Node*
- getHoldShort(const SGDirectionalLightBin& lights);
+ getHoldShort(const SGDirectionalLightBin& lights, const simgear::SGReaderWriterOptions* options);
static osg::Node*
- getGuard(const SGDirectionalLightBin& lights);
+ getGuard(const SGDirectionalLightBin& lights, const simgear::SGReaderWriterOptions* options);
};
simgear::Effect* getLightEffect(float size, const osg::Vec3& attenuation,
- float minSize, float maxSize, bool directional);
+ float minSize, float maxSize, bool directional,
+ const simgear::SGReaderWriterOptions* options);
#endif // _SG_PT_LIGHTS_HXX