]> git.mxchange.org Git - simgear.git/blob - simgear/environment/precipitation.cxx
hla: Make use of SGLocation.
[simgear.git] / simgear / environment / precipitation.cxx
1 /**
2  * @file precipitation.cxx
3  * @author Nicolas VIVIEN
4  * @date 2008-02-10
5  *
6  * @note Copyright (C) 2008 Nicolas VIVIEN
7  *
8  * @brief Precipitation effects to draw rain and snow.
9  *
10  * @par Licences
11  *   This program is free software; you can redistribute it and/or
12  *   modify it under the terms of the GNU General Public License as
13  *   published by the Free Software Foundation; either version 2 of the
14  *   License, or (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful, but
17  *   WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *   General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program; if not, write to the Free Software
23  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  */
26
27 #include "precipitation.hxx"
28 //#include "visual_enviro.hxx"
29
30 #include <simgear/constants.h>
31 #include <osg/ClipNode>
32 #include <simgear/scene/util/RenderConstants.hxx>
33
34 /**
35  * @brief SGPrecipitation constructor
36  *
37  * Build a new OSG object from osgParticle.
38  */
39 SGPrecipitation::SGPrecipitation() :
40     _freeze(false), _enabled(true), _snow_intensity(0.0), _rain_intensity(0.0), _clip_distance(5.0)
41 {
42     _precipitationEffect = new osgParticle::PrecipitationEffect;
43 }
44
45 void SGPrecipitation::setEnabled( bool value )
46 {
47     _enabled = value;
48 }
49
50 bool SGPrecipitation::getEnabled() const
51 {
52     return _enabled;
53 }
54
55 /**
56  * @brief Build and add the object "precipitationEffect"
57  *
58  * This function permits you to create an object precipitationEffect and initialize it.
59  * I define by default the color of water (for raining)
60  */
61 osg::Group* SGPrecipitation::build(void)
62 {
63     osg::Group* group = new osg::Group;
64
65     _precipitationEffect->snow(0);      
66     _precipitationEffect->rain(0);      
67
68     if (_clip_distance!=0.0)
69     {    
70         osg::ref_ptr<osg::ClipNode> clipNode = new osg::ClipNode;
71         clipNode->addClipPlane( new osg::ClipPlane( 0 ) );
72         clipNode->getClipPlane(0)->setClipPlane( 0.0, 0.0, -1.0, -_clip_distance );
73         clipNode->setReferenceFrame(osg::ClipNode::ABSOLUTE_RF);
74         clipNode->addChild(_precipitationEffect.get());
75
76         group->addChild(clipNode.get());
77     }
78     else
79     {
80         group->addChild(_precipitationEffect.get());
81     }
82
83     group->setNodeMask( ~(simgear::CASTSHADOW_BIT | simgear::MODELLIGHT_BIT) );
84
85     return group;
86 }
87
88
89 /**
90  * @brief Define the snow intensity
91  *
92  * This function permits you to define and change the snow intensity
93  * The param 'intensity' is normed (0 to 1).
94  */
95 void SGPrecipitation::setSnowIntensity(float intensity)
96 {
97     if (this->_snow_intensity < intensity-0.001)
98         this->_snow_intensity += 0.001;
99     else if (this->_snow_intensity > intensity+0.001)
100         this->_snow_intensity -= 0.001;
101     else
102         this->_snow_intensity = intensity;
103 }
104
105
106 /**
107  * @brief Define the rain intensity
108  *
109  * This function permits you to define and change the rain intensity
110  * The param 'intensity' is normed (0 to 1).
111  */
112 void SGPrecipitation::setRainIntensity(float intensity)
113 {
114     if (this->_rain_intensity < intensity-0.001)
115         this->_rain_intensity += 0.001;
116     else if (this->_rain_intensity > intensity+0.001)
117         this->_rain_intensity -= 0.001;
118     else
119         this->_rain_intensity = intensity;
120 }
121
122
123 /** 
124  * @brief Freeze the rain to snow
125  * 
126  * @param freeze Boolean 
127  * 
128  * This function permits you to turn off the rain to snow.
129  */
130 void SGPrecipitation::setFreezing(bool freeze)
131 {
132     this->_freeze = freeze;
133 }
134
135
136 /**
137  * @brief Define the wind direction and speed
138  *
139  * This function permits you to define and change the wind direction
140  * 
141  * After apply the MatrixTransform to the osg::Precipitation object,
142  * x points full south... From wind heading and speed, we can calculate
143  * the wind vector.
144  */
145 void SGPrecipitation::setWindProperty(double heading, double speed)
146 {
147     double x, y, z;
148
149     heading = (heading + 180) * SGD_DEGREES_TO_RADIANS;
150     speed = speed * SG_FEET_TO_METER;
151
152     x = -cos(heading) * speed;
153     y = sin(heading) * speed;
154     z = 0;
155
156     this->_wind_vec = osg::Vec3(x, y, z);
157 }
158
159
160 /**
161  * @brief Update the precipitation effects
162  *
163  * This function permits you to update the precipitation effects.
164  * Be careful, if snow and rain intensity are greater than '0', snow effect
165  * will be first.
166  *
167  * The settings come from the osgParticule/PrecipitationEffect.cpp exemple.
168  */
169 bool SGPrecipitation::update(void)
170 {
171     if (this->_freeze) {
172         if (this->_rain_intensity > 0) 
173             this->_snow_intensity = this->_rain_intensity;
174     }
175
176     if (_enabled && this->_snow_intensity > 0) {
177         _precipitationEffect->setWind(_wind_vec);
178         _precipitationEffect->setParticleSpeed( -0.75f - 0.25f*_snow_intensity);
179                 
180         _precipitationEffect->setParticleSize(0.02f + 0.03f*_snow_intensity);
181         _precipitationEffect->setMaximumParticleDensity(_snow_intensity * 7.2f);
182         _precipitationEffect->setCellSize(osg::Vec3(5.0f / (0.25f+_snow_intensity), 5.0f / (0.25f+_snow_intensity), 5.0f));
183                 
184         _precipitationEffect->setNearTransition(25.f);
185         _precipitationEffect->setFarTransition(100.0f - 60.0f*sqrtf(_snow_intensity));
186                 
187         _precipitationEffect->setParticleColor(osg::Vec4(0.85, 0.85, 0.85, 1.0) - osg::Vec4(0.1, 0.1, 0.1, 1.0) * _snow_intensity);
188     } else if (_enabled && this->_rain_intensity > 0) {
189         _precipitationEffect->setWind(_wind_vec);
190         _precipitationEffect->setParticleSpeed( -2.0f + -5.0f*_rain_intensity);
191                 
192         _precipitationEffect->setParticleSize(0.01 + 0.02*_rain_intensity);
193         _precipitationEffect->setMaximumParticleDensity(_rain_intensity * 7.5f);
194         _precipitationEffect->setCellSize(osg::Vec3(5.0f / (0.25f+_rain_intensity), 5.0f / (0.25f+_rain_intensity), 5.0f));
195                 
196         _precipitationEffect->setNearTransition(25.f);
197         _precipitationEffect->setFarTransition(100.0f - 60.0f*sqrtf(_rain_intensity));
198                 
199         _precipitationEffect->setParticleColor( osg::Vec4(0x7A, 0xCE, 0xFF, 0x80));
200     } else {
201         _precipitationEffect->snow(0);  
202         _precipitationEffect->rain(0);  
203     }
204
205     return true;
206 }