00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 # include <simgear_config.h>
00026 #endif
00027
00028 #include "sky.hxx"
00029 #include "cloudfield.hxx"
00030 #include "newcloud.hxx"
00031
00032 #include <simgear/math/sg_random.h>
00033 #include <simgear/scene/util/RenderConstants.hxx>
00034
00035 #include <osg/StateSet>
00036 #include <osg/Depth>
00037
00038
00039 SGSky::SGSky( void ) {
00040 effective_visibility = visibility = 10000.0;
00041
00042
00043 in_puff = false;
00044 puff_length = 0;
00045 puff_progression = 0;
00046 ramp_up = 0.15;
00047 ramp_down = 0.15;
00048
00049 in_cloud = -1;
00050
00051 clouds_3d_enabled = false;
00052 clouds_3d_density = 0.8;
00053
00054 pre_root = new osg::Group;
00055 pre_root->setNodeMask(simgear::BACKGROUND_BIT);
00056 osg::StateSet* preStateSet = new osg::StateSet;
00057 preStateSet->setAttribute(new osg::Depth(osg::Depth::LESS, 0.0, 1.0,
00058 false));
00059 pre_root->setStateSet(preStateSet);
00060 cloud_root = new osg::Group;
00061 cloud_root->setNodeMask(simgear::MODEL_BIT);
00062
00063 pre_selector = new osg::Switch;
00064
00065 pre_transform = new osg::Group;
00066
00067 _ephTransform = new osg::MatrixTransform;
00068 }
00069
00070
00071
00072 SGSky::~SGSky( void )
00073 {
00074 }
00075
00076
00077
00078
00079 void SGSky::build( double h_radius_m, double v_radius_m,
00080 double sun_size, double moon_size,
00081 const SGEphemeris& eph, SGPropertyNode *property_tree_node )
00082 {
00083 dome = new SGSkyDome;
00084 pre_transform->addChild( dome->build( h_radius_m, v_radius_m ) );
00085
00086 pre_transform->addChild(_ephTransform.get());
00087 planets = new SGStars;
00088 _ephTransform->addChild( planets->build(eph.getNumPlanets(), eph.getPlanets(), h_radius_m) );
00089
00090 stars = new SGStars;
00091 _ephTransform->addChild( stars->build(eph.getNumStars(), eph.getStars(), h_radius_m) );
00092
00093 moon = new SGMoon;
00094 _ephTransform->addChild( moon->build(tex_path, moon_size) );
00095
00096 oursun = new SGSun;
00097 _ephTransform->addChild( oursun->build(tex_path, sun_size, property_tree_node ) );
00098
00099 pre_selector->addChild( pre_transform.get() );
00100
00101 pre_root->addChild( pre_selector.get() );
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool SGSky::repaint( const SGSkyColor &sc, const SGEphemeris& eph )
00113 {
00114 if ( effective_visibility > 1000.0 ) {
00115 enable();
00116 dome->repaint( sc.adj_sky_color, sc.sky_color, sc.fog_color,
00117 sc.sun_angle, effective_visibility );
00118
00119 stars->repaint( sc.sun_angle, eph.getNumStars(), eph.getStars() );
00120 planets->repaint( sc.sun_angle, eph.getNumPlanets(), eph.getPlanets() );
00121 oursun->repaint( sc.sun_angle, effective_visibility );
00122 moon->repaint( sc.moon_angle );
00123
00124 for ( unsigned i = 0; i < cloud_layers.size(); ++i ) {
00125 if (cloud_layers[i]->getCoverage() != SGCloudLayer::SG_CLOUD_CLEAR){
00126 cloud_layers[i]->repaint( sc.cloud_color );
00127 }
00128 }
00129 } else {
00130
00131 disable();
00132 }
00133 SGCloudField::updateFog((double)effective_visibility,
00134 osg::Vec4f(toOsg(sc.fog_color), 1.0f));
00135 return true;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145 bool SGSky::reposition( const SGSkyState &st, const SGEphemeris& eph, double dt )
00146 {
00147 double angle = st.gst * 15;
00148 double angleRad = SGMiscd::deg2rad(angle);
00149
00150 SGVec3f zero_elev, view_up;
00151 double lon, lat, alt;
00152
00153 SGGeod geodZeroViewPos = SGGeod::fromGeodM(st.pos_geod, 0);
00154 zero_elev = toVec3f( SGVec3d::fromGeod(geodZeroViewPos) );
00155
00156
00157 SGQuatd hlOr = SGQuatd::fromLonLat(st.pos_geod);
00158 view_up = toVec3f(hlOr.backTransform(-SGVec3d::e3()));
00159
00160
00161 lon = st.pos_geod.getLongitudeRad();
00162 lat = st.pos_geod.getLatitudeRad();
00163 alt = st.pos_geod.getElevationM();
00164
00165 dome->reposition( zero_elev, alt, lon, lat, st.spin );
00166
00167 osg::Matrix m = osg::Matrix::rotate(angleRad, osg::Vec3(0, 0, -1));
00168 m.postMultTranslate(toOsg(st.pos));
00169 _ephTransform->setMatrix(m);
00170
00171 double sun_ra = eph.getSunRightAscension();
00172 double sun_dec = eph.getSunDeclination();
00173 oursun->reposition( sun_ra, sun_dec, st.sun_dist, lat, alt, st.sun_angle );
00174
00175 double moon_ra = eph.getMoonRightAscension();
00176 double moon_dec = eph.getMoonDeclination();
00177 moon->reposition( moon_ra, moon_dec, st.moon_dist );
00178
00179 for ( unsigned i = 0; i < cloud_layers.size(); ++i ) {
00180 if ( cloud_layers[i]->getCoverage() != SGCloudLayer::SG_CLOUD_CLEAR ) {
00181 cloud_layers[i]->reposition( zero_elev, view_up, lon, lat, alt, dt);
00182 } else
00183 cloud_layers[i]->getNode()->setAllChildrenOff();
00184 }
00185
00186 return true;
00187 }
00188
00189 void
00190 SGSky::add_cloud_layer( SGCloudLayer * layer )
00191 {
00192 cloud_layers.push_back(layer);
00193 cloud_root->addChild(layer->getNode());
00194
00195 layer->set_enable3dClouds(clouds_3d_enabled);
00196 }
00197
00198 const SGCloudLayer *
00199 SGSky::get_cloud_layer (int i) const
00200 {
00201 return cloud_layers[i];
00202 }
00203
00204 SGCloudLayer *
00205 SGSky::get_cloud_layer (int i)
00206 {
00207 return cloud_layers[i];
00208 }
00209
00210 int
00211 SGSky::get_cloud_layer_count () const
00212 {
00213 return cloud_layers.size();
00214 }
00215
00216 double SGSky::get_3dCloudDensity() const {
00217 return SGNewCloud::getDensity();
00218 }
00219
00220 void SGSky::set_3dCloudDensity(double density)
00221 {
00222 SGNewCloud::setDensity(density);
00223 }
00224
00225 float SGSky::get_3dCloudVisRange() const {
00226 return SGCloudField::getVisRange();
00227 }
00228
00229 void SGSky::set_3dCloudVisRange(float vis)
00230 {
00231 SGCloudField::setVisRange(vis);
00232 for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
00233 cloud_layers[i]->get_layer3D()->applyVisRange();
00234 }
00235 }
00236
00237 void SGSky::texture_path( const string& path ) {
00238 tex_path = SGPath( path );
00239 }
00240
00241
00242
00243 void SGSky::modify_vis( float alt, float time_factor ) {
00244 float effvis = visibility;
00245
00246 for ( int i = 0; i < (int)cloud_layers.size(); ++i ) {
00247 float asl = cloud_layers[i]->getElevation_m();
00248 float thickness = cloud_layers[i]->getThickness_m();
00249 float transition = cloud_layers[i]->getTransition_m();
00250
00251 double ratio = 1.0;
00252
00253 if ( cloud_layers[i]->getCoverage() == SGCloudLayer::SG_CLOUD_CLEAR ) {
00254
00255 ratio = 1.0;
00256 } else if ( alt < asl - transition ) {
00257
00258 ratio = 1.0;
00259 } else if ( alt < asl ) {
00260
00261 ratio = (asl - alt) / transition;
00262 } else if ( alt < asl + thickness ) {
00263
00264 ratio = 0.0;
00265 } else if ( alt < asl + thickness + transition ) {
00266
00267 ratio = (alt - (asl + thickness)) / transition;
00268 } else {
00269
00270 ratio = 1.0;
00271 }
00272
00273 if ( cloud_layers[i]->getCoverage() == SGCloudLayer::SG_CLOUD_CLEAR ||
00274 cloud_layers[i]->get_layer3D()->defined3D) {
00275
00276
00277 } else if ( (cloud_layers[i]->getCoverage() ==
00278 SGCloudLayer::SG_CLOUD_FEW)
00279 || (cloud_layers[i]->getCoverage() ==
00280 SGCloudLayer::SG_CLOUD_SCATTERED) )
00281 {
00282
00283
00284
00285
00286 float temp = ratio * 2.0;
00287 if ( temp > 1.0 ) { temp = 1.0; }
00288 cloud_layers[i]->setAlpha( temp );
00289
00290
00291 } else {
00292
00293
00294
00295 cloud_layers[i]->setAlpha( 1.0 );
00296
00297
00298
00299 effvis *= ratio;
00300 }
00301
00302 #if 0
00303 if ( ratio < 1.0 ) {
00304 if ( ! in_puff ) {
00305
00306 double rnd = sg_random();
00307 double chance = rnd * rnd * rnd;
00308 if ( chance > 0.95 ) {
00309 in_puff = true;
00310 puff_length = sg_random() * 2.0;
00311 puff_progression = 0.0;
00312 }
00313 }
00314
00315 if ( in_puff ) {
00316
00317
00318 if ( puff_progression <= ramp_up ) {
00319 double x = SGD_PI_2 * puff_progression / ramp_up;
00320 double factor = 1.0 - sin( x );
00321
00322
00323 effvis = effvis * factor;
00324 } else if ( puff_progression >= ramp_up + puff_length ) {
00325 double x = SGD_PI_2 *
00326 (puff_progression - (ramp_up + puff_length)) /
00327 ramp_down;
00328 double factor = sin( x );
00329
00330
00331
00332 effvis = effvis * factor;
00333 } else {
00334 effvis = 0.0;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 puff_progression += time_factor;
00348
00349
00350
00351
00352
00353
00354
00355 if ( puff_progression > puff_length + ramp_up + ramp_down) {
00356 in_puff = false;
00357 }
00358 }
00359 }
00360 #endif
00361
00362
00363 if ( effvis <= 25.0 ) {
00364 effvis = 25.0;
00365 }
00366
00367 }
00368
00369 effective_visibility = effvis;
00370 }
00371
00372