OSG 3.2.0 compatibility and surface light effects.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user