Files
simgear/simgear/environment/precipitation.cxx
T
Torsten Dreyer 75271c44a8 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

 <!-- definitions for the detailed precipitation manager -->
 <precipitation-control>
     <rain-droplet-size type="float" userarchive="n">0.015</rain-droplet-size>
     <snow-flake-size type="float" userarchive="n">0.03</snow-flake-size>
     <detailed-precipitation type="bool" userarchive="n">false</detailed-precipitation>
     <illumination type="float" userarchive="n">1.0</illumination>
     <clip-distance type="float" userarchive="n">5.0</clip-distance>
  </precipitation-control>

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
2014-10-21 10:46:48 +02:00

307 lines
8.7 KiB
C++

/**
* @file precipitation.cxx
* @author Nicolas VIVIEN
* @date 2008-02-10
*
* @note Copyright (C) 2008 Nicolas VIVIEN
*
* @brief Precipitation effects to draw rain and snow.
*
* @par Licences
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "precipitation.hxx"
//#include "visual_enviro.hxx"
#include <simgear/constants.h>
#include <osg/ClipNode>
#include <simgear/scene/util/RenderConstants.hxx>
/**
* @brief SGPrecipitation constructor
*
* Build a new OSG object from osgParticle.
*/
SGPrecipitation::SGPrecipitation() :
_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;
}
void SGPrecipitation::setEnabled( bool value )
{
_enabled = value;
}
void SGPrecipitation::setDropletExternal( bool value )
{
_droplet_external = value;
}
bool SGPrecipitation::getEnabled() const
{
return _enabled;
}
/**
* @brief Build and add the object "precipitationEffect"
*
* This function permits you to create an object precipitationEffect and initialize it.
* I define by default the color of water (for raining)
*/
osg::Group* SGPrecipitation::build(void)
{
osg::Group* group = new osg::Group;
_precipitationEffect->snow(0);
_precipitationEffect->rain(0);
if (_clip_distance!=0.0)
{
osg::ref_ptr<osg::ClipNode> clipNode = new osg::ClipNode;
clipNode->addClipPlane( new osg::ClipPlane( 0 ) );
clipNode->getClipPlane(0)->setClipPlane( 0.0, 0.0, -1.0, -_clip_distance );
clipNode->setReferenceFrame(osg::ClipNode::ABSOLUTE_RF);
clipNode->addChild(_precipitationEffect.get());
group->addChild(clipNode.get());
}
else
{
group->addChild(_precipitationEffect.get());
}
group->setNodeMask( ~(simgear::CASTSHADOW_BIT | simgear::MODELLIGHT_BIT) );
return group;
}
/**
* @brief Define the snow intensity
*
* This function permits you to define and change the snow intensity
* The param 'intensity' is normed (0 to 1).
*/
void SGPrecipitation::setSnowIntensity(float intensity)
{
if (this->_snow_intensity < intensity-0.001)
this->_snow_intensity += 0.001;
else if (this->_snow_intensity > intensity+0.001)
this->_snow_intensity -= 0.001;
else
this->_snow_intensity = intensity;
}
/**
* @brief Define the rain intensity
*
* This function permits you to define and change the rain intensity
* The param 'intensity' is normed (0 to 1).
*/
void SGPrecipitation::setRainIntensity(float intensity)
{
if (this->_rain_intensity < intensity-0.001)
this->_rain_intensity += 0.001;
else if (this->_rain_intensity > intensity+0.001)
this->_rain_intensity -= 0.001;
else
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
*
* 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;
}
/**
* @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.
*/
void SGPrecipitation::setWindProperty(double heading, double speed)
{
double x, y, z;
heading = (heading + 180) * SGD_DEGREES_TO_RADIANS;
speed = speed * SG_FEET_TO_METER;
x = -cos(heading) * speed;
y = sin(heading) * speed;
z = 0;
this->_wind_vec = osg::Vec3(x, y, z);
}
/**
* @brief Update the precipitation effects
*
* This function permits you to update the precipitation effects.
* Be careful, if snow and rain intensity are greater than '0', snow effect
* will be first.
*
* The settings come from the osgParticule/PrecipitationEffect.cpp exemple.
*/
bool SGPrecipitation::update(void)
{
if (this->_freeze) {
if (this->_rain_intensity > 0) {
this->_snow_intensity = this->_rain_intensity;
}
}
if (_enabled && this->_snow_intensity > 0) {
_precipitationEffect->setWind(_wind_vec);
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 * _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);
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->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(0.64 * _illumination, 0.64 * _illumination, 0.64 * _illumination, 0.5));
} else {
_precipitationEffect->snow(0);
_precipitationEffect->rain(0);
}
return true;
}