head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.40; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.58; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.04; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.22.01; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# sky.cxx

    00001 // sky.cxx -- ssg based sky model
    00002 //
    00003 // Written by Curtis Olson, started December 1997.
    00004 // SSG-ified by Curtis Olson, February 2000.
    00005 //
    00006 // Copyright (C) 1997-2000  Curtis L. Olson  - curt@@flightgear.org
    00007 //
    00008 // This library is free software; you can redistribute it and/or
    00009 // modify it under the terms of the GNU Library General Public
    00010 // License as published by the Free Software Foundation; either
    00011 // version 2 of the License, or (at your option) any later version.
    00012 //
    00013 // This library is distributed in the hope that it will be useful,
    00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016 // Library General Public License for more details.
    00017 //
    00018 // You should have received a copy of the GNU Library General Public
    00019 // License along with this library; if not, write to the
    00020 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021 // Boston, MA  02111-1307, USA.
    00022 //
    00023 // $Id: sky.cxx,v 1.18 2002/07/18 20:30:18 david Exp $
    00024
    00025
    00026 #include <plib/sg.h>
    00027 #include <plib/ssg.h>
    00028
    00029 #include <simgear/math/sg_random.h>
    00030
    00031 #include "sky.hxx"
    00032
    00033
    00034 // Constructor
    00035 SGSky::SGSky( void ) {
    00036     effective_visibility = visibility = 10000.0;
    00037
    00038     // near cloud visibility state variables
    00039     in_puff = false;
    00040     puff_length = 0;
    00041     puff_progression = 0;
    00042     ramp_up = 0.15;
    00043     ramp_down = 0.15;
    00044     // ramp_up = 4.0;
    00045     // ramp_down = 4.0;
    00046 }
    00047
    00048
    00049 // Destructor
    00050 SGSky::~SGSky( void )
    00051 {
    00052     for (unsigned int i = 0; i < cloud_layers.size(); i++)
    00053         delete cloud_layers[i];
    00054 }
    00055
    00056
    00057 // initialize the sky and connect the components to the scene graph at
    00058 // the provided branch
    00059 void SGSky::build(  double sun_size, double moon_size,
    00060                     int nplanets, sgdVec3 *planet_data,
    00061                     double planet_dist,
    00062                     int nstars, sgdVec3 *star_data, double star_dist )
    00063 {
    00064     pre_root = new ssgRoot;
    00065     post_root = new ssgRoot;
    00066
    00067     pre_selector = new ssgSelector;
    00068     post_selector = new ssgSelector;
    00069
    00070     pre_transform = new ssgTransform;
    00071     post_transform = new ssgTransform;
    00072
    00073     dome = new SGSkyDome;
    00074     pre_transform -> addKid( dome->build() );
    00075
    00076     planets = new SGStars;
    00077     pre_transform -> addKid( planets->build(nplanets, planet_data,
    00078                                             planet_dist)
    00079                              );
    00080
    00081     stars = new SGStars;
    00082     pre_transform -> addKid( stars->build(nstars, star_data, star_dist) );
    00083
    00084     moon = new SGMoon;
    00085     pre_transform -> addKid( moon->build(tex_path, moon_size) );
    00086
    00087     oursun = new SGSun;
    00088     pre_transform -> addKid( oursun->build(tex_path, sun_size) );
    00089
    00090     pre_selector->addKid( pre_transform );
    00091     pre_selector->clrTraversalMaskBits( SSGTRAV_HOT );
    00092
    00093     post_selector->addKid( post_transform );
    00094     post_selector->clrTraversalMaskBits( SSGTRAV_HOT );
    00095
    00096     pre_root->addKid( pre_selector );
    00097     post_root->addKid( post_selector );
    00098 }
    00099
    00100
    00101 // repaint the sky components based on current value of sun_angle,
    00102 // sky, and fog colors.
    00103 //
    00104 // sun angle in degrees relative to verticle
    00105 // 0 degrees = high noon
    00106 // 90 degrees = sun rise/set
    00107 // 180 degrees = darkest midnight
    00108 bool SGSky::repaint( sgVec4 sky_color, sgVec4 fog_color,
    00109                      double sun_angle, double moon_angle,
    00110                      int nplanets, sgdVec3 *planet_data,
    00111                      int nstars, sgdVec3 *star_data )
    00112 {
    00113     if ( effective_visibility > 1000.0 ) {
    00114         enable();
    00115         dome->repaint( sky_color, fog_color, sun_angle, effective_visibility );
    00116         oursun->repaint( sun_angle );
    00117         moon->repaint( moon_angle );
    00118         planets->repaint( sun_angle, nplanets, planet_data );
    00119         stars->repaint( sun_angle, nstars, star_data );
    00120
    00121         for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
    00122             cloud_layers[i]->repaint( fog_color );
    00123         }
    00124     } else {
    00125         // turn off sky
    00126         disable();
    00127     }
    00128
    00129     return true;
    00130 }
    00131
    00132
    00133 // reposition the sky at the specified origin and orientation
    00134 //
    00135 // lon specifies a rotation about the Z axis
    00136 // lat specifies a rotation about the new Y axis
    00137 // spin specifies a rotation about the new Z axis (this allows
    00138 // additional orientation for the sunrise/set effects and is used by
    00139 // the skydome and perhaps clouds.
    00140 bool SGSky::reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up,
    00141                         double lon, double lat, double alt, double spin,
    00142                         double gst,
    00143                         double sun_ra, double sun_dec, double sun_dist,
    00144                         double moon_ra, double moon_dec, double moon_dist )
    00145 {
    00146     double angle = gst * 15;    // degrees
    00147     dome->reposition( zero_elev, lon, lat, spin );
    00148     oursun->reposition( view_pos, angle, sun_ra, sun_dec, sun_dist );
    00149     moon->reposition( view_pos, angle, moon_ra, moon_dec, moon_dist );
    00150     planets->reposition( view_pos, angle );
    00151     stars->reposition( view_pos, angle );
    00152
    00153     for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
    00154         cloud_layers[i]->reposition( zero_elev, view_up, lon, lat, alt );
    00155     }
    00156
    00157     return true;
    00158 }
    00159
    00160
    00161 // draw background portions of the sky ... do this before you draw the
    00162 // rest of your scene.
    00163 void SGSky::preDraw() {
    00164     ssgCullAndDraw( pre_root );
    00165 }
    00166
    00167
    00168 // draw translucent clouds ... do this after you've drawn all the
    00169 // oapaque elements of your scene.
    00170 void SGSky::postDraw( float alt ) {
    00171     float slop = 5.0;           // if we are closer than this to a cloud layer,
    00172                                 // don't draw clouds
    00173
    00174     int in_cloud = -1;          // cloud we are in
    00175
    00176     int i;
    00177
    00178     // check where we are relative to the cloud layers
    00179     for ( i = 0; i < (int)cloud_layers.size(); ++i ) {
    00180         float asl = cloud_layers[i]->getElevation_m();
    00181         float thickness = cloud_layers[i]->getThickness_m();
    00182
    00183         if ( alt < asl - slop ) {
    00184             // below cloud layer
    00185         } else if ( alt < asl + thickness + slop ) {
    00186             // in cloud layer
    00187
    00188             // bail now and don't draw any clouds
    00189             in_cloud = i;
    00190         } else {
    00191             // above cloud layer
    00192         }
    00193     }
    00194
    00195     // determine rendering order
    00196     int pos = 0;
    00197     while ( pos < (int)cloud_layers.size() &&
    00198             alt > cloud_layers[pos]->getElevation_m())
    00199     {
    00200         ++pos;
    00201     }
    00202
    00203     if ( pos == 0 ) {
    00204         // we are below all the cloud layers, draw top to bottom
    00205         for ( i = cloud_layers.size() - 1; i >= 0; --i ) {
    00206             if ( i != in_cloud ) {
    00207                 cloud_layers[i]->draw();
    00208             }
    00209         }
    00210     } else if ( pos >= (int)cloud_layers.size() ) {
    00211         // we are above all the cloud layers, draw bottom to top
    00212         for ( i = 0; i < (int)cloud_layers.size(); ++i ) {
    00213             if ( i != in_cloud ) {
    00214                 cloud_layers[i]->draw();
    00215             }
    00216         }
    00217     } else {
    00218         // we are between cloud layers, draw lower layers bottom to
    00219         // top and upper layers top to bottom
    00220         for ( i = 0; i < pos; ++i ) {
    00221             if ( i != in_cloud ) {
    00222                 cloud_layers[i]->draw();
    00223             }
    00224         }
    00225         for ( i = cloud_layers.size() - 1; i >= pos; --i ) {
    00226             if ( i != in_cloud ) {
    00227                 cloud_layers[i]->draw();
    00228             }
    00229         }
    00230     }
    00231 }
    00232
    00233 void
    00234 SGSky::add_cloud_layer( SGCloudLayer * layer )
    00235 {
    00236     cloud_layers.push_back(layer);
    00237 }
    00238
    00239 const SGCloudLayer *
    00240 SGSky::get_cloud_layer (int i) const
    00241 {
    00242     return cloud_layers[i];
    00243 }
    00244
    00245 SGCloudLayer *
    00246 SGSky::get_cloud_layer (int i)
    00247 {
    00248     return cloud_layers[i];
    00249 }
    00250
    00251 int
    00252 SGSky::get_cloud_layer_count () const
    00253 {
    00254     return cloud_layers.size();
    00255 }
    00256
    00257 // modify the current visibility based on cloud layers, thickness,
    00258 // transition range, and simulated "puffs".
    00259 void SGSky::modify_vis( float alt, float time_factor ) {
    00260     float effvis = visibility;
    00261
    00262     for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
    00263         float asl = cloud_layers[i]->getElevation_m();
    00264         float thickness = cloud_layers[i]->getThickness_m();
    00265         float transition = cloud_layers[i]->getTransition_m();
    00266
    00267         double ratio = 1.0;
    00268
    00269         if ( alt < asl - transition ) {
    00270             // below cloud layer
    00271             ratio = 1.0;
    00272         } else if ( alt < asl ) {
    00273             // in lower transition
    00274             ratio = (asl - alt) / transition;
    00275         } else if ( alt < asl + thickness ) {
    00276             // in cloud layer
    00277             ratio = 0.0;
    00278         } else if ( alt < asl + thickness + transition ) {
    00279             // in upper transition
    00280             ratio = (alt - (asl + thickness)) / transition;
    00281         } else {
    00282             // above cloud layer
    00283             ratio = 1.0;
    00284         }
    00285
    00286         // accumulate effects from multiple cloud layers
    00287         effvis *= ratio;
    00288
    00289         if ( ratio < 1.0 ) {
    00290             if ( ! in_puff ) {
    00291                 // calc chance of entering cloud puff
    00292                 double rnd = sg_random();
    00293                 double chance = rnd * rnd * rnd;
    00294                 if ( chance > 0.95 /* * (diff - 25) / 50.0 */ ) {
    00295                     in_puff = true;
    00296                     puff_length = sg_random() * 2.0; // up to 2 seconds
    00297                     puff_progression = 0.0;
    00298                 }
    00299             }
    00300
    00301             if ( in_puff ) {
    00302                 // modify actual_visibility based on puff envelope
    00303
    00304                 if ( puff_progression <= ramp_up ) {
    00305                     double x = 0.5 * SGD_PI * puff_progression / ramp_up;
    00306                     double factor = 1.0 - sin( x );
    00307                     // cout << "ramp up = " << puff_progression
    00308                     //      << "  factor = " << factor << endl;
    00309                     effvis = effvis * factor;
    00310                 } else if ( puff_progression >= ramp_up + puff_length ) {
    00311                     double x = 0.5 * SGD_PI *
    00312                         (puff_progression - (ramp_up + puff_length)) /
    00313                         ramp_down;
    00314                     double factor = sin( x );
    00315                     // cout << "ramp down = "
    00316                     //      << puff_progression - (ramp_up + puff_length)
    00317                     //      << "  factor = " << factor << endl;
    00318                     effvis = effvis * factor;
    00319                 } else {
    00320                     effvis = 0.0;
    00321                 }
    00322
    00323                 /* cout << "len = " << puff_length
    00324                    << "  x = " << x
    00325                    << "  factor = " << factor
    00326                    << "  actual_visibility = " << actual_visibility
    00327                    << endl; */
    00328
    00329                 // time_factor = ( global_multi_loop *
    00330                 //                 current_options.get_speed_up() ) /
    00331                 //                (double)current_options.get_model_hz();
    00332
    00333                 puff_progression += time_factor;
    00334                 // cout << "time factor = " << time_factor << endl;
    00335
    00336                 /* cout << "gml = " << global_multi_loop
    00337                    << "  speed up = " << current_options.get_speed_up()
    00338                    << "  hz = " << current_options.get_model_hz() << endl;
    00339                    */
    00340
    00341                 if ( puff_progression > puff_length + ramp_up + ramp_down) {
    00342                     in_puff = false;
    00343                 }
    00344             }
    00345
    00346             // never let visibility drop below 25 meters
    00347             if ( effvis <= 25.0 ) {
    00348                 effvis = 25.0;
    00349             }
    00350         }
    00351     } // for
    00352
    00353     effective_visibility = effvis;
    00354 }

@ 1.3 log @Oops, try again. @ text @d363 1 a363 1