1
0
Fork 0
flightgear/src/Environment/precipitation_mgr.cxx

295 lines
8.5 KiB
C++
Raw Normal View History

/**
* @file precipitation_mgr.cxx
* @author Nicolas VIVIEN
* @date 2008-02-10
*
* @note Copyright (C) 2008 Nicolas VIVIEN
*
* @brief Precipitation manager
* This manager calculate the intensity of precipitation in function of the altitude,
* calculate the wind direction and velocity, then update the drawing of precipitation.
*
* @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.
*
*/
2008-03-09 22:09:17 +00:00
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <osg/MatrixTransform>
#include <simgear/constants.h>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/scene/sky/cloud.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Viewer/renderer.hxx>
#include <Scenery/scenery.hxx>
#include "precipitation_mgr.hxx"
/**
* @brief FGPrecipitation Manager constructor
*
* Build a new object to manage the precipitation object
*/
FGPrecipitationMgr::FGPrecipitationMgr()
{
// Try to set up the scenegraph.
setupSceneGraph();
}
/**
* @brief FGPrecipitaiton Manager destructor
*/
FGPrecipitationMgr::~FGPrecipitationMgr()
{
}
/**
* SGSubsystem initialization
*/
void FGPrecipitationMgr::init()
{
// Read latitude and longitude position
SGGeod geod = SGGeod::fromDegM(fgGetDouble("/position/longitude-deg", 0.0),
fgGetDouble("/position/latitude-deg", 0.0),
0.0);
osg::Matrix position(makeZUpFrame(geod));
// Move the precipitation object to player position
transform->setMatrix(position);
fgGetNode("environment/params/precipitation-level-ft", true);
}
void FGPrecipitationMgr::bind ()
{
_tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) );
_tiedProperties.Tie("precipitation-enable", precipitation.get(),
&SGPrecipitation::getEnabled,
&SGPrecipitation::setEnabled);
}
void FGPrecipitationMgr::unbind ()
{
_tiedProperties.Untie();
}
// Set up the precipitation manager scenegraph.
void FGPrecipitationMgr::setupSceneGraph(void)
{
FGScenery* scenery = globals->get_scenery();
osg::Group* group = scenery->get_precipitation_branch();
transform = new osg::MatrixTransform();
precipitation = new SGPrecipitation();
// By default, no precipitation
precipitation->setRainIntensity(0);
precipitation->setSnowIntensity(0);
// set the clip distance from the config
precipitation->setClipDistance(fgGetFloat("/environment/precipitation-control/clip-distance",5.0));
transform->addChild(precipitation->build());
group->addChild(transform.get());
}
void FGPrecipitationMgr::setPrecipitationLevel(double a)
{
fgSetDouble("environment/params/precipitation-level-ft",a);
}
/**
* @brief Calculate the max alitutude with precipitation
*
* @returns Elevation max in meter
*
* This function permits you to know what is the altitude max where we can
* find precipitation. The value is returned in meters.
*/
float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void)
{
int i;
int max;
float result;
SGPropertyNode *boundaryNode, *boundaryEntry;
if (fgGetBool("/environment/params/use-external-precipitation-level", false)) {
// If we're not modeling the precipitation level based on the cloud
// layers, take it directly from the property tree.
return fgGetFloat("/environment/params/external-precipitation-level-m", 0.0);
}
Precipitation updates from ThorstenR required SimGear commit 75271c44a82ae0fb1ff9c91e93a12fa8b10099fd 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:44:55 +02:00
// By default (not cloud layer)
max = SGCloudLayer::SG_MAX_CLOUD_COVERAGES;
result = 0;
SGSky* thesky = globals->get_renderer()->getSky();
// To avoid messing up
if (thesky == NULL)
return result;
// For each cloud layer
for (i=0; i<thesky->get_cloud_layer_count(); i++) {
int q;
// Get coverage
// Value for q are (meaning / thickness) :
// 5 : "clear" / 0
// 4 : "cirrus" / ??
// 3 : "few" / 65
// 2 : "scattered" / 600
// 1 : "broken" / 750
// 0 : "overcast" / 1000
q = thesky->get_cloud_layer(i)->getCoverage();
// Save the coverage max
if (q < max) {
max = q;
result = thesky->get_cloud_layer(i)->getElevation_m();
}
}
// If we haven't found clouds layers, we read the bounday layers table.
if (result > 0)
return result;
// Read boundary layers node
boundaryNode = fgGetNode("/environment/config/boundary");
if (boundaryNode != NULL) {
i = 0;
// For each boundary layers
while ( ( boundaryEntry = boundaryNode->getNode( "entry", i ) ) != NULL ) {
double elev = boundaryEntry->getDoubleValue( "elevation-ft" );
if (elev > result)
result = elev;
++i;
}
}
// Convert the result in meter
result = result * SG_FEET_TO_METER;
return result;
}
/**
* @brief Update the precipitation drawing
*
* To seem real, we stop the precipitation above the cloud or boundary layer.
* If METAR information doesn't give us this altitude, we will see precipitations
* in space...
* Moreover, below 0°C we change rain into snow.
*/
void FGPrecipitationMgr::update(double dt)
{
double dewtemp;
double currtemp;
double rain_intensity;
double snow_intensity;
float altitudeAircraft;
float altitudeCloudLayer;
Precipitation updates from ThorstenR required SimGear commit 75271c44a82ae0fb1ff9c91e93a12fa8b10099fd 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:44:55 +02:00
float rainDropletSize;
float snowFlakeSize;
float illumination;
altitudeCloudLayer = this->getPrecipitationAtAltitudeMax() * SG_METER_TO_FEET;
setPrecipitationLevel(altitudeCloudLayer);
Precipitation updates from ThorstenR required SimGear commit 75271c44a82ae0fb1ff9c91e93a12fa8b10099fd 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:44:55 +02:00
// Does the user enable the precipitation ?
if (!precipitation->getEnabled() ) {
// Disable precipitations
precipitation->setRainIntensity(0);
precipitation->setSnowIntensity(0);
// Update the drawing...
precipitation->update();
// Exit
return;
}
Precipitation updates from ThorstenR required SimGear commit 75271c44a82ae0fb1ff9c91e93a12fa8b10099fd 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:44:55 +02:00
// See if external droplet size and illumination are used
if (fgGetBool("/environment/precipitation-control/detailed-precipitation", false)) {
precipitation->setDropletExternal(true);
rainDropletSize = fgGetFloat("/environment/precipitation-control/rain-droplet-size", 0.015);
snowFlakeSize = fgGetFloat("/environment/precipitation-control/snow-flake-size", 0.03);
illumination = fgGetFloat("/environment/precipitation-control/illumination", 1.0);
precipitation->setRainDropletSize(rainDropletSize);
precipitation->setSnowFlakeSize(snowFlakeSize);
precipitation->setIllumination(illumination);
}
// Get the elevation of aicraft and of the cloud layer
altitudeAircraft = fgGetDouble("/position/altitude-ft", 0.0);
if ((altitudeCloudLayer > 0) && (altitudeAircraft > altitudeCloudLayer)) {
// The aircraft is above the cloud layer
rain_intensity = 0;
snow_intensity = 0;
}
else {
// The aircraft is bellow the cloud layer
rain_intensity = fgGetDouble("/environment/rain-norm", 0.0);
snow_intensity = fgGetDouble("/environment/snow-norm", 0.0);
}
// Get the current and dew temperature
dewtemp = fgGetDouble("/environment/dewpoint-degc", 0.0);
currtemp = fgGetDouble("/environment/temperature-degc", 0.0);
if (currtemp < dewtemp) {
// There is fog... and the weather is very steamy
if (rain_intensity == 0)
rain_intensity = 0.15;
}
// If the current temperature is below 0°C, we turn off the rain to snow...
if (currtemp < 0)
precipitation->setFreezing(true);
else
precipitation->setFreezing(false);
// Set the wind property
precipitation->setWindProperty(
fgGetDouble("/environment/wind-from-heading-deg", 0.0),
fgGetDouble("/environment/wind-speed-kt", 0.0));
// Set the intensity of precipitation
precipitation->setRainIntensity(rain_intensity);
precipitation->setSnowIntensity(snow_intensity);
// Update the drawing...
precipitation->update();
}