]> git.mxchange.org Git - simgear.git/blob - simgear/sky/sky.hxx
2948173f6f37b1acc37deaacf7dbeac47032942d
[simgear.git] / simgear / 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  - curt@flightgear.org
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 Library General Public
22 // License along with this library; if not, write to the
23 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 // Boston, MA  02111-1307, USA.
25 //
26 // $Id$
27
28
29 #ifndef _SG_SKY_HXX
30 #define _SG_SKY_HXX
31
32
33 #ifndef __cplusplus                                                          
34 # error This library requires C++
35 #endif                                   
36
37
38 #include <plib/ssg.h>           // plib include
39
40 #include <simgear/compiler.h>
41 #include <simgear/misc/sg_path.hxx>
42
43 #include <vector>
44
45 #include <simgear/sky/cloud.hxx>
46 #include <simgear/sky/dome.hxx>
47 #include <simgear/sky/moon.hxx>
48 #include <simgear/sky/oursun.hxx>
49 #include <simgear/sky/stars.hxx>
50
51 SG_USING_STD(vector);
52
53
54 typedef vector < SGCloudLayer* > layer_list_type;
55 typedef layer_list_type::iterator layer_list_iterator;
56 typedef layer_list_type::const_iterator layer_list_const_iterator;
57
58 /**
59  * A class to model a realistic (time/date/position) based sky.
60  *
61  * Introduction 
62  *
63  * The SGSky class models a blended sky dome, a haloed sun, a textured
64  * moon with phase that properly matches the date, stars and planets,
65  * and cloud layers. SGSky is designed to be dropped into existing
66  * plib based applications and depends heavily on plib's scene graph
67  * library, ssg. The sky implements various time of day lighting
68  * effects, it plays well with fog and visibility effects, and
69  * implements scudded cloud fly-through effects. Additionally, you can
70  * wire in the output of the SGEphemeris class to accurately position
71  * all the objects in the sky.
72  *
73  * Building the sky 
74  *
75
76  * Once you have created an instance of SGSky you must call the
77  * build() method.  Building the sky requires several textures. So,
78  * you must specify the path/directory where these textures reside
79  * before building the sky.  You do this first by calling the
80  * texture_path() method.
81
82  * The arguments you pass to the build() method allow you to specify
83  * the size of your sun sphere and moon sphere, a number of planets,
84  * and a multitude of stars.  For the planets and stars you pass in an
85  * array of right ascensions, declinations, magnitudes, and the
86  * distance from the view point.
87
88  * Cloud Layers 
89
90  * Cloud layers can be added, changed, or removed individually. To add
91  * a cloud layer use the add_cloud_layer() method.  The arguments
92  * allow you to specify base height above sea level, layer thickness,
93  * a transition zone for entering/leaving the cloud layer, the size of
94  * the cloud object, and the type of cloud texture. All distances are
95  * in meters. There are additional forms of this method that allow you
96  * to specify your own ssgSimpleState or texture name for drawing the
97  * cloud layer.
98
99  * Repainting the Sky 
100
101  * As the sun circles the globe, you can call the repaint() method to
102  * recolor the sky objects to simulate sunrise and sunset effects,
103  * visibility, and other lighting changes.  The arguments allow you to
104  * specify a base sky color (for the top of the dome), a fog color
105  * (for the horizon), the sun angle with the horizon (for
106  * sunrise/sunset effects), the moon angle (so we can make it more
107  * yellow at the horizon), and new star and planet data so that we can
108  * optionally change the magnitude of these (for day / night
109  * transitions.)
110
111  * Positioning Sky Objects 
112
113  * As time progresses and as you move across the surface of the earth,
114  * the apparent position of the objects and the various lighting
115  * effects can change. the reposition() method allows you to specify
116  * the positions of all the sky objects as well as your view position.
117  * The arguments allow you to specify your view position in world
118  * Cartesian coordinates, the zero elevation position in world
119  * Cartesian coordinates (your longitude, your latitude, sea level),
120  * the ``up'' vector in world Cartesian coordinates, current
121  * longitude, latitude, and altitude. A ``spin'' angle can be
122  * specified for orienting the sky with the sun position so sunset and
123  * sunrise effects look correct. You must specify GMT side real time,
124  * the sun right ascension, sun declination, and sun distance from
125  * view point (to keep it inside your view volume.) You also must
126  * specify moon right ascension, moon declination, and moon distance
127  * from view point.
128
129  * Rendering the Sky 
130
131  * The sky is designed to be rendered in two stages. The first stage
132  * renders the parts that form your back drop - the sky dome, the
133  * stars and planets, the sun, and the moon.  These should be rendered
134  * before the rest of your scene by calling the preDraw() method. The
135  * second stage renders the clouds which are likely to be translucent
136  * (depending on type) and should be drawn after your scene has been
137  * rendered.  Use the postDraw() method to draw the second stage of
138  * the sky.
139
140  * A typical application might do the following: 
141
142  * <li> thesky->preDraw();
143  * <li> ssgCullAndDraw ( myscene ) ;
144  * <li> thesky->postDraw( my_altitude );
145
146  * The current altitude in meters is passed to the postDraw() method
147  * so the clouds layers can be rendered correction from most distant
148  * to closest.
149
150  * Visibility Effects 
151
152  * Visibility and fog is important for correctly rendering the
153  * sky. You can inform SGSky of the current visibility by calling the
154  * set_visibility() method.
155
156  * When transitioning through clouds, it is nice to pull in the fog as
157  * you get close to the cloud layer to hide the fact that the clouds
158  * are drawn as a flat polygon. As you get nearer to the cloud layer
159  * it is also nice to temporarily pull in the visibility to simulate
160  * the effects of flying in and out of the puffy edge of the
161  * cloud. These effects can all be accomplished by calling the
162  * modify_vis() method.  The arguments allow you to specify your
163  * current altitude (which is then compared to the altitudes of the
164  * various cloud layers.) You can also specify a time factor which
165  * should be the length in seconds since the last time you called
166  * modify_vis(). The time_factor value allows the puffy cloud effect
167  * to be calculated correctly.
168
169  * The modify_vis() method alters the SGSky's internal idea of
170  * visibility, so you should subsequently call get_visibility() to get
171  * the actual modified visibility. You should then make the
172  * appropriate glFog() calls to setup fog properly for your scene.
173
174  * Accessor Methods 
175
176  * Once an instance of SGSky has been successfully initialized, there
177  * are a couple accessor methods you can use such as get_num_layers()
178  * to return the number of cloud layers, get_cloud_layer(i) to return
179  * cloud layer number i, get_visibility() to return the actual
180  * visibility as modified by the sky/cloud model.
181
182  */
183
184 class SGSky {
185
186 private:
187
188     // components of the sky
189     SGSkyDome *dome;
190     SGSun *oursun;
191     SGMoon *moon;
192     SGStars *planets;
193     SGStars *stars;
194     ssgSimpleState *cloud_mats[SG_MAX_CLOUD_TYPES];
195     layer_list_type cloud_layers;
196
197     ssgRoot *pre_root, *post_root;
198
199     ssgSelector *pre_selector, *post_selector;
200     ssgTransform *pre_transform, *post_transform;
201
202     SGPath tex_path;
203
204     // visibility
205     float visibility;
206     float effective_visibility;
207
208     // near cloud visibility state variables
209     bool in_puff;
210     double puff_length;         // in seconds
211     double puff_progression;    // in seconds
212     double ramp_up;             // in seconds
213     double ramp_down;           // in seconds
214
215 public:
216
217     /** Constructor */
218     SGSky( void );
219
220     /** Destructor */
221     ~SGSky( void );
222
223     /**
224      * Initialize the sky and connect the components to the scene
225      * graph at the provided branch.  See discussion in detailed class
226      * description.
227      * @param sun_size size of sun
228      * @param moon_size size of moon
229      * @param nplanets number of planets
230      * @param planet_data an array of planet right ascensions, declinations,
231      *        and magnitudes
232      * @param planet_dist distance from viewer to put the planets
233      * @param nstars number of stars
234      * @param star_data an array of star right ascensions, declinations,
235      *        and magnitudes
236      * @param star_dist distance from viewer to put the stars */
237     void build( double sun_size, double moon_size,
238                 int nplanets, sgdVec3 *planet_data, double planet_dist,
239                 int nstars, sgdVec3 *star_data, double star_dist );
240
241     /**
242      * Repaint the sky components based on current value of sun_angle,
243      * sky, and fog colors.  You can also specify new star and planet
244      * data so that we can optionally change the magnitude of these
245      * (for day/night transitions.)  See discussion in detailed
246      * class description.
247      *
248      * Sun and moon angles are specified in degrees relative to local up
249      * <li> 0 degrees = high noon
250      * <li> 90 degrees = sun rise/set
251      * <li> 180 degrees = darkest midnight
252      * @param sky_color the base sky color (for the top of the dome)
253      * @param fog_color the fog color (for the horizon)
254      * @param sun_angle the sun angle with the horizon (for sunrise/sunset
255      *        effects)
256      * @param moon_angle the moon angle (so we can make it more yellow
257      *        at the horizon)
258      * @param nplanets number of planets
259      * @param planet_data an array of planet right ascensions, declinations,
260      *        and magnitudes
261      * @param nstars number of stars
262      * @param star_data an array of star right ascensions, declinations,
263      *        and magnitudes
264      */
265     bool repaint( sgVec4 sky_color, sgVec4 fog_color,
266                   double sun_angle, double moon_angle,
267                   int nplanets, sgdVec3 *planet_data,
268                   int nstars, sgdVec3 *star_data );
269
270     /**
271      * Reposition the sky at the specified origin and orientation
272      *
273      * lon specifies a rotation about the Z axis
274      * lat specifies a rotation about the new Y axis
275      * spin specifies a rotation about the new Z axis (this allows
276      * additional orientation for the sunrise/set effects and is used
277      * by the skydome and perhaps clouds.  See discussion in detailed
278      * class description.
279      * @param view_pos specify your view position in world Cartesian
280      *        coordinates
281      * @param zero_elev the zero elevation position in world Cartesian
282      *        coordinates
283      * @param view_up the up vector in world Cartesian coordinates
284      * @param lon current longitude
285      * @param lat current latitude
286      * @param alt current altitude
287      * @param spin an offset angle for orienting the sky effects with the
288      *        sun position so sunset and sunrise effects look correct.
289      * @param gst GMT side real time
290      * @param sun_ra the sun's current right ascension
291      * @param sun_dec the sun's current declination
292      * @param sun_dist the sun's distance from the current view point
293      *        (to keep it inside your view volume.)
294      * @param moon_ra the moon's current right ascension
295      * @param moon_dec the moon's current declination
296      * @param moon_dist the moon's distance from the current view point. 
297      */
298     bool reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up,
299                      double lon, double lat, double alt, double spin,
300                      double gst, 
301                      double sun_ra, double sun_dec, double sun_dist,
302                      double moon_ra, double moon_dec, double moon_dist );
303
304     /**
305      * Modify the given visibility based on cloud layers, thickness,
306      * transition range, and simulated "puffs".  See discussion in detailed
307      * class description.
308      * @param alt current altitude
309      * @param time_factor amount of time since modify_vis() last called so
310      *        we can scale effect rates properly despite variable frame rates.
311      */
312     void modify_vis( float alt, float time_factor );
313
314     /**
315      * Draw background portions of the sky ... do this before you draw
316      * the rest of your scene.  See discussion in detailed
317      * class description.
318      */
319     void preDraw();
320
321     /**
322      * Draw translucent clouds ... do this after you've drawn all the
323      * oapaque elements of your scene.  See discussion in detailed
324      * class description.
325      * @param alt current altitude
326      */
327     void postDraw( float alt );
328
329     /** 
330      * Specify the texture path (optional, defaults to current directory)
331      * @param path base path to texture locations
332      */
333     inline void texture_path( const string& path ) {
334         tex_path = SGPath( path );
335     }
336
337     /** Enable drawing of the sky. */
338     inline void enable() {
339         pre_selector->select( 1 );
340         post_selector->select( 1 );
341     }
342
343     /**
344      * Disable drawing of the sky in the scene graph.  The leaf node is still
345      * there, how ever it won't be traversed on by ssgCullandRender()
346      */
347     inline void disable() {
348         pre_selector->select( 0 );
349         post_selector->select( 0 );
350     }
351
352     /**
353      * Add a cloud layer (distances in meters).
354      * @param asl cloud base height above sea level
355      * @param thickness cloud layer thickness
356      * @param transition thickness of transition layer from 100% out of 
357      *        cloud to 100% in cloud.  Used for scudded clouds effect.
358      * @param span horizontal size of cloud object
359      * @param type type of cloud (chosen from available cloud types)
360      */
361     void add_cloud_layer( double asl, double thickness,
362                           double transition, double span,
363                           SGCloudType type );
364
365     /**
366      * Add a cloud layer (distances in meters).
367      * @param asl cloud base height above sea level
368      * @param thickness cloud layer thickness
369      * @param transition thickness of transition layer from 100% out of 
370      *        cloud to 100% in cloud.  Used for scudded clouds effect.
371      * @param span horizontal size of cloud object
372      * @param tex_path file name of a cloud texture
373      */
374     void add_cloud_layer( double asl, double thickness,
375                           double transition, double span,
376                           const string &tex_path );
377
378     /**
379      * Add a cloud layer (distances in meters).
380      * @param asl cloud base height above sea level
381      * @param thickness cloud layer thickness
382      * @param transition thickness of transition layer from 100% out of 
383      *        cloud to 100% in cloud.  Used for scudded clouds effect.
384      * @param span horizontal size of cloud object
385      * @param state pointer to an existing ssgSimpleState
386      */
387     void add_cloud_layer( double asl, double thickness,
388                           double transition, double span,
389                           ssgSimpleState *state );
390
391     /** @return number of cloud layers */
392     inline int get_num_layers() const { return cloud_layers.size(); }
393
394     /**
395      * Get a cloud layer
396      * @param i which cloud layer
397      * @return cloud layer number i */
398     inline SGCloudLayer *get_cloud_layer( int i ) const {
399         return cloud_layers[i];
400     }
401
402     /** @return current effective visibility */
403     inline float get_visibility() const { return effective_visibility; }
404
405     /** Set desired clear air visibility.
406      * @param v visibility in meters
407      */
408     inline void set_visibility( float v ) {
409         effective_visibility = visibility = v;
410     }
411 };
412
413
414 #endif // _SG_SKY_HXX
415
416