]> git.mxchange.org Git - flightgear.git/blob - src/Environment/precipitation_mgr.cxx
b6e6e6e3183b7e32365c7af7fb90c2510a9fcf5c
[flightgear.git] / src / Environment / precipitation_mgr.cxx
1 /**
2  * @file precipitation_mgr.cxx
3  * @author Nicolas VIVIEN
4  * @date 2008-02-10
5  *
6  * @note Copyright (C) 2008 Nicolas VIVIEN
7  *
8  * @brief Precipitation manager
9  *   This manager calculate the intensity of precipitation in function of the altitude,
10  *   calculate the wind direction and velocity, then update the drawing of precipitation.
11  *
12  * @par Licences
13  *   This program is free software; you can redistribute it and/or
14  *   modify it under the terms of the GNU General Public License as
15  *   published by the Free Software Foundation; either version 2 of the
16  *   License, or (at your option) any later version.
17  *
18  *   This program is distributed in the hope that it will be useful, but
19  *   WITHOUT ANY WARRANTY; without even the implied warranty of
20  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *   General Public License for more details.
22  *
23  *   You should have received a copy of the GNU General Public License
24  *   along with this program; if not, write to the Free Software
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26  *
27  */
28
29 #include <osg/MatrixTransform>
30
31 #include <simgear/constants.h>
32 #include <simgear/math/SGMath.hxx>
33 #include <simgear/scene/sky/sky.hxx>
34 #include <simgear/scene/sky/cloud.hxx>
35
36 #include <Main/fg_props.hxx>
37 #include <Main/globals.hxx>
38 #include <Scenery/scenery.hxx>
39
40 #include "precipitation_mgr.hxx"
41
42
43 extern SGSky *thesky;
44
45
46 /** 
47  * @brief FGPrecipitation Manager constructor 
48  *
49  * Build a new object to manage the precipitation object
50  */
51 FGPrecipitationMgr::FGPrecipitationMgr()
52 {       
53     group = new osg::Group();
54     transform = new osg::MatrixTransform();
55     precipitation = new SGPrecipitation();
56
57
58     // By default, no precipitation
59     precipitation->setRainIntensity(0);
60     precipitation->setSnowIntensity(0);
61
62     transform->addChild(precipitation->build());
63     group->addChild(transform.get());
64 }
65
66
67 /** 
68  * @brief FGPrecipitaiton Manager destructor
69  */
70 FGPrecipitationMgr::~FGPrecipitationMgr()
71 {
72
73 }
74
75 /**
76  * SGSubsystem initialization
77  */
78 void FGPrecipitationMgr::init()
79 {
80     // Read latitude and longitude position
81     SGGeod geod = SGGeod::fromDegM(fgGetDouble("/position/longitude-deg", 0.0),
82                                    fgGetDouble("/position/latitude-deg", 0.0),
83                                    0.0);
84     osg::Matrix position(geod.makeZUpFrame());
85     // Move the precipitation object to player position
86     transform->setMatrix(position);
87     // Add to scene graph
88     osg::Group* scenery = globals->get_scenery()->get_scene_graph();
89     scenery->addChild(getObject());
90 }
91
92 /** 
93  * @brief Get OSG precipitation object
94  * 
95  * @returns A pointer on the OSG object (osg::Group *)
96  */
97 osg::Group * FGPrecipitationMgr::getObject(void)
98 {
99     return this->group.get();
100 }
101
102
103 /** 
104  * @brief Calculate the max alitutude with precipitation
105  * 
106  * @returns Elevation max in meter
107  *
108  * This function permits you to know what is the altitude max where we can
109  * find precipitation. The value is returned in meter.
110  */
111 float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void)
112 {
113     int i;
114     int max;
115     float result;
116
117
118     // By default (not cloud layer)
119     max = SGCloudLayer::SG_MAX_CLOUD_COVERAGES;
120     result = 0;
121
122     // To avoid messing up
123     if (thesky == NULL)
124         return result;
125
126     // For each cloud layer
127     for (i=0; i<thesky->get_cloud_layer_count(); i++) {
128         int q;
129
130         // Get coverage
131         // Value for q are (meaning / thickness) :
132         //   5 : "clear"                / 0
133         //   4 : "cirrus"       / ??
134         //   3 : "few"                  / 65
135         //   2 : "scattered"    / 600
136         //   1 : "broken"               / 750
137         //   0 : "overcast"             / 1000
138         q = thesky->get_cloud_layer(i)->getCoverage();
139
140         // Save the coverage max
141         if (q < max) {
142             max = q;
143             result = thesky->get_cloud_layer(i)->getElevation_m();
144         }
145     }
146
147     return result;
148 }
149
150
151 /** 
152  * @brief Update the precipitation drawing
153  * 
154  */
155 void FGPrecipitationMgr::update(double dt)
156 {
157     double dewtemp;
158     double currtemp;
159     double rain_intensity;
160     double snow_intensity;
161
162     float altitudeAircraft;
163     float altitudeCloudLayer;
164
165     // Get the elevation of aicraft and of the cloud layer
166     altitudeAircraft = fgGetDouble("/position/altitude-ft", 0.0);
167     altitudeCloudLayer = this->getPrecipitationAtAltitudeMax() * SG_METER_TO_FEET;
168
169     if (altitudeAircraft > altitudeCloudLayer) {
170         // The aircraft is above the cloud layer
171         rain_intensity = 0;
172         snow_intensity = 0;
173     }
174     else {
175         // The aircraft is bellow the cloud layer
176         rain_intensity = fgGetDouble("/environment/metar/rain-norm", 0.0);
177         snow_intensity = fgGetDouble("/environment/metar/snow-norm", 0.0);
178     }
179
180     // Get the current and dew temperature
181     dewtemp = fgGetDouble("/environment/dewpoint-degc", 0.0);
182     currtemp = fgGetDouble("/environment/temperature-degc", 0.0);
183
184     if (currtemp < dewtemp) {
185         // There is fog... and the weather is very steamy
186         if (rain_intensity == 0)
187             rain_intensity = 0.15;
188     }
189
190     // If the current temperature is below 0°C, we turn off the rain to snow...
191     if (currtemp < 0)
192         precipitation->setFreezing(true);
193     else
194         precipitation->setFreezing(false);
195
196
197     // Set the wind property
198     precipitation->setWindProperty(
199         fgGetDouble("/environment/wind-from-heading-deg", 0.0),
200         fgGetDouble("/environment/wind-speed-kt", 0.0));
201
202     // Set the intensity of precipitation
203     precipitation->setRainIntensity(rain_intensity);
204     precipitation->setSnowIntensity(snow_intensity);
205
206     // Update the drawing...
207     precipitation->update();
208 }