From 75271c44a82ae0fb1ff9c91e93a12fa8b10099fd Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Tue, 21 Oct 2014 10:44:13 +0200 Subject: [PATCH] Precipitation updates from ThorstenR Since the consensus seems to be that the precipitation clipping issue is with the panel code, attached is my proposed update for the precipitation system in SG and FG * without corresponding control structures in FGData it falls back to default, except I have fixed an inconsistency in freezing behavior - previously rain changed suddenly to snow when the temperature dropped below zero, but the reverse transition was dragged out and gave odd visible motion with the wind as snow gradually changed back to rain with the particle speed not well defined. Now both transitions are sudden. And I see no more particles flow against the wind * with 0.015 0.03 false 1.0 5.0 added to Environment/environment.xml, the new system allows to switch more detailed management on. This provides * explicit setting of rain droplet size and snow flake size by the weather system * automatic sqrt(r) scaling of the vertical speed of raindrops * automatic transition to snow when freezing for small droplets but hail for large droplet sizes (looks like snow, but has different particle dynamics) * an illumination scaling factor to dim the precipitating based on the light we have in the scene (I still need to devise a property rule to set this automatically) The clip distance is also exposed now and considered at startup of the system - might be useful for e.g. airships when the gas bag provides rain cover (?) or to be simply off for open airplanes --- simgear/environment/precipitation.cxx | 132 ++++++++++++++++++++++---- simgear/environment/precipitation.hxx | 9 ++ 2 files changed, 125 insertions(+), 16 deletions(-) diff --git a/simgear/environment/precipitation.cxx b/simgear/environment/precipitation.cxx index 073c06d8..8ffa2210 100644 --- a/simgear/environment/precipitation.cxx +++ b/simgear/environment/precipitation.cxx @@ -37,7 +37,7 @@ * Build a new OSG object from osgParticle. */ SGPrecipitation::SGPrecipitation() : - _freeze(false), _enabled(true), _snow_intensity(0.0), _rain_intensity(0.0), _clip_distance(5.0) + _freeze(false), _enabled(true), _droplet_external(false), _snow_intensity(0.0), _rain_intensity(0.0), _clip_distance(5.0), _rain_droplet_size(0.0), _snow_flake_size(0.0), _illumination(1.0) { _precipitationEffect = new osgParticle::PrecipitationEffect; } @@ -47,6 +47,11 @@ void SGPrecipitation::setEnabled( bool value ) _enabled = value; } +void SGPrecipitation::setDropletExternal( bool value ) +{ + _droplet_external = value; +} + bool SGPrecipitation::getEnabled() const { return _enabled; @@ -66,7 +71,7 @@ osg::Group* SGPrecipitation::build(void) _precipitationEffect->rain(0); if (_clip_distance!=0.0) - { + { osg::ref_ptr clipNode = new osg::ClipNode; clipNode->addClipPlane( new osg::ClipPlane( 0 ) ); clipNode->getClipPlane(0)->setClipPlane( 0.0, 0.0, -1.0, -_clip_distance ); @@ -119,17 +124,72 @@ void SGPrecipitation::setRainIntensity(float intensity) this->_rain_intensity = intensity; } +/** + * @brief Define the rain droplet size + * + * This function permits you to define and change the rain droplet size + * which is used if external droplet size control is enabled + */ + +void SGPrecipitation::setRainDropletSize(float size) +{ + _rain_droplet_size = size; +} + -/** +/** + * @brief Define the illumination multiplier + * + * This function permits you to define and change the rain droplet size + * which is used if external droplet size control is enabled + */ + +void SGPrecipitation::setIllumination(float illumination) +{ + _illumination = illumination; +} + +/** + * @brief Define the snow flake size + * + * This function permits you to define and change the snow flake size + * which is used if external droplet size control is enabled + */ + +void SGPrecipitation::setSnowFlakeSize(float size) +{ + _snow_flake_size = size; +} + + +/** + * @brief Define the rain droplet size + * + * This function permits you to define and change the rain droplet size + * which is used if external droplet size control is enabled + */ + +void SGPrecipitation::setClipDistance(float distance) +{ + _clip_distance = distance; +} + +/** * @brief Freeze the rain to snow - * - * @param freeze Boolean - * + * + * @param freeze Boolean + * * This function permits you to turn off the rain to snow. */ void SGPrecipitation::setFreezing(bool freeze) { + if ((this->_freeze)&&(!freeze)) // rain freezes suddenly, so we need to unfreeze + { + this->_rain_intensity = this->_snow_intensity; + this->_snow_intensity = 0.0; + } this->_freeze = freeze; + } @@ -137,7 +197,7 @@ void SGPrecipitation::setFreezing(bool freeze) * @brief Define the wind direction and speed * * This function permits you to define and change the wind direction - * + * * After apply the MatrixTransform to the osg::Precipitation object, * x points full south... From wind heading and speed, we can calculate * the wind vector. @@ -169,34 +229,74 @@ void SGPrecipitation::setWindProperty(double heading, double speed) bool SGPrecipitation::update(void) { if (this->_freeze) { - if (this->_rain_intensity > 0) - this->_snow_intensity = this->_rain_intensity; + if (this->_rain_intensity > 0) { + this->_snow_intensity = this->_rain_intensity; + } } if (_enabled && this->_snow_intensity > 0) { _precipitationEffect->setWind(_wind_vec); - _precipitationEffect->setParticleSpeed( -0.75f - 0.25f*_snow_intensity); + - _precipitationEffect->setParticleSize(0.02f + 0.03f*_snow_intensity); - _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 7.2f); + if(_droplet_external) + { + + if ((_freeze) && (_rain_droplet_size > 0.03)) // this is hail or sleet + { + _precipitationEffect->setParticleSize(_rain_droplet_size*1.5f); + _precipitationEffect->setParticleSpeed( -1.0f - 22.36f*sqrtf(_rain_droplet_size)); + _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 4.8f); + } + else if (_freeze) // this is snow from frozen small rain droplets + { + _precipitationEffect->setParticleSize(_rain_droplet_size*1.3f); + _precipitationEffect->setParticleSpeed( -0.75f - 0.25f*_snow_intensity); + _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 10.0f); + } + else // this was snow in the first place + { + _precipitationEffect->setParticleSize(_snow_flake_size); + _precipitationEffect->setParticleSpeed( -0.75f - 0.25f*_snow_intensity); + _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 7.2f); + } + } + else + { + _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 7.2f); + _precipitationEffect->setParticleSize(0.02f + 0.03f*_snow_intensity); + _precipitationEffect->setParticleSpeed( -0.75f - 0.25f*_snow_intensity); + } + + _precipitationEffect->setCellSize(osg::Vec3(5.0f / (0.25f+_snow_intensity), 5.0f / (0.25f+_snow_intensity), 5.0f)); _precipitationEffect->setNearTransition(25.f); _precipitationEffect->setFarTransition(100.0f - 60.0f*sqrtf(_snow_intensity)); - _precipitationEffect->setParticleColor(osg::Vec4(0.85, 0.85, 0.85, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0) * _snow_intensity); + _precipitationEffect->setParticleColor(osg::Vec4(0.85 * _illumination, 0.85 * _illumination, 0.85 * _illumination, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0) * _snow_intensity); } else if (_enabled && this->_rain_intensity > 0) { + _precipitationEffect->setWind(_wind_vec); - _precipitationEffect->setParticleSpeed( -2.0f + -5.0f*_rain_intensity); + + + if(_droplet_external) + { + _precipitationEffect->setParticleSize(_rain_droplet_size); + _precipitationEffect->setParticleSpeed( -1.0f - 22.36f*sqrtf(_rain_droplet_size)); + } + else + { + _precipitationEffect->setParticleSize(0.01 + 0.02*_rain_intensity); + _precipitationEffect->setParticleSpeed( -2.0f + -5.0f*_rain_intensity); + } - _precipitationEffect->setParticleSize(0.01 + 0.02*_rain_intensity); _precipitationEffect->setMaximumParticleDensity(_rain_intensity * 7.5f); _precipitationEffect->setCellSize(osg::Vec3(5.0f / (0.25f+_rain_intensity), 5.0f / (0.25f+_rain_intensity), 5.0f)); _precipitationEffect->setNearTransition(25.f); _precipitationEffect->setFarTransition(100.0f - 60.0f*sqrtf(_rain_intensity)); - _precipitationEffect->setParticleColor( osg::Vec4(0x7A, 0xCE, 0xFF, 0x80)); + _precipitationEffect->setParticleColor( osg::Vec4(0.64 * _illumination, 0.64 * _illumination, 0.64 * _illumination, 0.5)); } else { _precipitationEffect->snow(0); _precipitationEffect->rain(0); diff --git a/simgear/environment/precipitation.hxx b/simgear/environment/precipitation.hxx index 363137e9..fb3e2b59 100644 --- a/simgear/environment/precipitation.hxx +++ b/simgear/environment/precipitation.hxx @@ -37,10 +37,14 @@ class SGPrecipitation : public osg::Referenced private: bool _freeze; bool _enabled; + bool _droplet_external; float _snow_intensity; float _rain_intensity; float _clip_distance; + float _rain_droplet_size; + float _snow_flake_size; + float _illumination; osg::Vec3 _wind_vec; @@ -54,8 +58,13 @@ public: void setWindProperty(double, double); void setFreezing(bool); + void setDropletExternal(bool); void setRainIntensity(float); void setSnowIntensity(float); + void setRainDropletSize(float); + void setSnowFlakeSize(float); + void setIllumination(float); + void setClipDistance(float); void setEnabled( bool ); bool getEnabled() const; -- 2.39.5