X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Fprecipitation_mgr.cxx;h=9e83ab8529aeff365f7ce50939b5f6dfd17f16ef;hb=06e8fe747fb1733528aa1e01bc6bd285a53ec127;hp=fcabe72ba351c085592cbd5e338b335e1b11fbbf;hpb=eb26cb35905cb1894cb0346700826cff512e437e;p=flightgear.git diff --git a/src/Environment/precipitation_mgr.cxx b/src/Environment/precipitation_mgr.cxx index fcabe72ba..9e83ab852 100644 --- a/src/Environment/precipitation_mgr.cxx +++ b/src/Environment/precipitation_mgr.cxx @@ -24,38 +24,26 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * @par CVS - * $Id$ */ -#include -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include +#endif -#include -#include -#include -#include #include -#include #include #include #include +#include #include
+#include
+#include +#include #include "precipitation_mgr.hxx" - -extern SGSky *thesky; - - -void WorldCoordinate( osg::Matrix&, double, - double, double, double); - /** * @brief FGPrecipitation Manager constructor * @@ -63,32 +51,19 @@ void WorldCoordinate( osg::Matrix&, double, */ FGPrecipitationMgr::FGPrecipitationMgr() { - osg::Matrix position; - double latitude, longitude; - - - group = new osg::Group(); - transform = new osg::MatrixTransform(); - precipitation = new SGPrecipitation(); - - - // By default, none precipitation - precipitation->setRainIntensity(0); - precipitation->setSnowIntensity(0); + group = new osg::Group(); + transform = new osg::MatrixTransform(); + precipitation = new SGPrecipitation(); - // Read latitude and longitude position - latitude = fgGetDouble("/position/latitude-deg", 0.0); - longitude = fgGetDouble("/position/longitude-deg", 0.0); + // By default, no precipitation + precipitation->setRainIntensity(0); + precipitation->setSnowIntensity(0); - WorldCoordinate(position, latitude, longitude, 0, 0); - - - // Move the precipitation object to player position - transform->setMatrix(position); - transform->addChild(precipitation->build()); - - group->addChild(transform); + // 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()); } @@ -97,9 +72,44 @@ FGPrecipitationMgr::FGPrecipitationMgr() */ FGPrecipitationMgr::~FGPrecipitationMgr() { - delete precipitation; + } +/** + * 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); + // Add to scene graph + osg::Group* scenery = globals->get_scenery()->get_scene_graph(); + scenery->addChild(getObject()); + 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(); +} + +void FGPrecipitationMgr::setPrecipitationLevel(double a) +{ + fgSetDouble("environment/params/precipitation-level-ft",a); +} /** * @brief Get OSG precipitation object @@ -108,121 +118,182 @@ FGPrecipitationMgr::~FGPrecipitationMgr() */ osg::Group * FGPrecipitationMgr::getObject(void) { - return this->group; + return this->group.get(); } - /** * @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 meter. + * find precipitation. The value is returned in meters. */ float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void) { - int i; - int max; - float result; - - - // By default (not cloud layer) - max = SGCloudLayer::SG_MAX_CLOUD_COVERAGES; - result = 0; - - // To avoid messing up - if (thesky == NULL) - return result; - - // For each cloud layer - for (i=0; iget_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(); - } - } - - return result; + 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); + } + + + // 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; iget_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 * - * @returns true is all is OK - * - * This function permits you to update the precipitation drawing. - * This function is called by the renderer. + * 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. */ -bool FGPrecipitationMgr::update(void) +void FGPrecipitationMgr::update(double dt) { - double dewtemp; - double currtemp; - double rain_intensity; - double snow_intensity; - - float altitudeAircraft; - float altitudeCloudLayer; - - // Get the elevation of aicraft and of the cloud layer - altitudeAircraft = fgGetDouble("/position/altitude-ft", 0.0); - altitudeCloudLayer = this->getPrecipitationAtAltitudeMax() * SG_METER_TO_FEET; - - if (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/metar/rain-norm", 0.0); - snow_intensity = fgGetDouble("/environment/metar/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(); - - return true; + double dewtemp; + double currtemp; + double rain_intensity; + double snow_intensity; + + float altitudeAircraft; + float altitudeCloudLayer; + float rainDropletSize; + float snowFlakeSize; + float illumination; + + altitudeCloudLayer = this->getPrecipitationAtAltitudeMax() * SG_METER_TO_FEET; + setPrecipitationLevel(altitudeCloudLayer); + + + + // Does the user enable the precipitation ? + if (!precipitation->getEnabled() ) { + // Disable precipitations + precipitation->setRainIntensity(0); + precipitation->setSnowIntensity(0); + + // Update the drawing... + precipitation->update(); + + // Exit + return; + } + + // 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(); } - -