3 * Provides a class to model a realistic (time/date/position) based sky.
6 // Written by Curtis Olson, started December 1997.
7 // SSG-ified by Curtis Olson, February 2000.
9 // Copyright (C) 1997-2000 Curtis L. Olson - http://www.flightgear.org/~curt
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.
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.
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.
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>
39 #include <osg/ref_ptr>
40 #include <osg/MatrixTransform>
43 #include <simgear/ephemeris/ephemeris.hxx>
44 #include <simgear/math/SGMath.hxx>
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>
53 class SGReaderWriterOptions;
58 SGVec3d pos; //!< View position in world Cartesian coordinates.
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.
73 SGVec3f adj_sky_color;
81 * \anchor SGSky-details
83 * A class to model a realistic (time/date/position) based sky.
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.
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.
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.
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
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
135 * Positioning Sky Objects
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
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.
168 * A typical application might do the following:
170 * \li thesky->preDraw( my_altitude );
171 * \li thesky->drawUpperClouds();
172 * \li ssgCullAndDraw ( myscene ) ;
173 * \li thesky->drawLowerClouds();
175 * The current altitude in meters is passed to the preDraw() method
176 * so the clouds layers can be rendered correction from most distant
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.
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.
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.
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.
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;
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;
228 osg::ref_ptr<osg::Group> pre_root, pre_transform;
229 osg::ref_ptr<osg::Switch> cloud_root;
231 osg::ref_ptr<osg::MatrixTransform> _ephTransform;
237 float effective_visibility;
241 // near cloud visibility state variables
243 double puff_length; // in seconds
244 double puff_progression; // in seconds
245 double ramp_up; // in seconds
246 double ramp_down; // in seconds
249 bool clouds_3d_enabled;
252 double clouds_3d_density;
266 * Initialize the sky and connect the components to the scene
267 * graph at the provided branch.
269 * @note See discussion in \ref SGSky-details "detailed class description".
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
279 void build( double h_radius_m,
283 const SGEphemeris& eph,
284 SGPropertyNode *node,
285 simgear::SGReaderWriterOptions* options );
288 * Repaint the sky components based on current sun angle, and sky and fog
291 * @note See discussion in \ref SGSky-details "detailed class description".
293 * @param sky_color The base sky color (for the top of the dome)
294 * @param eph Current positions of planets and stars
296 bool repaint( const SGSkyColor &sky_color,
297 const SGEphemeris& eph );
300 * Reposition the sky at the specified origin and orientation.
302 * @note See discussion in \ref SGSky-details "detailed class description".
305 bool reposition( const SGSkyState& sky_state,
306 const SGEphemeris& eph,
310 * Modify the given visibility based on cloud layers, thickness,
311 * transition range, and simulated "puffs".
313 * @note See discussion in \ref SGSky-details "detailed class description".
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.
319 void modify_vis( float alt, float time_factor );
321 osg::Group* getPreRoot() { return pre_root.get(); }
322 osg::Group* getCloudRoot() { return cloud_root.get(); }
325 * Specify the texture path (optional, defaults to current directory)
327 * @param path Base path to texture locations
329 void texture_path( const std::string& path );
332 * Get the current sun color
334 inline SGVec4f get_sun_color() { return oursun->get_color(); }
337 * Get the current scene color
339 inline SGVec4f get_scene_color() { return oursun->get_scene_color(); }
344 * Transfer pointer ownership to this object.
346 * @param layer The new cloud layer to add.
348 void add_cloud_layer (SGCloudLayer * layer);
352 * Get a cloud layer (const).
354 * Pointer ownership remains with this object.
356 * @param i The index of the cloud layer, zero-based.
357 * @return A const pointer to the cloud layer.
359 const SGCloudLayer * get_cloud_layer (int i) const;
363 * Get a cloud layer (non-const).
365 * Pointer ownership remains with this object.
367 * @param i The index of the cloud layer, zero-based.
368 * @return A non-const pointer to the cloud layer.
370 SGCloudLayer * get_cloud_layer (int i);
374 * Return the number of cloud layers currently available.
376 * @return The cloud layer count.
378 int get_cloud_layer_count () const;
381 /** @return current effective visibility */
382 float get_visibility() const { return effective_visibility; }
384 /** Set desired clear air visibility.
385 * @param v visibility in meters
387 void set_visibility( float v );
389 /** Get 3D cloud density */
390 double get_3dCloudDensity() const;
392 /** Set 3D cloud density
393 * @param density 3D cloud density
395 void set_3dCloudDensity(double density);
397 /** Get 3D cloud visibility range*/
398 float get_3dCloudVisRange() const;
400 /** Set 3D cloud visibility range
402 * @param vis 3D cloud visibility range
404 void set_3dCloudVisRange(float vis);
406 /** Get 3D cloud impostor distance*/
407 float get_3dCloudImpostorDistance() const;
409 /** Set 3D cloud impostor distance
411 * @param vis 3D cloud impostor distance
413 void set_3dCloudImpostorDistance(float vis);
415 /** Get 3D cloud LoD1 Range*/
416 float get_3dCloudLoD1Range() const;
418 /** Set 3D cloud LoD1 Range
419 * @param vis LoD1 Range
421 void set_3dCloudLoD1Range(float vis);
423 /** Get 3D cloud LoD2 Range*/
424 float get_3dCloudLoD2Range() const;
426 /** Set 3D cloud LoD2 Range
427 * @param vis LoD2 Range
429 void set_3dCloudLoD2Range(float vis);
431 /** Get 3D cloud impostor usage */
432 bool get_3dCloudUseImpostors() const;
434 /** Set 3D cloud impostor usage
436 * @param imp whether use impostors for 3D clouds
438 void set_3dCloudUseImpostors(bool imp);
440 /** Get 3D cloud wrapping */
441 bool get_3dCloudWrap() const;
443 /** Set 3D cloud wrapping
444 * @param wrap whether to wrap 3D clouds
446 void set_3dCloudWrap(bool wrap);
448 void set_clouds_enabled(bool enabled);
451 #endif // _SG_SKY_HXX