From de66c74a91fb8da6107b5e4abd44c0cfac90cba1 Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 20 Jun 2000 20:31:48 +0000 Subject: [PATCH] Updating cloud code. --- simgear/sky/cloud.cxx | 47 +++++++--- simgear/sky/cloud.hxx | 16 +++- simgear/sky/sky.cxx | 193 ++++++++++++++++++++++++++++++++++++++---- simgear/sky/sky.hxx | 30 +++++-- 4 files changed, 251 insertions(+), 35 deletions(-) diff --git a/simgear/sky/cloud.cxx b/simgear/sky/cloud.cxx index 20215a18..7f513e99 100644 --- a/simgear/sky/cloud.cxx +++ b/simgear/sky/cloud.cxx @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -43,9 +44,15 @@ SGCloudLayer::~SGCloudLayer( void ) { // build the moon object -ssgBranch * SGCloudLayer::build( FGPath path, double s, double asl ) { +void SGCloudLayer::build( FGPath path, double s, double asl, double thickness, + double transition ) +{ + scale = 2000.0; layer_asl = asl; + layer_thickness = thickness; + layer_transition = transition; + size = s; last_lon = last_lat = -999.0f; @@ -76,25 +83,27 @@ ssgBranch * SGCloudLayer::build( FGPath path, double s, double asl ) { sgSetVec4( color, 1.0f, 1.0f, 1.0f, 1.0f ); sgSetVec3( vertex, -size, -size, 0.0f ); - sgSetVec2( tc, 0.0f, 0.0f ); + sgVec2 base; + sgSetVec2( base, fg_random(), fg_random() ); + sgSetVec2( tc, base[0], base[1] ); cl->add( color ); vl->add( vertex ); tl->add( tc ); sgSetVec3( vertex, size, -size, 0.0f ); - sgSetVec2( tc, size / 1000.0f, 0.0f ); + sgSetVec2( tc, base[0] + size / scale, base[1] ); cl->add( color ); vl->add( vertex ); tl->add( tc ); sgSetVec3( vertex, -size, size, 0.0f ); - sgSetVec2( tc, 0.0f, size / 1000.0f ); + sgSetVec2( tc, base[0], base[1] + size / scale ); cl->add( color ); vl->add( vertex ); tl->add( tc ); sgSetVec3( vertex, size, size, 0.0f ); - sgSetVec2( tc, size / 1000.0f, size / 1000.0f ); + sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale ); cl->add( color ); vl->add( vertex ); tl->add( tc ); @@ -113,7 +122,8 @@ ssgBranch * SGCloudLayer::build( FGPath path, double s, double asl ) { // moon_transform->addKid( halo ); layer_transform->addKid( layer ); - return layer_transform; + layer_root = new ssgRoot; + layer_root->addKid( layer_transform ); } @@ -135,7 +145,9 @@ bool SGCloudLayer::repaint( sgVec3 fog_color ) { // lat specifies a rotation about the new Y axis // spin specifies a rotation about the new Z axis (and orients the // sunrise/set effects -bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat ) { +bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat, + double alt ) +{ sgMat4 T1, LON, LAT; sgVec3 axis; @@ -143,7 +155,11 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat ) { sgVec3 asl_offset; sgCopyVec3( asl_offset, up ); sgNormalizeVec3( asl_offset ); - sgScaleVec3( asl_offset, layer_asl ); + if ( alt <= layer_asl ) { + sgScaleVec3( asl_offset, layer_asl ); + } else { + sgScaleVec3( asl_offset, layer_asl + layer_thickness ); + } // cout << "asl_offset = " << asl_offset[0] << "," << asl_offset[1] // << "," << asl_offset[2] << endl; sgAddVec3( asl_offset, p ); @@ -193,8 +209,8 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat ) { calc_gc_course_dist( dest, start, &course, &dist ); // cout << "course = " << course << ", dist = " << dist << endl; - double xoff = cos( course ) * dist / 500.0; - double yoff = sin( course ) * dist / 500.0; + double xoff = cos( course ) * dist / (2 * scale); + double yoff = sin( course ) * dist / (2 * scale); // cout << "xoff = " << xoff << ", yoff = " << yoff << endl; @@ -212,13 +228,13 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat ) { // cout << "base = " << base[0] << "," << base[1] << endl; tc = tl->get( 1 ); - sgSetVec2( tc, base[0] + size / 1000.0f, base[1] ); + sgSetVec2( tc, base[0] + size / scale, base[1] ); tc = tl->get( 2 ); - sgSetVec2( tc, base[0], base[1] + size / 1000.0f ); + sgSetVec2( tc, base[0], base[1] + size / scale ); tc = tl->get( 3 ); - sgSetVec2( tc, base[0] + size / 1000.0f, base[1] + size / 1000.0f ); + sgSetVec2( tc, base[0] + size / scale, base[1] + size / scale ); last_lon = lon; last_lat = lat; @@ -226,3 +242,8 @@ bool SGCloudLayer::reposition( sgVec3 p, sgVec3 up, double lon, double lat ) { return true; } + + +void SGCloudLayer::draw() { + ssgCullAndDraw( layer_root ); +} diff --git a/simgear/sky/cloud.hxx b/simgear/sky/cloud.hxx index 37deac19..1da11bb5 100644 --- a/simgear/sky/cloud.hxx +++ b/simgear/sky/cloud.hxx @@ -32,6 +32,7 @@ class SGCloudLayer { + ssgRoot *layer_root; ssgTransform *layer_transform; ssgSimpleState *layer_state; @@ -41,7 +42,10 @@ class SGCloudLayer { // height above sea level (meters) float layer_asl; + float layer_thickness; + float layer_transition; float size; + float scale; // for handling texture coordinates to simulate cloud movement // from winds, and to simulate the clouds being tied to ground @@ -58,7 +62,8 @@ public: ~SGCloudLayer( void ); // build the cloud object - ssgBranch *build( FGPath path, double size, double asl ); + void build( FGPath path, double size, double asl, double thickness, + double transition ); // repaint the cloud colors based on current value of sun_angle, // sky, and fog colors. This updates the color arrays for @@ -75,7 +80,14 @@ public: // lat specifies a rotation about the new Y axis // spin specifies a rotation about the new Z axis (and orients the // sunrise/set effects - bool reposition( sgVec3 p, sgVec3 up, double lon, double lat ); + bool reposition( sgVec3 p, sgVec3 up, double lon, double lat, double alt ); + + // draw the cloud layer + void draw(); + + inline float get_asl() const { return layer_asl; } + inline float get_thickness() const { return layer_thickness; } + inline float get_transition() const { return layer_transition; } }; diff --git a/simgear/sky/sky.cxx b/simgear/sky/sky.cxx index beff38a8..d37cc9d8 100644 --- a/simgear/sky/sky.cxx +++ b/simgear/sky/sky.cxx @@ -28,11 +28,22 @@ #include // plib include +#include +#include + #include "sky.hxx" // Constructor SGSky::SGSky( void ) { + effective_visibility = visibility = 10000.0; + + // near cloud visibility state variables + in_puff = false; + puff_length = 0; + puff_progression = 0; + ramp_up = 0.15; + ramp_down = 0.15; } @@ -97,14 +108,20 @@ bool SGSky::repaint( sgVec4 sky_color, sgVec4 fog_color, int nplanets, sgdVec3 *planet_data, int nstars, sgdVec3 *star_data ) { - dome->repaint( sky_color, fog_color, sun_angle ); - oursun->repaint( sun_angle ); - moon->repaint( moon_angle ); - planets->repaint( sun_angle, nplanets, planet_data ); - stars->repaint( sun_angle, nstars, star_data ); - - for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { - cloud_layers[i]->repaint( fog_color ); + if ( effective_visibility > 1000.0 ) { + enable(); + dome->repaint( sky_color, fog_color, sun_angle ); + oursun->repaint( sun_angle ); + moon->repaint( moon_angle ); + planets->repaint( sun_angle, nplanets, planet_data ); + stars->repaint( sun_angle, nstars, star_data ); + + for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { + cloud_layers[i]->repaint( fog_color ); + } + } else { + // turn off sky + disable(); } return true; @@ -119,7 +136,7 @@ bool SGSky::repaint( sgVec4 sky_color, sgVec4 fog_color, // additional orientation for the sunrise/set effects and is used by // the skydome and perhaps clouds. bool SGSky::reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up, - double lon, double lat, double spin, + double lon, double lat, double alt, double spin, double gst, double sun_ra, double sun_dec, double sun_dist, double moon_ra, double moon_dec, double moon_dist ) @@ -132,7 +149,7 @@ bool SGSky::reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up, stars->reposition( view_pos, angle ); for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { - cloud_layers[i]->reposition( zero_elev, view_up, lon, lat ); + cloud_layers[i]->reposition( zero_elev, view_up, lon, lat, alt ); } return true; @@ -146,13 +163,159 @@ void SGSky::draw_background() { // draw scenery elements of the sky -void SGSky::draw_scene() { - ssgCullAndDraw( post_root ); +void SGSky::draw_scene( float alt ) { + + if ( effective_visibility < 4000.0 ) { + // bail and don't draw clouds + return; + } + + // determine rendering order + int pos = 0; + while ( pos < (int)cloud_layers.size() && + alt > cloud_layers[pos]->get_asl()) + { + ++pos; + } + + if ( pos == 0 ) { + // we are below all the cloud layers, draw top to bottom + for ( int i = cloud_layers.size() - 1; i >= 0; --i ) { + cloud_layers[i]->draw(); + } + } else if ( pos >= (int)cloud_layers.size() ) { + // we are above all the cloud layers, draw bottom to top + for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { + cloud_layers[i]->draw(); + } + } else { + // we are between cloud layers, draw lower layers bottom to + // top and upper layers top to bottom + for ( int i = 0; i < pos; ++i ) { + cloud_layers[i]->draw(); + } + for ( int i = cloud_layers.size() - 1; i >= pos; --i ) { + cloud_layers[i]->draw(); + } + } } -void SGSky::add_cloud_layer( double asl ) { +void SGSky::add_cloud_layer( double asl, double thickness, double transition ) { SGCloudLayer *layer = new SGCloudLayer; - post_transform -> addKid( layer->build(tex_path, 20000.0f, asl) ); - cloud_layers.push_back( layer ); + layer->build(tex_path, 40000.0f, asl, thickness, transition); + + layer_list_iterator current = cloud_layers.begin(); + layer_list_iterator last = cloud_layers.end(); + while ( current != last && (*current)->get_asl() < asl ) { + ++current; + } + + if ( current != last ) { + cloud_layers.insert( current, layer ); + } else { + cloud_layers.push_back( layer ); + } + + for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { + cout << "layer " << i << " = " << cloud_layers[i]->get_asl() << endl; + } + cout << endl; } + + +// modify the current visibility based on cloud layers, thickness, +// transition range, and simulated "puffs". +void SGSky::modify_vis( float alt, float time_factor ) { + float effvis = visibility; + + for ( int i = 0; i < (int)cloud_layers.size(); ++i ) { + float asl = cloud_layers[i]->get_asl(); + float thickness = cloud_layers[i]->get_thickness(); + float transition = cloud_layers[i]->get_transition(); + + double ratio = 1.0; + + if ( alt < asl - transition ) { + // below cloud layer + ratio = 1.0; + } else if ( alt < asl ) { + // in lower transition + ratio = (asl - alt) / transition; + } else if ( alt < asl + thickness ) { + // in cloud layer + ratio = 0.0; + } else if ( alt < asl + thickness + transition ) { + // in upper transition + ratio = (alt - (asl + thickness)) / transition; + } else { + // above cloud layer + ratio = 1.0; + } + + // accumulate effects from multiple cloud layers + effvis *= ratio; + + if ( ratio < 1.0 ) { + if ( ! in_puff ) { + // calc chance of entering cloud puff + double rnd = fg_random(); + double chance = rnd * rnd * rnd; + if ( chance > 0.95 /* * (diff - 25) / 50.0 */ ) { + in_puff = true; + do { + puff_length = fg_random() * 2.0; // up to 2 seconds + } while ( puff_length <= 0.0 ); + puff_progression = 0.0; + } + } + + if ( in_puff ) { + // modify actual_visibility based on puff envelope + + if ( puff_progression <= ramp_up ) { + double x = FG_PI_2 * puff_progression / ramp_up; + double factor = 1.0 - sin( x ); + effvis = effvis * factor; + } else if ( puff_progression >= ramp_up + puff_length ) { + double x = FG_PI_2 * + (puff_progression - (ramp_up + puff_length)) / + ramp_down; + double factor = sin( x ); + effvis = effvis * factor; + } else { + effvis = 0.0; + } + + /* cout << "len = " << puff_length + << " x = " << x + << " factor = " << factor + << " actual_visibility = " << actual_visibility + << endl; */ + + // time_factor = ( global_multi_loop * + // current_options.get_speed_up() ) / + // (double)current_options.get_model_hz(); + + puff_progression += time_factor; + + /* cout << "gml = " << global_multi_loop + << " speed up = " << current_options.get_speed_up() + << " hz = " << current_options.get_model_hz() << endl; + */ + + if ( puff_progression > puff_length + ramp_up + ramp_down) { + in_puff = false; + } + } + + // never let visibility drop below zero + if ( effvis <= 0 ) { + effvis = 0.1; + } + } + } // for + + effective_visibility = effvis; +} + diff --git a/simgear/sky/sky.hxx b/simgear/sky/sky.hxx index 677ff6e4..058740f3 100644 --- a/simgear/sky/sky.hxx +++ b/simgear/sky/sky.hxx @@ -71,6 +71,17 @@ private: FGPath tex_path; + // visibility + float visibility; + float effective_visibility; + + // near cloud visibility state variables + bool in_puff; + double puff_length; + double puff_progression; + double ramp_up; + double ramp_down; + public: // Constructor @@ -92,7 +103,7 @@ public: // 0 degrees = high noon // 90 degrees = sun rise/set // 180 degrees = darkest midnight - bool repaint( sgVec4 sky_color, sgVec4 fog_color, + bool repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle, double moon_angle, int nplanets, sgdVec3 *planet_data, int nstars, sgdVec3 *star_data ); @@ -105,16 +116,20 @@ public: // additional orientation for the sunrise/set effects and is used // by the skydome and perhaps clouds. bool reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up, - double lon, double lat, double spin, + double lon, double lat, double alt, double spin, double gst, double sun_ra, double sun_dec, double sun_dist, double moon_ra, double moon_dec, double moon_dist ); + // modify the given visibility based on cloud layers, thickness, + // transition range, and simulated "puffs". + void modify_vis( float alt, float time_factor ); + // draw background portions of the sky void draw_background(); // draw scenery elements of the sky - void draw_scene(); + void draw_scene( float alt ); // specify the texture path (optional, defaults to current directory) inline void texture_path( const string& path ) { @@ -134,13 +149,18 @@ public: post_selector->select( 0 ); } - // add a cloud layer (above see level in meters) - void add_cloud_layer( double asl ); + // add a cloud layer (above sea level in meters) + void add_cloud_layer( double asl, double thickness, double transition ); inline int get_num_layers() const { return cloud_layers.size(); } inline SGCloudLayer *get_cloud_layer( int i ) const { return cloud_layers[i]; } + + inline float get_visibility() const { return effective_visibility; } + inline void set_visibility( float v ) { + effective_visibility = visibility = v; + } }; -- 2.39.5