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/soundmgr_openal.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 soundMgr(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
00193 return;
00194 list_of_lightning::iterator iLightning;
00195 for( iLightning = lightnings.begin() ; iLightning != lightnings.end() ; iLightning++ ) {
00196 delete (*iLightning);
00197 }
00198 lightnings.clear();
00199 }
00200
00201 void SGEnviro::startOfFrame( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double delta_time) {
00202
00203 return;
00204 view_in_cloud = false;
00205
00206 last_cloud_turbulence = cloud_turbulence;
00207 cloud_turbulence = 0.0;
00208 elapsed_time += delta_time;
00209 min_time_before_lt -= delta_time;
00210 dt = delta_time;
00211
00212 sgMat4 T1, LON, LAT;
00213 sgVec3 axis;
00214
00215 sgMakeTransMat4( T1, p );
00216
00217 sgSetVec3( axis, 0.0, 0.0, 1.0 );
00218 sgMakeRotMat4( LON, lon, axis );
00219
00220 sgSetVec3( axis, 0.0, 1.0, 0.0 );
00221 sgMakeRotMat4( LAT, 90.0 - lat, axis );
00222
00223 sgMat4 TRANSFORM;
00224
00225 sgCopyMat4( TRANSFORM, T1 );
00226 sgPreMultMat4( TRANSFORM, LON );
00227 sgPreMultMat4( TRANSFORM, LAT );
00228
00229 sgCoord pos;
00230 sgSetCoord( &pos, TRANSFORM );
00231
00232 sgMakeCoordMat4( transform, &pos );
00233 last_lon = lon;
00234 last_lat = lat;
00235 last_alt = alt;
00236
00237 radarEcho.clear();
00238 precipitation_max_alt = 400.0;
00239 }
00240
00241 void SGEnviro::endOfFrame(void) {
00242 }
00243
00244 double SGEnviro::get_cloud_turbulence(void) const {
00245 return last_cloud_turbulence;
00246 }
00247
00248
00249 bool SGEnviro::is_view_in_cloud(void) const {
00250 return view_in_cloud;
00251 }
00252 void SGEnviro::set_view_in_cloud(bool incloud) {
00253 view_in_cloud = incloud;
00254 }
00255
00256 bool SGEnviro::get_turbulence_enable_state(void) const {
00257 return turbulence_enable_state;
00258 }
00259
00260 void SGEnviro::set_turbulence_enable_state(bool enable) {
00261 turbulence_enable_state = enable;
00262 }
00263
00264 float SGEnviro::get_precipitation_density(void) const {
00265 return precipitation_density;
00266 }
00267 bool SGEnviro::get_precipitation_enable_state(void) const {
00268 return precipitation_enable_state;
00269 }
00270
00271 void SGEnviro::set_precipitation_density(float density) {
00272 precipitation_density = density;
00273 }
00274 void SGEnviro::set_precipitation_enable_state(bool enable) {
00275 precipitation_enable_state = enable;
00276 }
00277
00278
00279 bool SGEnviro::get_lightning_enable_state(void) const {
00280 return lightning_enable_state;
00281 }
00282
00283 void SGEnviro::set_lightning_enable_state(bool enable) {
00284 lightning_enable_state = enable;
00285 if( ! enable ) {
00286
00287 }
00288 }
00289
00290 void SGEnviro::setLight(sgVec4 adj_fog_color) {
00291
00292 return;
00293 sgCopyVec4( fog_color, adj_fog_color );
00294 if( false ) {
00295
00296 }
00297 }
00298 #if 0
00299 void SGEnviro::callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId) {
00300
00301
00302
00303
00304
00305
00306
00307 double turbulence = 0.0;
00308 if( dist < radius * radius * 2.25f ) {
00309 switch(family) {
00310 case SGNewCloud::CLFamilly_st:
00311 turbulence = 0.2;
00312 break;
00313 case SGNewCloud::CLFamilly_ci:
00314 case SGNewCloud::CLFamilly_cs:
00315 case SGNewCloud::CLFamilly_cc:
00316 case SGNewCloud::CLFamilly_ac:
00317 case SGNewCloud::CLFamilly_as:
00318 turbulence = 0.1;
00319 break;
00320 case SGNewCloud::CLFamilly_sc:
00321 turbulence = 0.3;
00322 break;
00323 case SGNewCloud::CLFamilly_ns:
00324 turbulence = 0.4;
00325 break;
00326 case SGNewCloud::CLFamilly_cu:
00327 turbulence = 0.5;
00328 break;
00329 case SGNewCloud::CLFamilly_cb:
00330 turbulence = 0.6;
00331 break;
00332 }
00333
00334 if( dist > radius * radius )
00335 turbulence *= 0.5;
00336 if( turbulence > cloud_turbulence )
00337 cloud_turbulence = turbulence;
00338
00339 }
00340
00341
00342
00343 double LWC = 0.0;
00344 switch(family) {
00345 case SGNewCloud::CLFamilly_st:
00346 LWC = 0.29;
00347 break;
00348 case SGNewCloud::CLFamilly_cu:
00349 LWC = 0.27;
00350 break;
00351 case SGNewCloud::CLFamilly_cb:
00352 LWC = 2.0;
00353 break;
00354 case SGNewCloud::CLFamilly_sc:
00355 LWC = 0.44;
00356 break;
00357 case SGNewCloud::CLFamilly_ci:
00358 LWC = 0.03;
00359 break;
00360
00361 case SGNewCloud::CLFamilly_cs:
00362 case SGNewCloud::CLFamilly_cc:
00363 case SGNewCloud::CLFamilly_ac:
00364 case SGNewCloud::CLFamilly_as:
00365 LWC = 0.03;
00366 break;
00367 case SGNewCloud::CLFamilly_ns:
00368 LWC = 0.29*2.0;
00369 break;
00370 }
00371
00372
00373 if( LWC > 0.0 )
00374 radarEcho.push_back( SGWxRadarEcho ( heading, alt, radius, dist, LWC, false, cloudId ) );
00375
00376
00377
00378
00379 if(lightning_enable_state && min_time_before_lt <= 0.0 && (family == SGNewCloud::CLFamilly_cb) &&
00380 dist < 15000.0 * 15000.0 && sg_random() > 0.9f) {
00381 double lat, lon;
00382 Point3D orig, dest;
00383 orig.setlat(last_lat * SG_DEGREES_TO_RADIANS );
00384 orig.setlon(last_lon * SG_DEGREES_TO_RADIANS );
00385 orig.setelev(0.0);
00386 dist = sgSqrt(dist);
00387 dest = calc_gc_lon_lat(orig, heading, dist);
00388 lon = dest.lon() * SG_RADIANS_TO_DEGREES;
00389 lat = dest.lat() * SG_RADIANS_TO_DEGREES;
00390 addLightning( lon, lat, alt );
00391
00392
00393 min_time_before_lt = 5.0 + sg_random() * 30;
00394
00395
00396 }
00397 if( (alt - radius * 0.1) > precipitation_max_alt )
00398 switch(family) {
00399 case SGNewCloud::CLFamilly_st:
00400 case SGNewCloud::CLFamilly_cu:
00401 case SGNewCloud::CLFamilly_cb:
00402 case SGNewCloud::CLFamilly_ns:
00403 case SGNewCloud::CLFamilly_sc:
00404 precipitation_max_alt = alt - radius * 0.1;
00405 break;
00406 }
00407 }
00408
00409 #endif
00410
00411 list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
00412 return &radarEcho;
00413 }
00414
00415
00416 void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down, double rain_norm, double speed) {
00417
00418 return;
00419 sgVec3 light;
00420 sgAddVec3( light, fog_color, min_light );
00421 float da = SG_PI * 2.0f / (float) slices;
00422
00423 float speedf = streak_period_max - speed * streak_period_change_per_kt;
00424 if( speedf < streak_period_min )
00425 speedf = streak_period_min;
00426 float lenf = streak_length_min + speed * streak_length_change_per_kt;
00427 if( lenf > streak_length_max )
00428 lenf = streak_length_max;
00429 float t = fmod((float) elapsed_time, speedf) / speedf;
00430
00431 if( !down )
00432 t = 1.0f - t;
00433 float angle = 0.0f;
00434
00435 glBegin(GL_LINES);
00436 if (slices > MAX_RAIN_SLICE)
00437 slices = MAX_RAIN_SLICE;
00438 for( int i = 0 ; i < slices ; i++ ) {
00439 float x = cos(angle) * baseRadius;
00440 float y = sin(angle) * baseRadius;
00441 angle += da;
00442 sgVec3 dir = {x, -height, y};
00443
00444
00445 float t1 = (i & 1 ? t : t + t) + rainpos[i];
00446 if(t1 > 1.0f) t1 -= 1.0f;
00447 if(t1 > 1.0f) t1 -= 1.0f;
00448
00449
00450 float c = t1 * (i & 1 ?
00451 streak_bright_farmost_layer
00452 : streak_bright_nearmost_layer);
00453 glColor4f(c * light[0], c * light[1], c * light[2], c);
00454 sgVec3 p1, p2;
00455 sgScaleVec3(p1, dir, t1);
00456
00457 float t2 = t1 + (i & 1 ? lenf : lenf+lenf);
00458 sgScaleVec3(p2, dir, t2);
00459
00460 glVertex3f(p1[0], p1[1] + height, p1[2]);
00461 glVertex3f(p2[0], p2[1] + height, p2[2]);
00462 }
00463 glEnd();
00464 }
00465
00466 void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm) {
00467
00468 return;
00469
00470 #if 0
00471 static int debug_period = 0;
00472 if (debug_period++ == 50) {
00473 debug_period = 0;
00474 cout << "drawRain("
00475 << pitch << ", "
00476 << roll << ", "
00477 << heading << ", "
00478 << hspeed << ", "
00479 << rain_norm << ");"
00480
00481
00482 << endl;
00483 }
00484 #endif
00485
00486
00487 glBindTexture(GL_TEXTURE_2D, 0);
00488
00489 glDisable(GL_DEPTH_TEST);
00490 glShadeModel(GL_SMOOTH);
00491 glEnable(GL_BLEND);
00492 glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
00493 glDisable( GL_FOG );
00494 glDisable(GL_LIGHTING);
00495
00496 int slice_count = static_cast<int>(
00497 (streak_count_min + rain_norm*(streak_count_max-streak_count_min))
00498 * precipitation_density / 100.0);
00499
00500
00501
00502
00503
00504
00505 double raindrop_speed_kts
00506 = (5.0 + rain_norm*15.0) * SG_MPH_TO_MPS * SG_MPS_TO_KT;
00507
00508 float angle = atanf(hspeed / raindrop_speed_kts) * SG_RADIANS_TO_DEGREES;
00509 glPushMatrix();
00510
00511 angle = -pitch - angle;
00512 glRotatef(roll, 0.0, 0.0, 1.0);
00513 glRotatef(heading, 0.0, 1.0, 0.0);
00514 glRotatef(angle, 1.0, 0.0, 0.0);
00515
00516
00517 DrawCone2(cone_base_radius, cone_height,
00518 slice_count, true, rain_norm, hspeed);
00519
00520 if(angle > 0.0 || heading != 0.0)
00521 DrawCone2(cone_base_radius, -cone_height,
00522 slice_count, false, rain_norm, hspeed);
00523
00524 glPopMatrix();
00525
00526 glEnable(GL_LIGHTING);
00527 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
00528 glEnable( GL_FOG );
00529 glEnable(GL_DEPTH_TEST);
00530
00531 }
00532
00533 void SGEnviro::set_soundMgr(SGSoundMgr *mgr) {
00534 soundMgr = mgr;
00535 }
00536
00537 void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
00538
00539 return;
00540 if( precipitation_enable_state && rain_norm > 0.0)
00541 if( precipitation_max_alt >= last_alt )
00542 drawRain(pitch, roll, heading, hspeed, rain_norm);
00543 }
00544
00545
00546 SGLightning::SGLightning(double _lon, double _lat, double _alt) :
00547 nb_tree(0),
00548 lon(_lon),
00549 lat(_lat),
00550 alt(_alt),
00551 age(1.0 + sg_random() * 4.0)
00552 {
00553
00554 lt_build();
00555 }
00556
00557 SGLightning::~SGLightning() {
00558 }
00559
00560
00561 void SGLightning::lt_build_tree_branch(int tree_nr, Point3D &start, float energy, int nbseg, float segsize) {
00562
00563 return;
00564
00565 sgVec3 dir, newdir;
00566 int nseg = 0;
00567 Point3D pt = start;
00568 if( nbseg == 50 )
00569 sgSetVec3( dir, 0.0, -1.0, 0.0 );
00570 else {
00571 sgSetVec3( dir, sg_random() - 0.5f, sg_random() - 0.5f, sg_random() - 0.5f);
00572 sgNormaliseVec3(dir);
00573 }
00574 if( nb_tree >= MAX_LT_TREE_SEG )
00575 return;
00576
00577 lt_tree[nb_tree].depth = tree_nr;
00578 nseg = 0;
00579 lt_tree[nb_tree].pt = pt;
00580 lt_tree[nb_tree].prev = -1;
00581 nb_tree ++;
00582
00583
00584 while(nseg < nbseg && pt.y() > 0.0) {
00585 int prev = nb_tree - 1;
00586 nseg++;
00587
00588 if( energy * sg_random() > 0.8f )
00589 lt_build_tree_branch(tree_nr + 1, pt, energy * 0.9f, nbseg == 50 ? 10 : static_cast<int>(nbseg * 0.4f), segsize * 0.7f);
00590
00591 if( nb_tree >= MAX_LT_TREE_SEG )
00592 return;
00593 sgSetVec3(newdir, (sg_random() - 0.5f), (sg_random() - 0.5f) - (nbseg == 50 ? 0.5f : 0.0), (sg_random() - 0.5f));
00594 sgNormaliseVec3(newdir);
00595 sgAddVec3( dir, newdir);
00596 sgNormaliseVec3(dir);
00597 sgVec3 scaleDir;
00598 sgScaleVec3( scaleDir, dir, segsize * energy * 0.5f );
00599 pt[PX] += scaleDir[0];
00600 pt[PY] += scaleDir[1];
00601 pt[PZ] += scaleDir[2];
00602
00603 lt_tree[nb_tree].depth = tree_nr;
00604 lt_tree[nb_tree].pt = pt;
00605 lt_tree[nb_tree].prev = prev;
00606 nb_tree ++;
00607 }
00608 }
00609
00610 void SGLightning::lt_build(void) {
00611
00612 return;
00613 Point3D top;
00614 nb_tree = 0;
00615 top[PX] = 0 ;
00616 top[PY] = alt;
00617 top[PZ] = 0;
00618 lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
00619 if( ! sgEnviro.soundMgr )
00620 return;
00621 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00622 Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
00623 double course = 0.0, dist = 0.0;
00624 calc_gc_course_dist( dest, start, &course, &dist );
00625 if( dist < 10000.0 && ! sgEnviro.snd_playing && (dist < sgEnviro.snd_dist || ! sgEnviro.snd_active) ) {
00626 sgEnviro.snd_timer = 0.0;
00627 sgEnviro.snd_wait = dist / 340;
00628 sgEnviro.snd_dist = dist;
00629 sgEnviro.snd_pos_lat = lat;
00630 sgEnviro.snd_pos_lon = lon;
00631 sgEnviro.snd_active = true;
00632 sgEnviro.snd_playing = false;
00633 }
00634 }
00635
00636
00637 void SGLightning::lt_Render(void) {
00638
00639 return;
00640 float flash = 0.5;
00641 if( fmod(sgEnviro.elapsed_time*100.0, 100.0) > 50.0 )
00642 flash = sg_random() * 0.75f + 0.25f;
00643 float h = lt_tree[0].pt[PY];
00644 sgVec4 col={0.62f, 0.83f, 1.0f, 1.0f};
00645 sgVec4 c;
00646
00647 #define DRAW_SEG() \
00648 {glColorMaterial(GL_FRONT, GL_EMISSION); \
00649 glDisable(GL_LINE_SMOOTH); glBegin(GL_LINES); \
00650 glColor4fv(c); \
00651 glVertex3f(lt_tree[n].pt[PX], lt_tree[n].pt[PZ], lt_tree[n].pt[PY]); \
00652 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]); \
00653 glEnd(); glEnable(GL_LINE_SMOOTH);}
00654
00655 glDepthMask( GL_FALSE );
00656 glEnable(GL_BLEND);
00657 glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00658 glBindTexture(GL_TEXTURE_2D, 0);
00659
00660 glDisable(GL_LIGHTING);
00661 glDisable( GL_FOG );
00662 glPushMatrix();
00663 sgMat4 modelview, tmp;
00664
00665
00666 sgCopyMat4( tmp, sgEnviro.transform );
00667 sgPostMultMat4( tmp, modelview );
00668
00669
00670
00671 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00672 Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
00673 double course = 0.0, dist = 0.0;
00674 calc_gc_course_dist( dest, start, &course, &dist );
00675 double ax = 0.0, ay = 0.0;
00676 ax = cos(course) * dist;
00677 ay = sin(course) * dist;
00678
00679 glTranslatef( ax, ay, -sgEnviro.last_alt );
00680
00681 sgEnviro.radarEcho.push_back( SGWxRadarEcho ( course, 0.0, 0.0, dist, age, true, 0 ) );
00682
00683 for( int n = 0 ; n < nb_tree ; n++ ) {
00684 if( lt_tree[n].prev < 0 )
00685 continue;
00686
00687 float t1 = sgLerp(0.5, 1.0, lt_tree[n].pt[PY] / h);
00688 t1 *= flash;
00689 if( lt_tree[n].depth >= 2 ) {
00690 glLineWidth(3);
00691 sgScaleVec4(c, col, t1 * 0.6f);
00692 DRAW_SEG();
00693 } else {
00694 if( lt_tree[n].depth == 0 ) {
00695 glLineWidth(12);
00696 sgScaleVec4(c, col, t1 * 0.5f);
00697 DRAW_SEG();
00698
00699 glLineWidth(6);
00700 sgScaleVec4(c, col, t1);
00701 DRAW_SEG();
00702 } else {
00703 glLineWidth(6);
00704 sgScaleVec4(c, col, t1 * 0.7f);
00705 DRAW_SEG();
00706 }
00707
00708 if( lt_tree[n].depth == 0 )
00709 glLineWidth(3);
00710 else
00711 glLineWidth(2);
00712
00713 sgSetVec4(c, t1, t1, t1, t1);
00714 DRAW_SEG();
00715 }
00716
00717 }
00718 glLineWidth(1);
00719 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
00720 glPopMatrix();
00721 glDepthMask( GL_TRUE );
00722 glEnable( GL_FOG );
00723 glEnable(GL_LIGHTING);
00724 }
00725
00726 void SGEnviro::addLightning(double lon, double lat, double alt) {
00727
00728 return;
00729 if( lightnings.size() > 10)
00730 return;
00731 SGLightning *lt= new SGLightning(lon, lat, alt);
00732 lightnings.push_back(lt);
00733 }
00734
00735 void SGEnviro::drawLightning(void) {
00736
00737 return;
00738 list_of_lightning::iterator iLightning;
00739
00740 if( snd_active )
00741 if( !snd_playing ) {
00742
00743 snd_timer += dt;
00744 if( snd_timer >= snd_wait ) {
00745 snd_playing = true;
00746
00747 Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00748 Point3D dest( snd_pos_lon*SG_DEGREES_TO_RADIANS, snd_pos_lat*SG_DEGREES_TO_RADIANS, 0.0 );
00749 double course = 0.0, dist = 0.0;
00750 calc_gc_course_dist( dest, start, &course, &dist );
00751 double ax = 0.0, ay = 0.0;
00752 ax = cos(course) * dist;
00753 ay = sin(course) * dist;
00754 SGSharedPtr<SGSoundSample> snd = soundMgr->find("thunder");
00755 if( snd ) {
00756 ALfloat pos[3]={ax, ay, -sgEnviro.last_alt };
00757 snd->set_source_pos(pos);
00758 snd->play_once();
00759 }
00760 }
00761 } else {
00762 if( !soundMgr->is_playing("thunder") ) {
00763 snd_active = false;
00764 snd_playing = false;
00765 }
00766 }
00767
00768 if( ! lightning_enable_state )
00769 return;
00770
00771 for( iLightning = lightnings.begin() ; iLightning != lightnings.end() ; iLightning++ ) {
00772 if( dt )
00773 if( sg_random() > 0.95f )
00774 (*iLightning)->lt_build();
00775 (*iLightning)->lt_Render();
00776 (*iLightning)->age -= dt;
00777 if( (*iLightning)->age < 0.0 ) {
00778 delete (*iLightning);
00779 lightnings.erase( iLightning );
00780 break;
00781 }
00782 }
00783
00784 }
00785
00786
00787 void SGEnviro::setFOV( float w, float h ) {
00788 fov_width = w;
00789 fov_height = h;
00790 }
00791
00792 void SGEnviro::getFOV( float &w, float &h ) {
00793 w = fov_width;
00794 h = fov_height;
00795 }