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