00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <simgear_config.h>
00024 #endif
00025
00026 #include <simgear/constants.h>
00027 #include <simgear/structure/SGReferenced.hxx>
00028 #include <simgear/structure/SGSharedPtr.hxx>
00029 #include <simgear/math/sg_random.h>
00030 #include <simgear/math/sg_geodesy.hxx>
00031 #include <simgear/math/point3d.hxx>
00032 #include <simgear/math/polar3d.hxx>
00033 #include <simgear/sound/sample_group.hxx>
00034 #include <simgear/scene/sky/cloudfield.hxx>
00035 #include <simgear/scene/sky/newcloud.hxx>
00036 #include <simgear/props/props.hxx>
00037 #include "visual_enviro.hxx"
00038
00039 #include <vector>
00040
00041 using std::vector;
00042
00043
00044 typedef struct {
00045 Point3D pt;
00046 int depth;
00047 int prev;
00048 } lt_tree_seg;
00049
00050 #define MAX_RAIN_SLICE 200
00051 static float rainpos[MAX_RAIN_SLICE];
00052 #define MAX_LT_TREE_SEG 400
00053
00054 #define DFL_MIN_LIGHT 0.35
00055 sgVec3 SGEnviro::min_light = {DFL_MIN_LIGHT, DFL_MIN_LIGHT, DFL_MIN_LIGHT};
00056 #define DFL_STREAK_BRIGHT_NEARMOST_LAYER 0.9
00057 SGfloat SGEnviro::streak_bright_nearmost_layer = DFL_STREAK_BRIGHT_NEARMOST_LAYER;
00058 #define DFL_STREAK_BRIGHT_FARMOST_LAYER 0.5
00059 SGfloat SGEnviro::streak_bright_farmost_layer = DFL_STREAK_BRIGHT_FARMOST_LAYER;
00060 #define DFL_STREAK_PERIOD_MAX 2.5
00061 SGfloat SGEnviro::streak_period_max = DFL_STREAK_PERIOD_MAX;
00062 #define DFL_STREAK_PERIOD_CHANGE_PER_KT 0.005
00063 SGfloat SGEnviro::streak_period_change_per_kt = DFL_STREAK_PERIOD_CHANGE_PER_KT;
00064 #define DFL_STREAK_PERIOD_MIN 1.0
00065 SGfloat SGEnviro::streak_period_min = DFL_STREAK_PERIOD_MIN;
00066 #define DFL_STREAK_LENGTH_MIN 0.03
00067 SGfloat SGEnviro::streak_length_min = DFL_STREAK_LENGTH_MIN;
00068 #define DFL_STREAK_LENGTH_CHANGE_PER_KT 0.0005
00069 SGfloat SGEnviro::streak_length_change_per_kt = DFL_STREAK_LENGTH_CHANGE_PER_KT;
00070 #define DFL_STREAK_LENGTH_MAX 0.1
00071 SGfloat SGEnviro::streak_length_max = DFL_STREAK_LENGTH_MAX;
00072 #define DFL_STREAK_COUNT_MIN 40
00073 int SGEnviro::streak_count_min = DFL_STREAK_COUNT_MIN;
00074 #define DFL_STREAK_COUNT_MAX 190
00075 #if (DFL_STREAK_COUNT_MAX > MAX_RAIN_SLICE)
00076 #error "Bad default!"
00077 #endif
00078 int SGEnviro::streak_count_max = DFL_STREAK_COUNT_MAX;
00079 #define DFL_CONE_BASE_RADIUS 15.0
00080 SGfloat SGEnviro::cone_base_radius = DFL_CONE_BASE_RADIUS;
00081 #define DFL_CONE_HEIGHT 30.0
00082 SGfloat SGEnviro::cone_height = DFL_CONE_HEIGHT;
00083
00084
00085 void SGEnviro::config(const SGPropertyNode* n)
00086 {
00087 if (!n)
00088 return;
00089
00090 const float ml = n->getFloatValue("min-light", DFL_MIN_LIGHT);
00091 sgSetVec3(min_light, ml, ml, ml);
00092
00093 streak_bright_nearmost_layer = n->getFloatValue(
00094 "streak-brightness-nearmost-layer",
00095 DFL_STREAK_BRIGHT_NEARMOST_LAYER);
00096 streak_bright_farmost_layer = n->getFloatValue(
00097 "streak-brightness-farmost-layer",
00098 DFL_STREAK_BRIGHT_FARMOST_LAYER);
00099
00100 streak_period_max = n->getFloatValue(
00101 "streak-period-max",
00102 DFL_STREAK_PERIOD_MAX);
00103 streak_period_min = n->getFloatValue(
00104 "streak-period-min",
00105 DFL_STREAK_PERIOD_MIN);
00106 streak_period_change_per_kt = n->getFloatValue(
00107 "streak-period-change-per-kt",
00108 DFL_STREAK_PERIOD_CHANGE_PER_KT);
00109
00110 streak_length_max = n->getFloatValue(
00111 "streak-length-max",
00112 DFL_STREAK_LENGTH_MAX);
00113 streak_length_min = n->getFloatValue(
00114 "streak-length-min",
00115 DFL_STREAK_LENGTH_MIN);
00116 streak_length_change_per_kt = n->getFloatValue(
00117 "streak-length-change-per-kt",
00118 DFL_STREAK_LENGTH_CHANGE_PER_KT);
00119
00120 streak_count_min = n->getIntValue(
00121 "streak-count-min", DFL_STREAK_COUNT_MIN);
00122 streak_count_max = n->getIntValue(
00123 "streak-count-max", DFL_STREAK_COUNT_MAX);
00124 if (streak_count_max > MAX_RAIN_SLICE)
00125 streak_count_max = MAX_RAIN_SLICE;
00126
00127 cone_base_radius = n->getFloatValue(
00128 "cone-base-radius", DFL_CONE_BASE_RADIUS);
00129 cone_height = n->getFloatValue("cone_height", DFL_CONE_HEIGHT);
00130 }
00131
00132
00136 class SGLightning {
00137 public:
00145 SGLightning(double lon, double lat, double alt);
00146 ~SGLightning();
00147 void lt_Render(void);
00148 void lt_build(void);
00149 void lt_build_tree_branch(int tree_nr, Point3D &start, float energy, int nbseg, float segsize);
00150
00151
00152 lt_tree_seg lt_tree[MAX_LT_TREE_SEG];
00153
00154 int nb_tree;
00155
00156 double lon, lat, alt;
00157 int sequence_count;
00158
00159 double age;
00160 };
00161
00162 typedef vector<SGLightning *> list_of_lightning;
00163 static list_of_lightning lightnings;
00164
00165 SGEnviro sgEnviro;
00166
00167 SGEnviro::SGEnviro() :
00168 view_in_cloud(false),
00169 precipitation_enable_state(true),
00170 precipitation_density(100.0),
00171 precipitation_max_alt(0.0),
00172 turbulence_enable_state(false),
00173 last_cloud_turbulence(0.0),
00174 cloud_turbulence(0.0),
00175 lightning_enable_state(false),
00176 elapsed_time(0.0),
00177 dt(0.0),
00178 sampleGroup(NULL),
00179 snd_active(false),
00180 snd_dist(0.0),
00181 min_time_before_lt(0.0),
00182 fov_width(55.0),
00183 fov_height(55.0)
00184
00185 {
00186 for(int i = 0; i < MAX_RAIN_SLICE ; i++)
00187 rainpos[i] = sg_random();
00188 radarEcho.reserve(100);
00189 }
00190
00191 SGEnviro::~SGEnviro(void) {
00192 if (sampleGroup) delete sampleGroup;
00193
00194
00195 return;
00196 list_of_lightning::iterator iLightning;
00197 for( iLightning = lightnings.begin() ; iLightning != lightnings.end() ; iLightning++ ) {
00198 delete (*iLightning);
00199 }
00200 lightnings.clear();
00201 }
00202
00203 void SGEnviro::startOfFrame( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double delta_time) {
00204
00205 return;
00206 view_in_cloud = false;
00207
00208 last_cloud_turbulence = cloud_turbulence;
00209 cloud_turbulence = 0.0;
00210 elapsed_time += delta_time;
00211 min_time_before_lt -= delta_time;
00212 dt = delta_time;
00213
00214 sgMat4 T1, LON, LAT;
00215 sgVec3 axis;
00216
00217 sgMakeTransMat4( T1, p );
00218
00219 sgSetVec3( axis, 0.0, 0.0, 1.0 );
00220 sgMakeRotMat4( LON, lon, axis );
00221
00222 sgSetVec3( axis, 0.0, 1.0, 0.0 );
00223 sgMakeRotMat4( LAT, 90.0 - lat, axis );
00224
00225 sgMat4 TRANSFORM;
00226
00227 sgCopyMat4( TRANSFORM, T1 );
00228 sgPreMultMat4( TRANSFORM, LON );
00229 sgPreMultMat4( TRANSFORM, LAT );
00230
00231 sgCoord pos;
00232 sgSetCoord( &pos, TRANSFORM );
00233
00234 sgMakeCoordMat4( transform, &pos );
00235 last_lon = lon;
00236 last_lat = lat;
00237 last_alt = alt;
00238
00239 radarEcho.clear();
00240 precipitation_max_alt = 400.0;
00241 }
00242
00243 void SGEnviro::endOfFrame(void) {
00244 }
00245
00246 double SGEnviro::get_cloud_turbulence(void) const {
00247 return last_cloud_turbulence;
00248 }
00249
00250
00251 bool SGEnviro::is_view_in_cloud(void) const {
00252 return view_in_cloud;
00253 }
00254 void SGEnviro::set_view_in_cloud(bool incloud) {
00255 view_in_cloud = incloud;
00256 }
00257
00258 bool SGEnviro::get_turbulence_enable_state(void) const {
00259 return turbulence_enable_state;
00260 }
00261
00262 void SGEnviro::set_turbulence_enable_state(bool enable) {
00263 turbulence_enable_state = enable;
00264 }
00265
00266 float SGEnviro::get_precipitation_density(void) const {
00267 return precipitation_density;
00268 }
00269 bool SGEnviro::get_precipitation_enable_state(void) const {
00270 return precipitation_enable_state;
00271 }
00272
00273 void SGEnviro::set_precipitation_density(float density) {
00274 precipitation_density = density;
00275 }
00276 void SGEnviro::set_precipitation_enable_state(bool enable) {
00277 precipitation_enable_state = enable;
00278 }
00279
00280
00281 bool SGEnviro::get_lightning_enable_state(void) const {
00282 return lightning_enable_state;
00283 }
00284
00285 void SGEnviro::set_lightning_enable_state(bool enable) {
00286 lightning_enable_state = enable;
00287 if( ! enable ) {
00288
00289 }
00290 }
00291
00292 void SGEnviro::setLight(sgVec4 adj_fog_color) {
00293
00294 return;
00295 sgCopyVec4( fog_color, adj_fog_color );
00296 if( false ) {
00297
00298 }
00299 }
00300 #if 0
00301 void SGEnviro::callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId) {
00302
00303
00304
00305
00306
00307
00308
00309 double turbulence = 0.0;
00310 if( dist < radius * radius * 2.25f ) {
00311 switch(family) {
00312 case SGNewCloud::CLFamilly_st:
00313 turbulence = 0.2;
00314 break;
00315 case SGNewCloud::CLFamilly_ci:
00316 case SGNewCloud::CLFamilly_cs:
00317 case SGNewCloud::CLFamilly_cc:
00318 case SGNewCloud::CLFamilly_ac:
00319 case SGNewCloud::CLFamilly_as:
00320 turbulence = 0.1;
00321 break;
00322 case SGNewCloud::CLFamilly_sc:
00323 turbulence = 0.3;
00324 break;
00325 case SGNewCloud::CLFamilly_ns:
00326 turbulence = 0.4;
00327 break;
00328 case SGNewCloud::CLFamilly_cu:
00329 turbulence = 0.5;
00330 break;
00331 case SGNewCloud::CLFamilly_cb:
00332 turbulence = 0.6;
00333 break;
00334 }
00335
00336 if( dist > radius * radius )
00337 turbulence *= 0.5;
00338 if( turbulence > cloud_turbulence )
00339 cloud_turbulence = turbulence;
00340
00341 }
00342
00343
00344
00345 double LWC = 0.0;
00346 switch(family) {
00347 case SGNewCloud::CLFamilly_st:
00348 LWC = 0.29;
00349 break;
00350 case SGNewCloud::CLFamilly_cu:
00351 LWC = 0.27;
00352 break;
00353 case SGNewCloud::CLFamilly_cb:
00354 LWC = 2.0;
00355 break;
00356 case SGNewCloud::CLFamilly_sc:
00357 LWC = 0.44;
00358 break;
00359 case SGNewCloud::CLFamilly_ci:
00360 LWC = 0.03;
00361 break;
00362
00363 case SGNewCloud::CLFamilly_cs:
00364 case SGNewCloud::CLFamilly_cc:
00365 case SGNewCloud::CLFamilly_ac:
00366 case SGNewCloud::CLFamilly_as:
00367 LWC = 0.03;
00368 break;
00369 case SGNewCloud::CLFamilly_ns:
00370 LWC = 0.29*2.0;
00371 break;
00372 }
00373
00374
00375 if( LWC > 0.0 )
00376 radarEcho.push_back( SGWxRadarEcho ( heading, alt, radius, dist, LWC, false, cloudId ) );
00377
00378
00379
00380
00381 if(lightning_enable_state && min_time_before_lt <= 0.0 && (family == SGNewCloud::CLFamilly_cb) &&
00382 dist < 15000.0 * 15000.0 && sg_random() > 0.9f) {
00383 double lat, lon;
00384 Point3D orig, dest;
00385 orig.setlat(last_lat * SG_DEGREES_TO_RADIANS );
00386 orig.setlon(last_lon * SG_DEGREES_TO_RADIANS );
00387 orig.setelev(0.0);
00388 dist = sgSqrt(dist);
00389 dest = calc_gc_lon_lat(orig, heading, dist);
00390 lon = dest.lon() * SG_RADIANS_TO_DEGREES;
00391 lat = dest.lat() * SG_RADIANS_TO_DEGREES;
00392 addLightning( lon, lat, alt );
00393
00394
00395 min_time_before_lt = 5.0 + sg_random() * 30;
00396
00397
00398 }
00399 if( (alt - radius * 0.1) > precipitation_max_alt )
00400 switch(family) {
00401 case SGNewCloud::CLFamilly_st:
00402 case SGNewCloud::CLFamilly_cu:
00403 case SGNewCloud::CLFamilly_cb:
00404 case SGNewCloud::CLFamilly_ns:
00405 case SGNewCloud::CLFamilly_sc:
00406 precipitation_max_alt = alt - radius * 0.1;
00407 break;
00408 }
00409 }
00410
00411 #endif
00412
00413 list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
00414 return &radarEcho;
00415 }
00416
00417
00418 void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down, double rain_norm, double speed) {
00419
00420 return;
00421 sgVec3 light;
00422 sgAddVec3( light, fog_color, min_light );
00423 float da = SG_PI * 2.0f / (float) slices;
00424
00425 float speedf = streak_period_max - speed * streak_period_change_per_kt;
00426 if( speedf < streak_period_min )
00427 speedf = streak_period_min;
00428 float lenf = streak_length_min + speed * streak_length_change_per_kt;
00429 if( lenf > streak_length_max )
00430 lenf = streak_length_max;
00431 float t = fmod((float) elapsed_time, speedf) / speedf;
00432
00433 if( !down )
00434 t = 1.0f - t;
00435 float angle = 0.0f;
00436
00437 glBegin(GL_LINES);
00438 if (slices > MAX_RAIN_SLICE)
00439 slices = MAX_RAIN_SLICE;
00440 for( int i = 0 ; i < slices ; i++ ) {
00441 float x = cos(angle) * baseRadius;
00442 float y = sin(angle) * baseRadius;
00443 angle += da;
00444 sgVec3 dir = {x, -height, y};
00445
00446
00447 float t1 = (i & 1 ? t : t + t) + rainpos[i];
00448 if(t1 > 1.0f) t1 -= 1.0f;
00449 if(t1 > 1.0f) t1 -= 1.0f;
00450
00451
00452 float c = t1 * (i & 1 ?
00453 streak_bright_farmost_layer
00454 : streak_bright_nearmost_layer);
00455 glColor4f(c * light[0], c * light[1], c * light[2], c);
00456 sgVec3 p1, p2;
00457 sgScaleVec3(p1, dir, t1);
00458
00459 float t2 = t1 + (i & 1 ? lenf : lenf+lenf);
00460 sgScaleVec3(p2, dir, t2);
00461
00462 glVertex3f(p1[0], p1[1] + height, p1[2]);
00463 glVertex3f(p2[0], p2[1] + height, p2[2]);
00464 }
00465 glEnd();
00466 }
00467
00468 void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm) {
00469
00470 return;
00471
00472 #if 0
00473 static int debug_period = 0;
00474 if (debug_period++ == 50) {
00475 debug_period = 0;
00476 cout << "drawRain("
00477 << pitch << ", "
00478 << roll << ", "
00479 << heading << ", "
00480 << hspeed << ", "
00481 << rain_norm << ");"
00482
00483
00484 << endl;
00485 }
00486 #endif
00487
00488
00489 glBindTexture(GL_TEXTURE_2D, 0);
00490
00491 glDisable(GL_DEPTH_TEST);
00492 glShadeModel(GL_SMOOTH);
00493 glEnable(GL_BLEND);
00494 glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
00495 glDisable( GL_FOG );
00496 glDisable(GL_LIGHTING);
00497
00498 int slice_count = static_cast<int>(
00499 (streak_count_min + rain_norm*(streak_count_max-streak_count_min))
00500 * precipitation_density / 100.0);
00501
00502
00503
00504
00505
00506
00507 double raindrop_speed_kts
00508 = (5.0 + rain_norm*15.0) * SG_MPH_TO_MPS * SG_MPS_TO_KT;
00509
00510 float angle = atanf(hspeed / raindrop_speed_kts) * SG_RADIANS_TO_DEGREES;
00511 glPushMatrix();
00512
00513 angle = -pitch - angle;
00514 glRotatef(roll, 0.0, 0.0, 1.0);
00515 glRotatef(heading, 0.0, 1.0, 0.0);
00516 glRotatef(angle, 1.0, 0.0, 0.0);
00517
00518
00519 DrawCone2(cone_base_radius, cone_height,
00520 slice_count, true, rain_norm, hspeed);
00521
00522 if(angle > 0.0 || heading != 0.0)
00523 DrawCone2(cone_base_radius, -cone_height,
00524 slice_count, false, rain_norm, hspeed);
00525
00526 glPopMatrix();
00527
00528 glEnable(GL_LIGHTING);
00529 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
00530 glEnable( GL_FOG );
00531 glEnable(GL_DEPTH_TEST);
00532
00533 }
00534
00535 void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) {
00536 sampleGroup = sgr;
00537 }
00538
00539 void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
00540
00541 return;
00542 if( precipitation_enable_state && rain_norm > 0.0)
00543 if( precipitation_max_alt >= last_alt )
00544 drawRain(pitch, roll, heading, hspeed, rain_norm);
00545 }
00546
00547
00548 SGLightning::SGLightning(double _lon, double _lat, double _alt) :
00549 nb_tree(0),
00550 lon(_lon),
00551 lat(_lat),
00552 alt(_alt),
00553 age(1.0 + sg_random() * 4.0)
00554 {
00555
00556 lt_build();
00557 }
00558
00559 SGLightning::~SGLightning() {
00560 }
00561
00562
00563 void SGLightning::lt_build_tree_branch(int tree_nr, Point3D &start, float energy, int nbseg, float segsize) {
00564
00565 return;
00566
00567 sgVec3 dir, newdir;
00568 int nseg = 0;
00569 Point3D pt = start;
00570 if( nbseg == 50 )
00571 sgSetVec3( dir, 0.0, -1.0, 0.0 );
00572 else {
00573 sgSetVec3( dir, sg_random() - 0.5f, sg_random() - 0.5f, sg_random() - 0.5f);
00574 sgNormaliseVec3(dir);
00575 }
00576 if( nb_tree >= MAX_LT_TREE_SEG )
00577 return;
00578
00579 lt_tree[nb_tree].depth = tree_nr;
00580 nseg = 0;
00581 lt_tree[nb_tree].pt = pt;
00582 lt_tree[nb_tree].prev = -1;
00583 nb_tree ++;
00584
00585
00586 while(nseg < nbseg && pt.y() > 0.0) {
00587 int prev = nb_tree - 1;
00588 nseg++;
00589
00590 if( energy * sg_random() > 0.8f )
00591 lt_build_tree_branch(tree_nr + 1, pt, energy * 0.9f, nbseg == 50 ? 10 : static_cast<int>(nbseg * 0.4f), segsize * 0.7f);
00592
00593 if( nb_tree >= MAX_LT_TREE_SEG )
00594 return;
00595 sgSetVec3(newdir, (sg_random() - 0.5f), (sg_random() - 0.5f) - (nbseg == 50 ? 0.5f : 0.0), (sg_random() - 0.5f));
00596 sgNormaliseVec3(newdir);
00597 sgAddVec3( dir, newdir);
00598 sgNormaliseVec3(dir);
00599 sgVec3 scaleDir;
00600 sgScaleVec3( scaleDir, dir, segsize * energy * 0.5f );
00601 pt[PX] += scaleDir[0];
00602 pt[PY] += scaleDir[1];
00603 pt[PZ] += scaleDir[2];
00604
00605 lt_tree[nb_tree].depth = tree_nr;
00606 lt_tree[nb_tree].pt = pt;
00607 lt_tree[nb_tree].prev = prev;
00608 nb_tree ++;
00609 }
00610 }
00611
00612 void SGLightning::lt_build(void) {
00613
00614 return;
00615 Point3D top;
00616 nb_tree = 0;
00617 top[PX] = 0 ;
00618 top[PY] = alt;
00619 top[PZ] = 0;
00620 lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
00621 if( ! sgEnviro.sampleGroup )
00622 return;
00623 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00624 Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
00625 double course = 0.0, dist = 0.0;
00626 calc_gc_course_dist( dest, start, &course, &dist );
00627 if( dist < 10000.0 && ! sgEnviro.snd_playing && (dist < sgEnviro.snd_dist || ! sgEnviro.snd_active) ) {
00628 sgEnviro.snd_timer = 0.0;
00629 sgEnviro.snd_wait = dist / 340;
00630 sgEnviro.snd_dist = dist;
00631 sgEnviro.snd_pos_lat = lat;
00632 sgEnviro.snd_pos_lon = lon;
00633 sgEnviro.snd_active = true;
00634 sgEnviro.snd_playing = false;
00635 }
00636 }
00637
00638
00639 void SGLightning::lt_Render(void) {
00640
00641 return;
00642 float flash = 0.5;
00643 if( fmod(sgEnviro.elapsed_time*100.0, 100.0) > 50.0 )
00644 flash = sg_random() * 0.75f + 0.25f;
00645 float h = lt_tree[0].pt[PY];
00646 sgVec4 col={0.62f, 0.83f, 1.0f, 1.0f};
00647 sgVec4 c;
00648
00649 #define DRAW_SEG() \
00650 {glColorMaterial(GL_FRONT, GL_EMISSION); \
00651 glDisable(GL_LINE_SMOOTH); glBegin(GL_LINES); \
00652 glColor4fv(c); \
00653 glVertex3f(lt_tree[n].pt[PX], lt_tree[n].pt[PZ], lt_tree[n].pt[PY]); \
00654 glVertex3f(lt_tree[lt_tree[n].prev].pt[PX], lt_tree[lt_tree[n].prev].pt[PZ], lt_tree[lt_tree[n].prev].pt[PY]); \
00655 glEnd(); glEnable(GL_LINE_SMOOTH);}
00656
00657 glDepthMask( GL_FALSE );
00658 glEnable(GL_BLEND);
00659 glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00660 glBindTexture(GL_TEXTURE_2D, 0);
00661
00662 glDisable(GL_LIGHTING);
00663 glDisable( GL_FOG );
00664 glPushMatrix();
00665 sgMat4 modelview, tmp;
00666
00667
00668 sgCopyMat4( tmp, sgEnviro.transform );
00669 sgPostMultMat4( tmp, modelview );
00670
00671
00672
00673 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00674 Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
00675 double course = 0.0, dist = 0.0;
00676 calc_gc_course_dist( dest, start, &course, &dist );
00677 double ax = 0.0, ay = 0.0;
00678 ax = cos(course) * dist;
00679 ay = sin(course) * dist;
00680
00681 glTranslatef( ax, ay, -sgEnviro.last_alt );
00682
00683 sgEnviro.radarEcho.push_back( SGWxRadarEcho ( course, 0.0, 0.0, dist, age, true, 0 ) );
00684
00685 for( int n = 0 ; n < nb_tree ; n++ ) {
00686 if( lt_tree[n].prev < 0 )
00687 continue;
00688
00689 float t1 = sgLerp(0.5, 1.0, lt_tree[n].pt[PY] / h);
00690 t1 *= flash;
00691 if( lt_tree[n].depth >= 2 ) {
00692 glLineWidth(3);
00693 sgScaleVec4(c, col, t1 * 0.6f);
00694 DRAW_SEG();
00695 } else {
00696 if( lt_tree[n].depth == 0 ) {
00697 glLineWidth(12);
00698 sgScaleVec4(c, col, t1 * 0.5f);
00699 DRAW_SEG();
00700
00701 glLineWidth(6);
00702 sgScaleVec4(c, col, t1);
00703 DRAW_SEG();
00704 } else {
00705 glLineWidth(6);
00706 sgScaleVec4(c, col, t1 * 0.7f);
00707 DRAW_SEG();
00708 }
00709
00710 if( lt_tree[n].depth == 0 )
00711 glLineWidth(3);
00712 else
00713 glLineWidth(2);
00714
00715 sgSetVec4(c, t1, t1, t1, t1);
00716 DRAW_SEG();
00717 }
00718
00719 }
00720 glLineWidth(1);
00721 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
00722 glPopMatrix();
00723 glDepthMask( GL_TRUE );
00724 glEnable( GL_FOG );
00725 glEnable(GL_LIGHTING);
00726 }
00727
00728 void SGEnviro::addLightning(double lon, double lat, double alt) {
00729
00730 return;
00731 if( lightnings.size() > 10)
00732 return;
00733 SGLightning *lt= new SGLightning(lon, lat, alt);
00734 lightnings.push_back(lt);
00735 }
00736
00737 void SGEnviro::drawLightning(void) {
00738
00739 return;
00740 list_of_lightning::iterator iLightning;
00741
00742 if( snd_active ) {
00743 if( !snd_playing ) {
00744
00745 snd_timer += dt;
00746 if( snd_timer >= snd_wait ) {
00747 snd_playing = true;
00748
00749 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00750 Point3D dest( snd_pos_lon*SG_DEGREES_TO_RADIANS, snd_pos_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00751 double course = 0.0, dist = 0.0;
00752 calc_gc_course_dist( dest, start, &course, &dist );
00753 double ax = 0.0, ay = 0.0;
00754 ax = cos(course) * dist;
00755 ay = sin(course) * dist;
00756 SGSharedPtr<SGSoundSample> snd = sampleGroup->find("thunder");
00757 if( snd ) {
00758 SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt);
00759 snd->set_position(pos);
00760 snd->play_once();
00761 }
00762 }
00763 } else {
00764 if( !sampleGroup->is_playing("thunder") ) {
00765 snd_active = false;
00766 snd_playing = false;
00767 }
00768 }
00769
00770 }
00771 if( ! lightning_enable_state )
00772 return;
00773
00774 for( iLightning = lightnings.begin() ; iLightning != lightnings.end() ; iLightning++ ) {
00775 if( dt )
00776 if( sg_random() > 0.95f )
00777 (*iLightning)->lt_build();
00778 (*iLightning)->lt_Render();
00779 (*iLightning)->age -= dt;
00780 if( (*iLightning)->age < 0.0 ) {
00781 delete (*iLightning);
00782 lightnings.erase( iLightning );
00783 break;
00784 }
00785 }
00786
00787 }
00788
00789
00790 void SGEnviro::setFOV( float w, float h ) {
00791 fov_width = w;
00792 fov_height = h;
00793 }
00794
00795 void SGEnviro::getFOV( float &w, float &h ) {
00796 w = fov_width;
00797 h = fov_height;
00798 }