From: Stuart Buchanan Date: Tue, 18 Feb 2014 21:30:15 +0000 (+0000) Subject: OSG 3.2.0 compatibility and surface light effects. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=c35243e215ef0a03061948fd9c45e1112f98cdf4;p=simgear.git OSG 3.2.0 compatibility and surface light effects. --- diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index d86c7115..28526389 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -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); diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index 17b02a65..7d961af4 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -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 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 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 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() ? + pass->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, (realProp->getValue() ? 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 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 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 +installPoint("point"); + EffectNameValue depthFunctionInit[] = { {"never", Depth::NEVER}, @@ -1359,17 +1406,17 @@ class PropertyExpression : public SGExpression { public: PropertyExpression(SGPropertyNode* pnode) : _pnode(pnode), _listener(NULL) {} - + ~PropertyExpression() { delete _listener; } - + void eval(T& value, const expression::Binding*) const { value = _pnode->getValue(); } - + 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 _tniq; }; diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index ab5bbe03..0c0dfe48 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -23,6 +23,7 @@ #include "Pass.hxx" +#include #include #include #include @@ -34,6 +35,9 @@ #include #include +#include +#include + #include #include #include @@ -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 = 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 image; @@ -305,7 +321,7 @@ Texture* TexBuilder::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 lock(lightMutex); + + // Always called from when the lightMutex is already taken + static osg::ref_ptr 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 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; rowgetWhiteTexture(), 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); diff --git a/simgear/scene/sky/dome.cxx b/simgear/scene/sky/dome.cxx index 50dbe33b..01e8beeb 100644 --- a/simgear/scene/sky/dome.cxx +++ b/simgear/scene/sky/dome.cxx @@ -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 diff --git a/simgear/scene/sky/oursun.cxx b/simgear/scene/sky/oursun.cxx index f959200c..a267034f 100644 --- a/simgear/scene/sky/oursun.cxx +++ b/simgear/scene/sky/oursun.cxx @@ -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; diff --git a/simgear/scene/tgdb/SGBuildingBin.cxx b/simgear/scene/tgdb/SGBuildingBin.cxx index 042c56f6..30fc34a9 100644 --- a/simgear/scene/tgdb/SGBuildingBin.cxx +++ b/simgear/scene/tgdb/SGBuildingBin.cxx @@ -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); } } diff --git a/simgear/scene/tgdb/SGBuildingBin.hxx b/simgear/scene/tgdb/SGBuildingBin.hxx index 23d47fcb..890dff98 100644 --- a/simgear/scene/tgdb/SGBuildingBin.hxx +++ b/simgear/scene/tgdb/SGBuildingBin.hxx @@ -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; } diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index accac411..9b8aa3bc 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -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; 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); diff --git a/simgear/scene/tgdb/obj.cxx b/simgear/scene/tgdb/obj.cxx index edb35f26..4a9d8b59 100644 --- a/simgear/scene/tgdb/obj.cxx +++ b/simgear/scene/tgdb/obj.cxx @@ -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); } diff --git a/simgear/scene/tgdb/pt_lights.cxx b/simgear/scene/tgdb/pt_lights.cxx index eb8dd048..d6374b6f 100644 --- a/simgear/scene/tgdb/pt_lights.cxx +++ b/simgear/scene/tgdb/pt_lights.cxx @@ -41,12 +41,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -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 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 PointParams; typedef std::map > EffectMap; EffectMap effectMap; - -ref_ptr polyMode = new PolygonMode(PolygonMode::FRONT, - PolygonMode::POINT); -ref_ptr 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 lock(lightMutex); + ref_ptr effect; EffectMap::iterator eitr = effectMap.find(pointParams); if (eitr != effectMap.end()) { - ref_ptr 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 = new Effect; - std::vector parameterExtensions; - - if (SGSceneFeatures::instance()->getEnablePointSpriteLights()) - { - std::vector 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 spriteExtensions; - spriteExtensions.push_back(combinedExtensions.front()); - Technique* spriteTniq = new Technique; - spriteTniq->passes.push_back(spritePass); - spriteTniq->setGLExtensionsPred(2.0, spriteExtensions); - effect->techniques.push_back(spriteTniq); - parameterExtensions.push_back(combinedExtensions.back()); - } - Technique* parameterTniq = new Technique; - parameterTniq->passes.push_back(attenuationPass); - parameterTniq->setGLExtensionsPred(1.4, parameterExtensions); - effect->techniques.push_back(parameterTniq); - Technique* basicTniq = new Technique(true); - basicTniq->passes.push_back(basicPass); - effect->techniques.push_back(basicTniq); + SGPropertyNode_ptr effectProp = new SGPropertyNode; + makeChild(effectProp, "inherits-from")->setStringValue("Effects/surface-lights"); + + SGPropertyNode* params = makeChild(effectProp, "parameters"); + params->getNode("size",true)->setValue(size); + params->getNode("attenuation",true)->getNode("x", true)->setValue(attenuation.x()); + params->getNode("attenuation",true)->getNode("y", true)->setValue(attenuation.y()); + params->getNode("attenuation",true)->getNode("z", true)->setValue(attenuation.z()); + params->getNode("min-size",true)->setValue(minSize); + params->getNode("max-size",true)->setValue(maxSize); + params->getNode("cull-face",true)->setValue(directional ? "back" : "off"); + + effect = makeEffect(effectProp, true, options); + if (eitr == effectMap.end()) effectMap.insert(std::make_pair(pointParams, effect)); else @@ -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); diff --git a/simgear/scene/tgdb/pt_lights.hxx b/simgear/scene/tgdb/pt_lights.hxx index bbe28ad7..863328dc 100644 --- a/simgear/scene/tgdb/pt_lights.hxx +++ b/simgear/scene/tgdb/pt_lights.hxx @@ -40,6 +40,7 @@ #include #include +#include #include #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