OSG 3.2.0 compatibility and surface light effects.

This commit is contained in:
Stuart Buchanan
2014-02-18 21:30:15 +00:00
parent 00d8849a28
commit c35243e215
12 changed files with 315 additions and 289 deletions

View File

@@ -128,12 +128,11 @@ namespace canvas
_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);

View File

@@ -48,6 +48,7 @@
#include <osg/Math>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/Point>
#include <osg/Program>
#include <osg/Referenced>
#include <osg/RenderInfo>
@@ -265,8 +266,8 @@ struct CullFaceBuilder : PassAttributeBuilder
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");
@@ -284,7 +285,7 @@ struct ColorMaskBuilder : PassAttributeBuilder
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");
@@ -309,7 +310,7 @@ struct HintBuilder : public PassAttributeBuilder
StateSet::RenderingHint renderingHint = StateSet::DEFAULT_BIN;
findAttr(renderingHints, realProp, renderingHint);
pass->setRenderingHint(renderingHint);
}
}
};
InstallAttributeBuilder<HintBuilder> installHint("rendering-hint");
@@ -387,9 +388,9 @@ void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
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")))
@@ -538,7 +539,7 @@ struct StencilBuilder : public PassAttributeBuilder
findAttr(stencilFunction, pfunction, func);
if (pvalue)
ref = pvalue->getIntValue();
if (pmask)
if (pmask)
mask = pmask->getIntValue();
if (psfail)
@@ -578,7 +579,7 @@ void AlphaToCoverageBuilder::buildAttribute(Effect* effect, Pass* pass,
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));
}
@@ -1062,19 +1063,19 @@ struct PolygonOffsetBuilder : public PassAttributeBuilder
{
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);
@@ -1117,6 +1118,52 @@ struct VertexProgramPointSizeBuilder : public PassAttributeBuilder
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},
@@ -1359,17 +1406,17 @@ class PropertyExpression : public SGExpression<T>
{
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;
@@ -1383,15 +1430,15 @@ class EffectPropertyListener : public SGPropertyChangeListener
{
public:
EffectPropertyListener(Technique* tniq) : _tniq(tniq) {}
void valueChanged(SGPropertyNode* node)
{
if (_tniq.valid())
_tniq->refreshValidity();
}
virtual ~EffectPropertyListener() { }
protected:
osg::observer_ptr<Technique> _tniq;
};

View File

@@ -23,6 +23,7 @@
#include "Pass.hxx"
#include <osg/PointSprite>
#include <osg/TexEnv>
#include <osg/TexEnvCombine>
#include <osg/TexGen>
@@ -34,6 +35,9 @@
#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>
@@ -47,6 +51,10 @@
namespace simgear
{
using OpenThreads::Mutex;
using OpenThreads::ScopedLock;
using namespace std;
using namespace osg;
@@ -138,7 +146,15 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
<< "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);
@@ -225,7 +241,7 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
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);
@@ -237,9 +253,9 @@ bool setAttrs(const TexTuple& attrs, Texture* tex,
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;
@@ -305,7 +321,7 @@ Texture* TexBuilder<T>::build(Effect* effect, Pass* pass, const SGPropertyNode*
tex = new T;
if (!setAttrs(attrs, tex, options))
return NULL;
if (itr == texMap.end())
texMap.insert(make_pair(attrs, tex));
else
@@ -385,7 +401,103 @@ namespace
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;
@@ -430,7 +542,7 @@ protected:
// 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)

View File

@@ -194,7 +194,7 @@ SGCloudLayer::SGCloudLayer( const string &tex_path ) :
->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();
@@ -319,7 +319,7 @@ SGCloudLayer::getCoverageString( Coverage coverage )
}
}
SGCloudLayer::Coverage
SGCloudLayer::Coverage
SGCloudLayer::getCoverageType( const std::string & coverage )
{
if( SG_CLOUD_OVERCAST_STRING == coverage ) {
@@ -374,14 +374,14 @@ void
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/
@@ -407,7 +407,7 @@ SGCloudLayer::rebuild()
-( 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 );
@@ -424,7 +424,7 @@ SGCloudLayer::rebuild()
( 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 );
@@ -441,7 +441,7 @@ SGCloudLayer::rebuild()
( 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 );
@@ -475,7 +475,7 @@ SGCloudLayer::rebuild()
-( 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 );
@@ -504,23 +504,23 @@ SGCloudLayer::rebuild()
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
@@ -545,8 +545,8 @@ SGCloudLayer::rebuild()
// 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.
@@ -555,38 +555,38 @@ SGCloudLayer::rebuild()
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 );
@@ -597,28 +597,27 @@ SGCloudLayer::rebuild()
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());
@@ -626,7 +625,7 @@ SGCloudLayer::rebuild()
layer[i]->addDrawable(geometry);
layer_transform->addChild(layer[i].get());
}
//OSGFIXME: true
if ( layer_states[layer_coverage].valid() ) {
osg::CopyOp copyOp; // shallow copy
@@ -661,7 +660,7 @@ bool SGCloudLayer::repaint( const SGVec3f& fog_color ) {
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
@@ -684,11 +683,11 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
// 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));
@@ -716,7 +715,7 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
} else {
layer_root->setAllChildrenOff();
}
// now calculate update texture coordinates
SGGeod pos = SGGeod::fromRad(lon, lat);
@@ -725,10 +724,10 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
}
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,
@@ -804,7 +803,7 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
}
void SGCloudLayer::set_enable3dClouds(bool enable) {
if (layer3D->isDefined3D() && enable) {
cloud_root->setChildValue(layer3D->getNode(), true);
cloud_root->setChildValue(layer_root.get(), false);

View File

@@ -216,8 +216,7 @@ SGSkyDome::build( double hscale, double vscale, simgear::SGReaderWriterOptions *
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);
@@ -272,7 +271,7 @@ SGSkyDome::repaint( const SGVec3f& sun_color, const SGVec3f& sky_color,
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
@@ -381,7 +380,7 @@ SGSkyDome::reposition( const SGVec3f& p, double _asl,
// 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

View File

@@ -1,9 +1,9 @@
// 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
@@ -79,7 +79,7 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
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));
@@ -135,10 +135,9 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
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);
@@ -148,7 +147,7 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
geode = new osg::Geode;
stateSet = geode->getOrCreateStateSet();
stateSet->setRenderBinDetails(-7, "RenderBin");
texture = SGLoadTexture2D("inner_halo.png", options.get());
stateSet->setTextureAttributeAndModes(0, texture);
@@ -172,17 +171,16 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
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");
@@ -210,10 +208,9 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
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);
@@ -260,14 +257,14 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
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
@@ -277,12 +274,12 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
// * 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;
@@ -292,7 +289,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
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;
@@ -302,7 +299,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
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] ));
@@ -341,7 +338,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
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;
@@ -363,10 +360,10 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
// 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),
@@ -391,7 +388,7 @@ bool SGSun::reposition( double rightAscension, double declination,
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;

View File

@@ -635,12 +635,8 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
// 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);
}
}

View File

@@ -233,8 +233,7 @@ public:
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;
}

View File

@@ -143,7 +143,7 @@ Geometry* makeSharedTreeGeometry(int numQuads)
}
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;
@@ -232,11 +232,11 @@ struct MakeTreesLeaf
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)));
@@ -335,7 +335,7 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
for (i = forestList.begin(); i != forestList.end(); ++i) {
TreeBin* forest = *i;
ref_ptr<Effect> effect;
EffectMap::iterator iter = treeEffectMap.find(forest->texture);
@@ -374,10 +374,10 @@ osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform
for (size_t i = 0; i < group->getNumChildren(); ++i)
mt->addChild(group->getChild(i));
delete forest;
}
forestList.clear();
QuadTreeCleaner cleaner;
mt->accept(cleaner);

View File

@@ -950,7 +950,7 @@ public:
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;
@@ -979,7 +979,7 @@ public:
|| !_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()
@@ -998,24 +998,24 @@ public:
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);
}

View File

@@ -41,12 +41,10 @@
#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>
@@ -76,166 +74,44 @@ using OpenThreads::ScopedLock;
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());
}
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);
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);
if (eitr == effectMap.end())
effectMap.insert(std::make_pair(pointParams, effect));
else
@@ -252,7 +128,7 @@ SGLightFactory::getLightDrawable(const SGLightBin::Light& light)
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);
@@ -263,7 +139,7 @@ SGLightFactory::getLightDrawable(const SGLightBin::Light& light)
// 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());
@@ -290,7 +166,7 @@ SGLightFactory::getLightDrawable(const SGDirectionalLightBin::Light& light)
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);
@@ -300,7 +176,7 @@ SGLightFactory::getLightDrawable(const SGDirectionalLightBin::Light& light)
// 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());
@@ -317,7 +193,7 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff
{
if (lights.getNumLights() <= 0)
return 0;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec4Array* colors = new osg::Vec4Array;
@@ -327,14 +203,14 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff
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());
@@ -361,7 +237,7 @@ SGLightFactory::getLights(const SGDirectionalLightBin& lights)
{
if (lights.getNumLights() <= 0)
return 0;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec4Array* colors = new osg::Vec4Array;
@@ -380,14 +256,14 @@ SGLightFactory::getLights(const SGDirectionalLightBin& lights)
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());
@@ -433,7 +309,7 @@ buildVasi(const SGDirectionalLightBin& lights, const SGVec3f& up,
} 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,
@@ -467,7 +343,7 @@ SGLightFactory::getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
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);
@@ -477,7 +353,7 @@ SGLightFactory::getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
}
osg::Node*
SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
SGLightFactory::getSequenced(const SGDirectionalLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() <= 0)
return 0;
@@ -488,7 +364,7 @@ SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
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);
@@ -504,7 +380,7 @@ SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
}
osg::Node*
SGLightFactory::getOdal(const SGLightBin& lights)
SGLightFactory::getOdal(const SGLightBin& lights, const SGReaderWriterOptions* options)
{
if (lights.getNumLights() < 2)
return 0;
@@ -515,7 +391,7 @@ SGLightFactory::getOdal(const SGLightBin& lights)
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;
@@ -545,7 +421,7 @@ SGLightFactory::getOdal(const SGLightBin& lights)
// 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;
@@ -559,7 +435,7 @@ SGLightFactory::getHoldShort(const SGDirectionalLightBin& lights)
// ...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)));
@@ -577,7 +453,7 @@ SGLightFactory::getHoldShort(const SGDirectionalLightBin& lights)
// 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;
@@ -588,7 +464,7 @@ SGLightFactory::getGuard(const SGDirectionalLightBin& lights)
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);

View File

@@ -40,6 +40,7 @@
#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"
@@ -85,18 +86,19 @@ public:
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