+ lightning_enable_state = enable;
+ if( ! enable ) {
+ // TODO:cleanup
+ }
+}
+
+void SGEnviro::setLight(sgVec4 adj_fog_color) {
+ // OSGFIXME
+ return;
+ sgCopyVec4( fog_color, adj_fog_color );
+ if( false ) {
+ // ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
+ }
+}
+#if 0
+void SGEnviro::callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId) {
+ // send data to wx radar
+ // compute turbulence
+ // draw precipitation
+ // draw lightning
+ // compute illumination
+
+ // http://www.pilotfriend.com/flight_training/weather/THUNDERSTORM%20HAZARDS1.htm
+ double turbulence = 0.0;
+ if( dist < radius * radius * 2.25f ) {
+ switch(family) {
+ case SGNewCloud::CLFamilly_st:
+ turbulence = 0.2;
+ break;
+ case SGNewCloud::CLFamilly_ci:
+ case SGNewCloud::CLFamilly_cs:
+ case SGNewCloud::CLFamilly_cc:
+ case SGNewCloud::CLFamilly_ac:
+ case SGNewCloud::CLFamilly_as:
+ turbulence = 0.1;
+ break;
+ case SGNewCloud::CLFamilly_sc:
+ turbulence = 0.3;
+ break;
+ case SGNewCloud::CLFamilly_ns:
+ turbulence = 0.4;
+ break;
+ case SGNewCloud::CLFamilly_cu:
+ turbulence = 0.5;
+ break;
+ case SGNewCloud::CLFamilly_cb:
+ turbulence = 0.6;
+ break;
+ }
+ // full turbulence inside cloud, half in the vicinity
+ if( dist > radius * radius )
+ turbulence *= 0.5;
+ if( turbulence > cloud_turbulence )
+ cloud_turbulence = turbulence;
+ // we can do 'local' precipitations too
+ }
+
+ // convert to LWC for radar (experimental)
+ // http://www-das.uwyo.edu/~geerts/cwx/notes/chap08/moist_cloud.html
+ double LWC = 0.0;
+ switch(family) {
+ case SGNewCloud::CLFamilly_st:
+ LWC = 0.29;
+ break;
+ case SGNewCloud::CLFamilly_cu:
+ LWC = 0.27;
+ break;
+ case SGNewCloud::CLFamilly_cb:
+ LWC = 2.0;
+ break;
+ case SGNewCloud::CLFamilly_sc:
+ LWC = 0.44;
+ break;
+ case SGNewCloud::CLFamilly_ci:
+ LWC = 0.03;
+ break;
+ // no data
+ case SGNewCloud::CLFamilly_cs:
+ case SGNewCloud::CLFamilly_cc:
+ case SGNewCloud::CLFamilly_ac:
+ case SGNewCloud::CLFamilly_as:
+ LWC = 0.03;
+ break;
+ case SGNewCloud::CLFamilly_ns:
+ LWC = 0.29*2.0;
+ break;
+ }
+
+ // add to the list for the wxRadar instrument
+ if( LWC > 0.0 )
+ radarEcho.push_back( SGWxRadarEcho ( heading, alt, radius, dist, LWC, false, cloudId ) );
+
+ // NB:data valid only from cockpit view
+
+ // spawn a new lightning
+ if(lightning_enable_state && min_time_before_lt <= 0.0 && (family == SGNewCloud::CLFamilly_cb) &&
+ dist < 15000.0 * 15000.0 && sg_random() > 0.9f) {
+ double lat, lon;
+ Point3D orig, dest;
+ orig.setlat(last_lat * SG_DEGREES_TO_RADIANS );
+ orig.setlon(last_lon * SG_DEGREES_TO_RADIANS );
+ orig.setelev(0.0);
+ dist = sgSqrt(dist);
+ dest = calc_gc_lon_lat(orig, heading, dist);
+ lon = dest.lon() * SG_RADIANS_TO_DEGREES;
+ lat = dest.lat() * SG_RADIANS_TO_DEGREES;
+ addLightning( lon, lat, alt );
+
+ // reset timer
+ min_time_before_lt = 5.0 + sg_random() * 30;
+ // DEBUG only
+// min_time_before_lt = 5.0;
+ }
+ if( (alt - radius * 0.1) > precipitation_max_alt )
+ switch(family) {
+ case SGNewCloud::CLFamilly_st:
+ case SGNewCloud::CLFamilly_cu:
+ case SGNewCloud::CLFamilly_cb:
+ case SGNewCloud::CLFamilly_ns:
+ case SGNewCloud::CLFamilly_sc:
+ precipitation_max_alt = alt - radius * 0.1;
+ break;
+ }
+}
+
+#endif
+
+list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
+ return &radarEcho;
+}
+
+// precipitation rendering code
+void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down, double rain_norm, double speed) {
+ // OSGFIXME
+ return;
+ sgVec3 light;
+ sgAddVec3( light, fog_color, min_light );
+ float da = SG_PI * 2.0f / (float) slices;
+ // low number = faster
+ float speedf = streak_period_max - speed * streak_period_change_per_kt;
+ if( speedf < streak_period_min )
+ speedf = streak_period_min;
+ float lenf = streak_length_min + speed * streak_length_change_per_kt;
+ if( lenf > streak_length_max )
+ lenf = streak_length_max;
+ float t = fmod((float) elapsed_time, speedf) / speedf;
+// t = 0.1f;
+ if( !down )
+ t = 1.0f - t;
+ float angle = 0.0f;
+ //glColor4f(1.0f, 0.7f, 0.7f, 0.9f); // XXX unneeded? overriden below
+ glBegin(GL_LINES);
+ if (slices > MAX_RAIN_SLICE)
+ slices = MAX_RAIN_SLICE; // should never happen
+ for( int i = 0 ; i < slices ; i++ ) {
+ float x = cos(angle) * baseRadius;
+ float y = sin(angle) * baseRadius;
+ angle += da;
+ sgVec3 dir = {x, -height, y};
+
+ // rain drops at 2 different speed to simulate depth
+ float t1 = (i & 1 ? t : t + t) + rainpos[i];
+ if(t1 > 1.0f) t1 -= 1.0f;
+ if(t1 > 1.0f) t1 -= 1.0f;
+
+ // distant raindrops are more transparent
+ float c = t1 * (i & 1 ?
+ streak_bright_farmost_layer
+ : streak_bright_nearmost_layer);
+ glColor4f(c * light[0], c * light[1], c * light[2], c);
+ sgVec3 p1, p2;
+ sgScaleVec3(p1, dir, t1);
+ // distant raindrops are shorter
+ float t2 = t1 + (i & 1 ? lenf : lenf+lenf);
+ sgScaleVec3(p2, dir, t2);
+
+ glVertex3f(p1[0], p1[1] + height, p1[2]);
+ glVertex3f(p2[0], p2[1] + height, p2[2]);
+ }
+ glEnd();
+}
+
+void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm) {
+ // OSGFIXME
+ return;
+
+#if 0
+ static int debug_period = 0;
+ if (debug_period++ == 50) {
+ debug_period = 0;
+ cout << "drawRain("
+ << pitch << ", "
+ << roll << ", "
+ << heading << ", "
+ << hspeed << ", "
+ << rain_norm << ");"
+ //" angle = " << angle
+ //<< " raindrop(KTS) = " << raindrop_speed_kts
+ << endl;
+ }
+#endif
+
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glDisable(GL_DEPTH_TEST);
+ glShadeModel(GL_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
+ glDisable( GL_FOG );
+ glDisable(GL_LIGHTING);
+
+ int slice_count = static_cast<int>(
+ (streak_count_min + rain_norm*(streak_count_max-streak_count_min))
+ * precipitation_density / 100.0);
+
+ // www.wonderquest.com/falling-raindrops.htm says that
+ // Raindrop terminal velocity is 5 to 20mph
+ // Rather than model it accurately (temp, pressure, diameter), and make it
+ // smaller than terminal when closer to the precipitation cloud base,
+ // we interpolate in the 5-20mph range according to rain_norm.
+ double raindrop_speed_kts
+ = (5.0 + rain_norm*15.0) * SG_MPH_TO_MPS * SG_MPS_TO_KT;
+
+ float angle = atanf(hspeed / raindrop_speed_kts) * SG_RADIANS_TO_DEGREES;
+ glPushMatrix();
+ // the cone rotate with hspeed
+ angle = -pitch - angle;
+ glRotatef(roll, 0.0, 0.0, 1.0);
+ glRotatef(heading, 0.0, 1.0, 0.0);
+ glRotatef(angle, 1.0, 0.0, 0.0);
+
+ // up cone
+ DrawCone2(cone_base_radius, cone_height,
+ slice_count, true, rain_norm, hspeed);
+ // down cone (usually not visible)
+ if(angle > 0.0 || heading != 0.0)
+ DrawCone2(cone_base_radius, -cone_height,
+ slice_count, false, rain_norm, hspeed);
+
+ glPopMatrix();
+
+ glEnable(GL_LIGHTING);
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
+ glEnable( GL_FOG );
+ glEnable(GL_DEPTH_TEST);
+
+}
+
+void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) {
+ sampleGroup = sgr;
+}
+
+void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
+ // OSGFIXME
+ return;
+ if( precipitation_enable_state && rain_norm > 0.0)
+ if( precipitation_max_alt >= last_alt )
+ drawRain(pitch, roll, heading, hspeed, rain_norm);
+}
+
+
+SGLightning::SGLightning(double _lon, double _lat, double _alt) :
+ nb_tree(0),
+ lon(_lon),
+ lat(_lat),
+ alt(_alt),
+ age(1.0 + sg_random() * 4.0)
+{
+// sequence_count = 1 + sg_random() * 5.0;
+ lt_build();