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