]> git.mxchange.org Git - flightgear.git/blobdiff - src/Environment/precipitation_mgr.cxx
Precipitation updates from ThorstenR
[flightgear.git] / src / Environment / precipitation_mgr.cxx
index d6b802d669fbfc2e852739623d1e0bf976636bec..9e83ab8529aeff365f7ce50939b5f6dfd17f16ef 100644 (file)
 #include <osg/MatrixTransform>
 
 #include <simgear/constants.h>
-#include <simgear/math/SGMath.hxx>
 #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"
 
-
-extern SGSky *thesky;
-
-
 /** 
  * @brief FGPrecipitation Manager constructor 
  *
@@ -63,6 +60,8 @@ FGPrecipitationMgr::FGPrecipitationMgr()
     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());
 }
@@ -85,12 +84,31 @@ void FGPrecipitationMgr::init()
     SGGeod geod = SGGeod::fromDegM(fgGetDouble("/position/longitude-deg", 0.0),
                                    fgGetDouble("/position/latitude-deg", 0.0),
                                    0.0);
-    osg::Matrix position(geod.makeZUpFrame());
+    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);
 }
 
 /** 
@@ -103,26 +121,34 @@ osg::Group * FGPrecipitationMgr::getObject(void)
     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;
+    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;
@@ -148,6 +174,32 @@ float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void)
         }
     }
 
+
+    // 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;
 }
 
@@ -155,6 +207,10 @@ float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void)
 /** 
  * @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)
 {
@@ -165,20 +221,51 @@ void FGPrecipitationMgr::update(double dt)
 
     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);
-    altitudeCloudLayer = this->getPrecipitationAtAltitudeMax() * SG_METER_TO_FEET;
 
-    if (altitudeAircraft > altitudeCloudLayer) {
+    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/metar/rain-norm", 0.0);
-        snow_intensity = fgGetDouble("/environment/metar/snow-norm", 0.0);
+        rain_intensity = fgGetDouble("/environment/rain-norm", 0.0);
+        snow_intensity = fgGetDouble("/environment/snow-norm", 0.0);
     }
 
     // Get the current and dew temperature