]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/sky.hxx
For clouds, use a RNG seed that only changes every 10 minutes.
[simgear.git] / simgear / scene / sky / sky.hxx
1 /**
2  * \file sky.hxx
3  * Provides a class to model a realistic (time/date/position) based sky.
4  */
5
6 // Written by Curtis Olson, started December 1997.
7 // SSG-ified by Curtis Olson, February 2000.
8 //
9 // Copyright (C) 1997-2000  Curtis L. Olson  - http://www.flightgear.org/~curt
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Library General Public
13 // License as published by the Free Software Foundation; either
14 // version 2 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 // Library 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 // $Id$
26
27
28 #ifndef _SG_SKY_HXX
29 #define _SG_SKY_HXX
30
31
32 #ifndef __cplusplus
33 # error This library requires C++
34 #endif
35
36 #include <simgear/compiler.h>
37 #include <simgear/math/sg_random.h>
38 #include <simgear/misc/sg_path.hxx>
39 #include <simgear/props/props.hxx>
40
41 #include <vector>
42
43 #include <osg/ref_ptr>
44 #include <osg/MatrixTransform>
45 #include <osg/Node>
46 #include <osg/Switch>
47
48 #include <simgear/ephemeris/ephemeris.hxx>
49 #include <simgear/math/SGMath.hxx>
50
51 #include <simgear/scene/sky/cloud.hxx>
52 #include <simgear/scene/sky/dome.hxx>
53 #include <simgear/scene/sky/moon.hxx>
54 #include <simgear/scene/sky/oursun.hxx>
55 #include <simgear/scene/sky/stars.hxx>
56
57 namespace simgear {
58 class SGReaderWriterOptions;
59 }
60
61 typedef struct {
62     SGVec3d pos;
63     SGGeod pos_geod;
64     SGQuatd ori;
65     double spin;
66         double gst;
67         double sun_dist;
68         double moon_dist;
69         double sun_angle;
70 } SGSkyState;
71
72 typedef struct {
73         SGVec3f sky_color;
74     SGVec3f adj_sky_color;
75     SGVec3f fog_color;
76         SGVec3f cloud_color;
77         double sun_angle, moon_angle;
78 } SGSkyColor;
79
80 /**
81  * A class to model a realistic (time/date/position) based sky.
82  *
83  * Introduction 
84  *
85  * The SGSky class models a blended sky dome, a haloed sun, a textured
86  * moon with phase that properly matches the date, stars and planets,
87  * and cloud layers. SGSky is designed to be dropped into existing
88  * plib based applications and depends heavily on plib's scene graph
89  * library, ssg. The sky implements various time of day lighting
90  * effects, it plays well with fog and visibility effects, and
91  * implements scudded cloud fly-through effects. Additionally, you can
92  * wire in the output of the SGEphemeris class to accurately position
93  * all the objects in the sky.
94  *
95  * Building the sky 
96  *
97
98  * Once you have created an instance of SGSky you must call the
99  * build() method.  Building the sky requires several textures. So,
100  * you must specify the path/directory where these textures reside
101  * before building the sky.  You do this first by calling the
102  * texture_path() method.
103
104  * The arguments you pass to the build() method allow you to specify
105  * the horizontal and vertical radiuses of the sky dome, the size of
106  * your sun sphere and moon sphere, a number of planets, and a
107  * multitude of stars.  For the planets and stars you pass in an array
108  * of right ascensions, declinations, and magnitudes.
109
110  * Cloud Layers 
111
112  * Cloud layers can be added, changed, or removed individually. To add
113  * a cloud layer use the add_cloud_layer() method.  The arguments
114  * allow you to specify base height above sea level, layer thickness,
115  * a transition zone for entering/leaving the cloud layer, the size of
116  * the cloud object, and the type of cloud texture. All distances are
117  * in meters. There are additional forms of this method that allow you
118  * to specify your own ssgSimpleState or texture name for drawing the
119  * cloud layer.
120
121  * Repainting the Sky 
122
123  * As the sun circles the globe, you can call the repaint() method to
124  * recolor the sky objects to simulate sunrise and sunset effects,
125  * visibility, and other lighting changes.  The arguments allow you to
126  * specify a base sky color (for the top of the dome), a fog color
127  * (for the horizon), the sun angle with the horizon (for
128  * sunrise/sunset effects), the moon angle (so we can make it more
129  * yellow at the horizon), and new star and planet data so that we can
130  * optionally change the magnitude of these (for day / night
131  * transitions.)
132
133  * Positioning Sky Objects 
134
135  * As time progresses and as you move across the surface of the earth,
136  * the apparent position of the objects and the various lighting
137  * effects can change. the reposition() method allows you to specify
138  * the positions of all the sky objects as well as your view position.
139  * The arguments allow you to specify your view position in world
140  * Cartesian coordinates, the zero elevation position in world
141  * Cartesian coordinates (your longitude, your latitude, sea level),
142  * the ``up'' vector in world Cartesian coordinates, current
143  * longitude, latitude, and altitude. A ``spin'' angle can be
144  * specified for orienting the sky with the sun position so sunset and
145  * sunrise effects look correct. You must specify GMT side real time,
146  * the sun right ascension, sun declination, and sun distance from
147  * view point (to keep it inside your view volume.) You also must
148  * specify moon right ascension, moon declination, and moon distance
149  * from view point.
150
151  * Rendering the Sky 
152
153  * The sky is designed to be rendered in three stages. The first stage
154  * renders the parts that form your back drop - the sky dome, the
155  * stars and planets, the sun, and the moon.  These should be rendered
156  * before the rest of your scene by calling the preDraw() method. The
157  * second stage renders the clouds that are above the viewer. This stage 
158  * is done before translucent objects in the main scene are drawn. It 
159  * is seperated from the preDraw routine to enable to implement a 
160  * multi passes technique and is located in the drawUpperClouds() method.
161  * The third stage renders the clouds that are below the viewer an which 
162  * are likely to be translucent (depending on type) and should be drawn 
163  * after your scene has been rendered.  Use the drawLowerClouds() method 
164  * to draw the second stage of the sky.
165
166  * A typical application might do the following: 
167
168  * <li> thesky->preDraw( my_altitude );
169  * <li> thesky->drawUpperClouds();
170  * <li> ssgCullAndDraw ( myscene ) ;
171  * <li> thesky->drawLowerClouds();
172
173  * The current altitude in meters is passed to the preDraw() method
174  * so the clouds layers can be rendered correction from most distant
175  * to closest.
176
177  * Visibility Effects 
178
179  * Visibility and fog is important for correctly rendering the
180  * sky. You can inform SGSky of the current visibility by calling the
181  * set_visibility() method.
182
183  * When transitioning through clouds, it is nice to pull in the fog as
184  * you get close to the cloud layer to hide the fact that the clouds
185  * are drawn as a flat polygon. As you get nearer to the cloud layer
186  * it is also nice to temporarily pull in the visibility to simulate
187  * the effects of flying in and out of the puffy edge of the
188  * cloud. These effects can all be accomplished by calling the
189  * modify_vis() method.  The arguments allow you to specify your
190  * current altitude (which is then compared to the altitudes of the
191  * various cloud layers.) You can also specify a time factor which
192  * should be the length in seconds since the last time you called
193  * modify_vis(). The time_factor value allows the puffy cloud effect
194  * to be calculated correctly.
195
196  * The modify_vis() method alters the SGSky's internal idea of
197  * visibility, so you should subsequently call get_visibility() to get
198  * the actual modified visibility. You should then make the
199  * appropriate glFog() calls to setup fog properly for your scene.
200
201  * Accessor Methods 
202
203  * Once an instance of SGSky has been successfully initialized, there
204  * are a couple accessor methods you can use such as get_num_layers()
205  * to return the number of cloud layers, get_cloud_layer(i) to return
206  * cloud layer number i, get_visibility() to return the actual
207  * visibility as modified by the sky/cloud model.
208
209  */
210
211 class SGSky {
212
213 private:
214     typedef std::vector<SGSharedPtr<SGCloudLayer> > layer_list_type;
215     typedef layer_list_type::iterator layer_list_iterator;
216     typedef layer_list_type::const_iterator layer_list_const_iterator;
217
218     // components of the sky
219     SGSharedPtr<SGSkyDome> dome;
220     SGSharedPtr<SGSun> oursun;
221     SGSharedPtr<SGMoon> moon;
222     SGSharedPtr<SGStars> planets;
223     SGSharedPtr<SGStars> stars;
224     layer_list_type cloud_layers;
225
226     osg::ref_ptr<osg::Group> pre_root, cloud_root;
227     osg::ref_ptr<osg::Switch> pre_selector;
228     osg::ref_ptr<osg::Group> pre_transform;
229
230     osg::ref_ptr<osg::MatrixTransform> _ephTransform;
231
232     SGPath tex_path;
233
234     // visibility
235     float visibility;
236     float effective_visibility;
237     float minimum_sky_visibility;
238
239     int in_cloud;
240     int cur_layer_pos;
241
242     // near cloud visibility state variables
243     bool in_puff;
244     double puff_length;         // in seconds
245     double puff_progression;    // in seconds
246     double ramp_up;             // in seconds
247     double ramp_down;           // in seconds
248
249     // 3D clouds enabled
250     bool clouds_3d_enabled;
251
252     // 3D cloud density
253     double clouds_3d_density;
254     
255     // RNG seed
256     mt seed;
257
258 public:
259
260     /** Constructor */
261     SGSky( void );
262
263     /** Destructor */
264     ~SGSky( void );
265
266     /**
267      * Initialize the sky and connect the components to the scene
268      * graph at the provided branch.  See discussion in detailed class
269      * description.
270      * @param h_radius_m horizontal radius of sky dome
271      * @param v_radius_m vertical radius of sky dome
272      * @param sun_size size of sun
273      * @param moon_size size of moon
274      * @param nplanets number of planets
275      * @param planet_data an array of planet right ascensions, declinations,
276      *        and magnitudes
277      * @param nstars number of stars
278      * @param star_data an array of star right ascensions, declinations,
279      *        and magnitudes
280      */
281     void build( double h_radius_m, double v_radius_m,
282                 double sun_size, double moon_size,
283                 const SGEphemeris& eph, SGPropertyNode *property_tree_node,
284                 simgear::SGReaderWriterOptions* options);
285
286     /**
287      * Repaint the sky components based on current value of sun_angle,
288      * sky, and fog colors.  You can also specify new star and planet
289      * data so that we can optionally change the magnitude of these
290      * (for day/night transitions.)  See discussion in detailed
291      * class description.
292      *
293      * Sun and moon angles are specified in degrees relative to local up
294      * <li> 0 degrees = high noon
295      * <li> 90 degrees = sun rise/set
296      * <li> 180 degrees = darkest midnight
297      * @param sky_color the base sky color (for the top of the dome)
298      * @param fog_color the fog color (for the horizon)
299      * @param sun_angle the sun angle with the horizon (for sunrise/sunset
300      *        effects)
301      * @param moon_angle the moon angle (so we can make it more yellow
302      *        at the horizon)
303      * @param nplanets number of planets
304      * @param planet_data an array of planet right ascensions, declinations,
305      *        and magnitudes
306      * @param nstars number of stars
307      * @param star_data an array of star right ascensions, declinations,
308      *        and magnitudes
309      */
310     bool repaint( const SGSkyColor &sc, const SGEphemeris& eph );
311
312     /**
313      * Reposition the sky at the specified origin and orientation
314      *
315      * lon specifies a rotation about the Z axis
316      * lat specifies a rotation about the new Y axis
317      * spin specifies a rotation about the new Z axis (this allows
318      * additional orientation for the sunrise/set effects and is used
319      * by the skydome and perhaps clouds.  See discussion in detailed
320      * class description.
321      * @param view_pos specify your view position in world Cartesian
322      *        coordinates
323      * @param zero_elev the zero elevation position in world Cartesian
324      *        coordinates
325      * @param view_up the up vector in world Cartesian coordinates
326      * @param lon current longitude
327      * @param lat current latitude
328      * @param alt current altitude
329      * @param spin an offset angle for orienting the sky effects with the
330      *        sun position so sunset and sunrise effects look correct.
331      * @param gst GMT side real time
332      * @param sun_ra the sun's current right ascension
333      * @param sun_dec the sun's current declination
334      * @param sun_dist the sun's distance from the current view point
335      *        (to keep it inside your view volume.)
336      * @param moon_ra the moon's current right ascension
337      * @param moon_dec the moon's current declination
338      * @param moon_dist the moon's distance from the current view point. 
339      */
340     bool reposition( const SGSkyState &st, const SGEphemeris& eph, double dt = 0.0 );
341
342     /**
343      * Modify the given visibility based on cloud layers, thickness,
344      * transition range, and simulated "puffs".  See discussion in detailed
345      * class description.
346      * @param alt current altitude
347      * @param time_factor amount of time since modify_vis() last called so
348      *        we can scale effect rates properly despite variable frame rates.
349      */
350     void modify_vis( float alt, float time_factor );
351
352     osg::Node* getPreRoot() { return pre_root.get(); }
353     osg::Node* getCloudRoot() { return cloud_root.get(); }
354
355     /** 
356      * Specify the texture path (optional, defaults to current directory)
357      * @param path base path to texture locations
358      */
359     void texture_path( const string& path );
360
361     /** Enable drawing of the sky. */
362     inline void enable() {
363         pre_selector->setValue(0, 1);
364     }
365
366     /**
367      * Disable drawing of the sky in the scene graph.  The leaf node is still
368      * there, how ever it won't be traversed on by ssgCullandRender()
369      */
370     inline void disable() {
371         pre_selector->setValue(0, 0);
372     }
373
374     /**
375      * Get the current sun color
376      */
377     inline SGVec4f get_sun_color() { return oursun->get_color(); }
378
379     /**
380      * Get the current scene color
381      */
382     inline SGVec4f get_scene_color() { return oursun->get_scene_color(); }
383
384     /**
385      * Add a cloud layer.
386      *
387      * Transfer pointer ownership to this object.
388      *
389      * @param layer The new cloud layer to add.
390      */
391     void add_cloud_layer (SGCloudLayer * layer);
392
393
394     /**
395      * Get a cloud layer (const).
396      *
397      * Pointer ownership remains with this object.
398      *
399      * @param i The index of the cloud layer, zero-based.
400      * @return A const pointer to the cloud layer.
401      */
402     const SGCloudLayer * get_cloud_layer (int i) const;
403
404
405     /**
406      * Get a cloud layer (non-const).
407      *
408      * Pointer ownership remains with this object.
409      *
410      * @param i The index of the cloud layer, zero-based.
411      * @return A non-const pointer to the cloud layer.
412      */
413     SGCloudLayer * get_cloud_layer (int i);
414
415
416     /**
417      * Return the number of cloud layers currently available.
418      *
419      * @return The cloud layer count.
420      */
421     int get_cloud_layer_count () const;
422
423
424     /** @return current effective visibility */
425     inline float get_visibility() const { return effective_visibility; }
426
427     /** Set desired clear air visibility.
428      * @param v visibility in meters
429      */
430     inline void set_visibility( float v ) {
431         effective_visibility = visibility = (v <= 25.0) ? 25.0 : v;
432     }
433
434     /** Get 3D cloud density */
435     double get_3dCloudDensity() const;
436
437     /** Set 3D cloud density 
438      * @param density 3D cloud density
439      */
440     void set_3dCloudDensity(double density);
441
442     /** Get 3D cloud visibility range*/
443     float get_3dCloudVisRange() const;
444
445     /** Set 3D cloud visibility range
446      * @param density 3D cloud visibility range
447      */
448     void set_3dCloudVisRange(float vis);
449
450     /** Get 3D cloud impostor distance*/
451     float get_3dCloudImpostorDistance() const;
452
453     /** Set 3D cloud impostor distance
454      * @param density 3D cloud impostor distance
455      */
456     void set_3dCloudImpostorDistance(float vis);
457
458     /** Get 3D cloud LoD1 Range*/
459     float get_3dCloudLoD1Range() const;
460
461     /** Set 3D cloud LoD1 Range
462      * @param vis LoD1 Range
463      */
464     void set_3dCloudLoD1Range(float vis);
465
466     /** Get 3D cloud LoD2 Range*/
467     float get_3dCloudLoD2Range() const;
468
469     /** Set 3D cloud LoD2 Range
470      * @param vis LoD2 Range
471      */
472     void set_3dCloudLoD2Range(float vis);
473
474     /** Get 3D cloud impostor usage */
475     bool get_3dCloudUseImpostors() const;
476
477     /** Set 3D cloud impostor usage
478      * @param wrap whether use impostors for 3D clouds
479      */
480     void set_3dCloudUseImpostors(bool imp);
481
482     /** Get 3D cloud wrapping */
483     bool get_3dCloudWrap() const;
484
485     /** Set 3D cloud wrapping
486      * @param wrap whether to wrap 3D clouds
487      */
488     void set_3dCloudWrap(bool wrap);
489
490
491     /** Get minimum sky visibility */
492     float get_minimum_sky_visibility() const;
493
494     /** Set minimum sky visibility */
495     void set_minimum_sky_visibility( float value );
496 };
497 #endif // _SG_SKY_HXX