]> git.mxchange.org Git - simgear.git/blob - simgear/sky/skydome.cxx
Working on ssg-ifying sky.
[simgear.git] / simgear / sky / skydome.cxx
1 // skydome.cxx -- model sky with an upside down "bowl"
2 //
3 // Written by Curtis Olson, started December 1997.
4 // SSG-ified by Curtis Olson, February 2000.
5 //
6 // Copyright (C) 1997-2000  Curtis L. Olson  - curt@flightgear.org
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 //
22 // $Id$
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #ifdef HAVE_WINDOWS_H
30 #  include <windows.h>
31 #endif
32
33 #include <math.h>
34
35 #include <GL/glut.h>
36 #include <simgear/xgl/xgl.h>
37
38 #include <simgear/constants.h>
39 #include <simgear/debug/logstream.hxx>
40 #include <simgear/math/fg_random.h>
41
42 // #include <Aircraft/aircraft.hxx>
43 // #include <FDM/flight.hxx>
44 // #include <Main/views.hxx>
45 // #include <Time/event.hxx>
46 // #include <Time/fg_time.hxx>
47
48 #include "skydome.hxx"
49
50
51 #ifdef __MWERKS__
52 #  pragma global_optimizer off
53 #endif
54
55
56 // in meters of course
57 #define CENTER_ELEV   25000.0
58
59 #define UPPER_RADIUS  50000.0
60 #define UPPER_ELEV    20000.0
61
62 #define MIDDLE_RADIUS 70000.0
63 #define MIDDLE_ELEV    8000.0
64
65 #define LOWER_RADIUS  80000.0
66 #define LOWER_ELEV        0.0
67
68 #define BOTTOM_RADIUS 50000.0
69 #define BOTTOM_ELEV   -2000.0
70
71
72 // Constructor
73 FGSkyDome::FGSkyDome( void ) {
74 }
75
76
77 // Destructor
78 FGSkyDome::~FGSkyDome( void ) {
79 }
80
81
82 // initialize the sky object and connect it into our scene graph
83 bool FGSkyDome::initialize( ) {
84     sgVec4 color;
85
86     float theta;
87     int i;
88
89     // create the scene graph for the dome
90     dome = new ssgRoot;
91     dome->setName( "Sky Dome" );
92
93     // set up the state
94     dome_state = new ssgSimpleState();
95     dome_state->setShadeModel( GL_SMOOTH );
96     dome_state->disable( GL_LIGHTING );
97     dome_state->disable( GL_CULL_FACE );
98     dome_state->disable( GL_TEXTURE_2D );
99     dome_state->enable( GL_COLOR_MATERIAL );
100     dome_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
101     dome_state->disable( GL_BLEND );
102     dome_state->disable( GL_ALPHA_TEST );
103
104     // initialize arrays
105     center_disk_vl = new ssgVertexArray( 14 );
106     center_disk_cl = new ssgColourArray( 14 );
107                                        
108     upper_ring_vl = new ssgVertexArray( 26 );
109     upper_ring_cl = new ssgColourArray( 26 );
110
111     middle_ring_vl = new ssgVertexArray( 26 );
112     middle_ring_cl = new ssgColourArray( 26 );
113
114     lower_ring_vl = new ssgVertexArray( 26 );
115     lower_ring_cl = new ssgColourArray( 26 );
116
117     // initially seed to all blue
118     sgSetVec4( color, 0.0, 0.0, 1.0, 1.0 );
119
120     // generate the raw vertex data
121     sgVec3 center_vertex;
122     sgVec3 upper_vertex[12];
123     sgVec3 middle_vertex[12];
124     sgVec3 lower_vertex[12];
125     sgVec3 bottom_vertex[12];
126
127     sgSetVec3( center_vertex, 0.0, 0.0, CENTER_ELEV );
128
129     for ( i = 0; i < 12; i++ ) {
130         theta = (i * 30.0) * DEG_TO_RAD;
131
132         sgSetVec3( upper_vertex[i],
133                    cos(theta) * UPPER_RADIUS,
134                    sin(theta) * UPPER_RADIUS,
135                    UPPER_ELEV );
136         
137         sgSetVec3( middle_vertex[i],
138                    cos((double)theta) * MIDDLE_RADIUS,
139                    sin((double)theta) * MIDDLE_RADIUS,
140                    MIDDLE_ELEV );
141
142         sgSetVec3( lower_vertex[i],
143                    cos((double)theta) * LOWER_RADIUS,
144                    sin((double)theta) * LOWER_RADIUS,
145                    LOWER_ELEV );
146
147         sgSetVec3( bottom_vertex[i],
148                    cos((double)theta) * BOTTOM_RADIUS,
149                    sin((double)theta) * BOTTOM_RADIUS,
150                    BOTTOM_ELEV );
151     }
152
153     // generate the center disk vertex/color arrays
154     center_disk_vl->add( center_vertex );
155     center_disk_cl->add( color );
156     for ( i = 11; i >= 0; i-- ) {
157         center_disk_vl->add( upper_vertex[i] );
158         center_disk_cl->add( color );
159     }
160     center_disk_vl->add( upper_vertex[11] );
161     center_disk_cl->add( color );
162
163     // generate the upper ring
164     for ( i = 0; i < 12; i++ ) {
165         upper_ring_vl->add( middle_vertex[i] );
166         upper_ring_cl->add( color );
167
168         upper_ring_vl->add( upper_vertex[i] );
169         upper_ring_cl->add( color );
170     }
171     upper_ring_vl->add( middle_vertex[0] );
172     upper_ring_cl->add( color );
173
174     upper_ring_vl->add( upper_vertex[0] );
175     upper_ring_cl->add( color );
176
177     // generate middle ring
178     for ( i = 0; i < 12; i++ ) {
179         middle_ring_vl->add( lower_vertex[i] );
180         middle_ring_cl->add( color );
181
182         middle_ring_vl->add( middle_vertex[i] );
183         middle_ring_cl->add( color );
184     }
185     middle_ring_vl->add( lower_vertex[0] );
186     middle_ring_cl->add( color );
187
188     middle_ring_vl->add( middle_vertex[0] );
189     middle_ring_cl->add( color );
190
191     // generate lower ring
192     for ( i = 0; i < 12; i++ ) {
193         lower_ring_vl->add( bottom_vertex[i] );
194         lower_ring_cl->add( color );
195
196         lower_ring_vl->add( lower_vertex[i] );
197         lower_ring_cl->add( color );
198     }
199     lower_ring_vl->add( bottom_vertex[0] );
200     lower_ring_cl->add( color );
201
202     lower_ring_vl->add( lower_vertex[0] );
203     lower_ring_cl->add( color );
204
205     // force a repaint of the sky colors with ugly defaults
206     sgVec3 fog_color;
207     sgSetVec3( fog_color, 1.0, 1.0, 1.0 );
208     repaint( color, fog_color, 0.0 );
209
210     // build the ssg scene graph sub tree for the sky and connected
211     // into the provide scene graph branch
212     dome_selector = new ssgSelector;
213     dome_transform = new ssgTransform;
214
215     ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring;
216
217     center_disk = new ssgVtxTable( GL_TRIANGLE_FAN, 
218                                    center_disk_vl, NULL, NULL, center_disk_cl );
219
220     upper_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, 
221                                   upper_ring_vl, NULL, NULL, upper_ring_cl );
222
223     middle_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, 
224                                    middle_ring_vl, NULL, NULL, middle_ring_cl );
225
226     lower_ring = new ssgVtxTable( GL_TRIANGLE_STRIP, 
227                                   lower_ring_vl, NULL, NULL, lower_ring_cl );
228
229     center_disk->setState( dome_state );
230     upper_ring->setState( dome_state );
231     middle_ring->setState( dome_state );
232     lower_ring->setState( dome_state );
233
234     dome_transform->addKid( center_disk );
235     dome_transform->addKid( upper_ring );
236     dome_transform->addKid( middle_ring );
237     dome_transform->addKid( lower_ring );
238
239     dome_selector->addKid( dome_transform );
240     dome_selector->clrTraversalMaskBits( SSGTRAV_HOT );
241
242     dome->addKid( dome_selector );
243
244     return true;
245 }
246
247
248 // repaint the sky colors based on current value of sun_angle, sky,
249 // and fog colors.  This updates the color arrays for ssgVtxTable.
250 // sun angle in degrees relative to verticle
251 // 0 degrees = high noon
252 // 90 degrees = sun rise/set
253 // 180 degrees = darkest midnight
254 bool FGSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle )
255 {
256     double diff;
257     sgVec3 outer_param, outer_amt, outer_diff;
258     sgVec3 middle_param, middle_amt, middle_diff;
259     int i, j;
260
261     // Check for sunrise/sunset condition
262     if ( (sun_angle > 80.0) && (sun_angle < 100.0) ) {
263         // 0.0 - 0.4
264         sgSetVec3( outer_param,
265                    (10.0 - fabs(90.0 - sun_angle)) / 20.0,
266                    (10.0 - fabs(90.0 - sun_angle)) / 40.0,
267                    -(10.0 - fabs(90.0 - sun_angle)) / 30.0 );
268
269         sgSetVec3( middle_param,
270                    (10.0 - fabs(90.0 - sun_angle)) / 40.0,
271                    (10.0 - fabs(90.0 - sun_angle)) / 80.0,
272                    0.0 );
273
274         sgScaleVec3( outer_diff, outer_param, 1.0 / 6.0 );
275
276         sgScaleVec3( middle_diff, middle_param, 1.0 / 6.0 );
277     } else {
278         sgSetVec3( outer_param, 0.0, 0.0, 0.0 );
279         sgSetVec3( middle_param, 0.0, 0.0, 0.0 );
280
281         sgSetVec3( outer_diff, 0.0, 0.0, 0.0 );
282         sgSetVec3( middle_diff, 0.0, 0.0, 0.0 );
283     }
284     // printf("  outer_red_param = %.2f  outer_red_diff = %.2f\n", 
285     //        outer_red_param, outer_red_diff);
286
287     // calculate transition colors between sky and fog
288     sgCopyVec3( outer_amt, outer_param );
289     sgCopyVec3( middle_amt, middle_param );
290
291     //
292     // First, recalulate the basic colors
293     //
294
295     sgVec4 upper_color[12];
296     sgVec4 middle_color[12];
297     sgVec4 lower_color[12];
298     sgVec4 bottom_color[12];
299
300     for ( i = 0; i < 6; i++ ) {
301         for ( j = 0; j < 3; j++ ) {
302             diff = sky_color[j] - fog_color[j];
303
304             // printf("sky = %.2f  fog = %.2f  diff = %.2f\n", 
305             //        l->sky_color[j], l->fog_color[j], diff);
306
307             upper_color[i][j] = sky_color[j] - diff * 0.3;
308             middle_color[i][j] = sky_color[j] - diff * 0.9 + middle_amt[j];
309             lower_color[i][j] = fog_color[j] + outer_amt[j];
310
311             if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
312             if ( upper_color[i][j] < 0.1 ) { upper_color[i][j] = 0.1; }
313             if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
314             if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
315             if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
316             if ( lower_color[i][j] < 0.1 ) { lower_color[i][j] = 0.1; }
317         }
318         upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
319
320         for ( j = 0; j < 3; j++ ) {
321             outer_amt[j] -= outer_diff[j];
322             middle_amt[j] -= middle_diff[j];
323         }
324
325         /*
326         printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
327                upper_color[i][1], upper_color[i][2], upper_color[i][3]);
328         printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
329                middle_color[i][0], middle_color[i][1], middle_color[i][2], 
330                middle_color[i][3]);
331         printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
332                lower_color[i][0], lower_color[i][1], lower_color[i][2], 
333                lower_color[i][3]);
334         */
335     }
336
337     sgSetVec3( outer_amt, 0.0, 0.0, 0.0 );
338     sgSetVec3( middle_amt, 0.0, 0.0, 0.0 );
339
340     for ( i = 6; i < 12; i++ ) {
341         for ( j = 0; j < 3; j++ ) {
342             diff = sky_color[j] - fog_color[j];
343
344             // printf("sky = %.2f  fog = %.2f  diff = %.2f\n", 
345             //        sky_color[j], fog_color[j], diff);
346
347             upper_color[i][j] = sky_color[j] - diff * 0.3;
348             middle_color[i][j] = sky_color[j] - diff * 0.9 + middle_amt[j];
349             lower_color[i][j] = fog_color[j] + outer_amt[j];
350
351             if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
352             if ( upper_color[i][j] < 0.1 ) { upper_color[i][j] = 0.1; }
353             if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
354             if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
355             if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
356             if ( lower_color[i][j] < 0.1 ) { lower_color[i][j] = 0.1; }
357         }
358         upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
359
360         for ( j = 0; j < 3; j++ ) {
361             outer_amt[j] += outer_diff[j];
362             middle_amt[j] += middle_diff[j];
363         }
364
365         /*
366         printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
367                upper_color[i][1], upper_color[i][2], upper_color[i][3]);
368         printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
369                middle_color[i][0], middle_color[i][1], middle_color[i][2], 
370                middle_color[i][3]);
371         printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
372                lower_color[i][0], lower_color[i][1], lower_color[i][2], 
373                lower_color[i][3]);
374         */
375     }
376
377     for ( i = 0; i < 12; i++ ) {
378         sgCopyVec4( bottom_color[i], fog_color );
379     }
380
381     //
382     // Second, assign the basic colors to the object color arrays
383     //
384
385     float *slot;
386     int counter;
387
388     // update the center disk color arrays
389     counter = 0;
390     slot = center_disk_cl->get( counter++ );
391     // sgVec4 red;
392     // sgSetVec4( red, 1.0, 0.0, 0.0, 1.0 );
393     sgCopyVec4( slot, sky_color );
394     for ( i = 11; i >= 0; i-- ) {
395         slot = center_disk_cl->get( counter++ );
396         sgCopyVec4( slot, upper_color[i] );
397     }
398     slot = center_disk_cl->get( counter++ );
399     sgCopyVec4( slot, upper_color[11] );
400
401     // generate the upper ring
402     counter = 0;
403     for ( i = 0; i < 12; i++ ) {
404         slot = upper_ring_cl->get( counter++ );
405         sgCopyVec4( slot, middle_color[i] );
406
407         slot = upper_ring_cl->get( counter++ );
408         sgCopyVec4( slot, upper_color[i] );
409     }
410     slot = upper_ring_cl->get( counter++ );
411     sgCopyVec4( slot, middle_color[0] );
412
413     slot = upper_ring_cl->get( counter++ );
414     sgCopyVec4( slot, upper_color[0] );
415
416     // generate middle ring
417     counter = 0;
418     for ( i = 0; i < 12; i++ ) {
419         slot = middle_ring_cl->get( counter++ );
420         sgCopyVec4( slot, lower_color[i] );
421
422         slot = middle_ring_cl->get( counter++ );
423         sgCopyVec4( slot, middle_color[i] );
424     }
425     slot = middle_ring_cl->get( counter++ );
426     sgCopyVec4( slot, lower_color[0] );
427
428     slot = middle_ring_cl->get( counter++ );
429     sgCopyVec4( slot, middle_color[0] );
430
431     // generate lower ring
432     counter = 0;
433     for ( i = 0; i < 12; i++ ) {
434         slot = lower_ring_cl->get( counter++ );
435         sgCopyVec4( slot, bottom_color[i] );
436
437         slot = lower_ring_cl->get( counter++ );
438         sgCopyVec4( slot, lower_color[i] );
439     }
440     slot = lower_ring_cl->get( counter++ );
441     sgCopyVec4( slot, bottom_color[0] );
442
443     slot = lower_ring_cl->get( counter++ );
444     sgCopyVec4( slot, lower_color[0] );
445
446     return true;
447 }
448
449
450 // reposition the sky at the specified origin and orientation
451 // lon specifies a rotation about the Z axis
452 // lat specifies a rotation about the new Y axis
453 // spin specifies a rotation about the new Z axis (and orients the
454 // sunrise/set effects
455 bool FGSkyDome::reposition( sgVec3 p, double lon, double lat, double spin ) {
456     sgMat4 T, LON, LAT, SPIN;
457     sgVec3 axis;
458
459     // Translate to view position
460     // Point3D zero_elev = current_view.get_cur_zero_elev();
461     // xglTranslatef( zero_elev.x(), zero_elev.y(), zero_elev.z() );
462     sgMakeTransMat4( T, p );
463
464     // printf("  Translated to %.2f %.2f %.2f\n", 
465     //        zero_elev.x, zero_elev.y, zero_elev.z );
466
467     // Rotate to proper orientation
468     // printf("  lon = %.2f  lat = %.2f\n", FG_Longitude * RAD_TO_DEG,
469     //        FG_Latitude * RAD_TO_DEG);
470     // xglRotatef( f->get_Longitude() * RAD_TO_DEG, 0.0, 0.0, 1.0 );
471     sgSetVec3( axis, 0.0, 0.0, 1.0 );
472     sgMakeRotMat4( LON, lon * RAD_TO_DEG, axis );
473
474     // xglRotatef( 90.0 - f->get_Latitude() * RAD_TO_DEG, 0.0, 1.0, 0.0 );
475     sgSetVec3( axis, 0.0, 1.0, 0.0 );
476     sgMakeRotMat4( LAT, 90.0 - lat * RAD_TO_DEG, axis );
477
478     // xglRotatef( l->sun_rotation * RAD_TO_DEG, 0.0, 0.0, 1.0 );
479     sgSetVec3( axis, 0.0, 0.0, 1.0 );
480     sgMakeRotMat4( SPIN, spin * RAD_TO_DEG, axis );
481
482     sgMat4 TRANSFORM;
483
484     sgCopyMat4( TRANSFORM, T );
485     sgPreMultMat4( TRANSFORM, LON );
486     sgPreMultMat4( TRANSFORM, LAT );
487     sgPreMultMat4( TRANSFORM, SPIN );
488
489     sgCoord skypos;
490     sgSetCoord( &skypos, TRANSFORM );
491
492     dome_transform->setTransform( &skypos );
493
494     return true;
495 }
496
497
498 // Draw the skydome
499 bool FGSkyDome::draw() {
500     ssgCullAndDraw( dome );
501
502     return true;
503 }
504
505
506 #if 0
507
508 // depricated code from here to the end 
509
510
511 // Calculate the sky structure vertices
512 void fgSkyVerticesInit() {
513     float theta;
514     int i;
515
516     FG_LOG(FG_ASTRO, FG_INFO, "  Generating the sky dome vertices.");
517
518     for ( i = 0; i < 12; i++ ) {
519         theta = (i * 30.0) * DEG_TO_RAD;
520         
521         inner_vertex[i][0] = cos(theta) * UPPER_RADIUS;
522         inner_vertex[i][1] = sin(theta) * UPPER_RADIUS;
523         inner_vertex[i][2] = UPPER_ELEV;
524         
525         // printf("    %.2f %.2f\n", cos(theta) * UPPER_RADIUS, 
526         //        sin(theta) * UPPER_RADIUS);
527
528         middle_vertex[i][0] = cos((double)theta) * MIDDLE_RADIUS;
529         middle_vertex[i][1] = sin((double)theta) * MIDDLE_RADIUS;
530         middle_vertex[i][2] = MIDDLE_ELEV;
531             
532         outer_vertex[i][0] = cos((double)theta) * LOWER_RADIUS;
533         outer_vertex[i][1] = sin((double)theta) * LOWER_RADIUS;
534         outer_vertex[i][2] = LOWER_ELEV;
535             
536         bottom_vertex[i][0] = cos((double)theta) * BOTTOM_RADIUS;
537         bottom_vertex[i][1] = sin((double)theta) * BOTTOM_RADIUS;
538         bottom_vertex[i][2] = BOTTOM_ELEV;
539     }
540 }
541
542
543 // (Re)calculate the sky colors at each vertex
544 void fgSkyColorsInit() {
545     fgLIGHT *l;
546     double sun_angle, diff;
547     double outer_param[3], outer_amt[3], outer_diff[3];
548     double middle_param[3], middle_amt[3], middle_diff[3];
549     int i, j;
550
551     l = &cur_light_params;
552
553     FG_LOG( FG_ASTRO, FG_INFO, 
554             "  Generating the sky colors for each vertex." );
555
556     // setup for the possibility of sunset effects
557     sun_angle = l->sun_angle * RAD_TO_DEG;
558     // fgPrintf( FG_ASTRO, FG_INFO, 
559     //           "  Sun angle in degrees = %.2f\n", sun_angle);
560
561     if ( (sun_angle > 80.0) && (sun_angle < 100.0) ) {
562         // 0.0 - 0.4
563         outer_param[0] = (10.0 - fabs(90.0 - sun_angle)) / 20.0;
564         outer_param[1] = (10.0 - fabs(90.0 - sun_angle)) / 40.0;
565         outer_param[2] = -(10.0 - fabs(90.0 - sun_angle)) / 30.0;
566         // outer_param[2] = 0.0;
567
568         middle_param[0] = (10.0 - fabs(90.0 - sun_angle)) / 40.0;
569         middle_param[1] = (10.0 - fabs(90.0 - sun_angle)) / 80.0;
570         middle_param[2] = 0.0;
571
572         outer_diff[0] = outer_param[0] / 6.0;
573         outer_diff[1] = outer_param[1] / 6.0;
574         outer_diff[2] = outer_param[2] / 6.0;
575
576         middle_diff[0] = middle_param[0] / 6.0;
577         middle_diff[1] = middle_param[1] / 6.0;
578         middle_diff[2] = middle_param[2] / 6.0;
579     } else {
580         outer_param[0] = outer_param[1] = outer_param[2] = 0.0;
581         middle_param[0] = middle_param[1] = middle_param[2] = 0.0;
582
583         outer_diff[0] = outer_diff[1] = outer_diff[2] = 0.0;
584         middle_diff[0] = middle_diff[1] = middle_diff[2] = 0.0;
585     }
586     // printf("  outer_red_param = %.2f  outer_red_diff = %.2f\n", 
587     //        outer_red_param, outer_red_diff);
588
589     // calculate transition colors between sky and fog
590     for ( j = 0; j < 3; j++ ) {
591         outer_amt[j] = outer_param[j];
592         middle_amt[j] = middle_param[j];
593     }
594
595     for ( i = 0; i < 6; i++ ) {
596         for ( j = 0; j < 3; j++ ) {
597             diff = l->sky_color[j] - l->fog_color[j];
598
599             // printf("sky = %.2f  fog = %.2f  diff = %.2f\n", 
600             //        l->sky_color[j], l->fog_color[j], diff);
601
602             upper_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
603             middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9 
604                                            + middle_amt[j]) * 255);
605             lower_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j]) 
606                                           * 255);
607
608             if ( upper_color[i][j] > 255 ) { upper_color[i][j] = 255; }
609             if ( upper_color[i][j] < 25 ) { upper_color[i][j] = 25; }
610             if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
611             if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
612             if ( lower_color[i][j] > 255 ) { lower_color[i][j] = 255; }
613             if ( lower_color[i][j] < 25 ) { lower_color[i][j] = 25; }
614         }
615         upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 
616             (GLubyte)(l->sky_color[3] * 255);
617
618         for ( j = 0; j < 3; j++ ) {
619             outer_amt[j] -= outer_diff[j];
620             middle_amt[j] -= middle_diff[j];
621         }
622
623         /*
624         printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
625                upper_color[i][1], upper_color[i][2], upper_color[i][3]);
626         printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
627                middle_color[i][0], middle_color[i][1], middle_color[i][2], 
628                middle_color[i][3]);
629         printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
630                lower_color[i][0], lower_color[i][1], lower_color[i][2], 
631                lower_color[i][3]);
632         */
633     }
634
635     for ( j = 0; j < 3; j++ ) {
636         outer_amt[j] = 0.0;
637         middle_amt[j] = 0.0;
638     }
639
640     for ( i = 6; i < 12; i++ ) {
641
642         for ( j = 0; j < 3; j++ ) {
643             diff = l->sky_color[j] - l->fog_color[j];
644
645             // printf("sky = %.2f  fog = %.2f  diff = %.2f\n", 
646             //        l->sky_color[j], l->fog_color[j], diff);
647
648             upper_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
649             middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9 
650                                             + middle_amt[j]) * 255);
651             lower_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j]) 
652                                           * 255);
653
654             if ( upper_color[i][j] > 255 ) { upper_color[i][j] = 255; }
655             if ( upper_color[i][j] < 25 ) { upper_color[i][j] = 25; }
656             if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
657             if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
658             if ( lower_color[i][j] > 255 ) { lower_color[i][j] = 255; }
659             if ( lower_color[i][j] < 35 ) { lower_color[i][j] = 35; }
660         }
661         upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 
662             (GLubyte)(l->sky_color[3] * 255);
663
664         for ( j = 0; j < 3; j++ ) {
665             outer_amt[j] += outer_diff[j];
666             middle_amt[j] += middle_diff[j];
667         }
668
669         /*
670         printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
671                upper_color[i][1], upper_color[i][2], upper_color[i][3]);
672         printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
673                middle_color[i][0], middle_color[i][1], middle_color[i][2], 
674                middle_color[i][3]);
675         printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
676                lower_color[i][0], lower_color[i][1], lower_color[i][2], 
677                lower_color[i][3]);
678         */
679     }
680 }
681
682
683 // Initialize the sky structure and colors
684 void fgSkyInit() {
685     FG_LOG( FG_ASTRO, FG_INFO, "Initializing the sky" );
686
687     fgSkyVerticesInit();
688
689     // regester fgSkyColorsInit() as an event to be run periodically
690     global_events.Register( "fgSkyColorsInit()", fgSkyColorsInit, 
691                             fgEVENT::FG_EVENT_READY, 30000);
692 }
693
694
695 // Draw the Sky
696 void fgSkyRender() {
697     FGInterface *f;
698     fgLIGHT *l;
699     GLubyte sky_color[4];
700     GLubyte upper_color[4];
701     GLubyte middle_color[4];
702     GLubyte lower_color[4];
703     double diff;
704     int i;
705
706     f = current_aircraft.fdm_state;
707     l = &cur_light_params;
708
709     // printf("Rendering the sky.\n");
710
711     // calculate the proper colors
712     for ( i = 0; i < 3; i++ ) {
713         diff = l->sky_color[i] - l->adj_fog_color[i];
714
715         // printf("sky = %.2f  fog = %.2f  diff = %.2f\n", 
716         //        l->sky_color[j], l->adj_fog_color[j], diff);
717
718         upper_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.3) * 255);
719         middle_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.9) * 255);
720         lower_color[i] = (GLubyte)(l->adj_fog_color[i] * 255);
721     }
722     upper_color[3] = middle_color[3] = lower_color[3] = 
723         (GLubyte)(l->adj_fog_color[3] * 255);
724
725     xglPushMatrix();
726
727     // Translate to view position
728     Point3D zero_elev = current_view.get_cur_zero_elev();
729     xglTranslatef( zero_elev.x(), zero_elev.y(), zero_elev.z() );
730     // printf("  Translated to %.2f %.2f %.2f\n", 
731     //        zero_elev.x, zero_elev.y, zero_elev.z );
732
733     // Rotate to proper orientation
734     // printf("  lon = %.2f  lat = %.2f\n", FG_Longitude * RAD_TO_DEG,
735     //        FG_Latitude * RAD_TO_DEG);
736     xglRotatef( f->get_Longitude() * RAD_TO_DEG, 0.0, 0.0, 1.0 );
737     xglRotatef( 90.0 - f->get_Latitude() * RAD_TO_DEG, 0.0, 1.0, 0.0 );
738     xglRotatef( l->sun_rotation * RAD_TO_DEG, 0.0, 0.0, 1.0 );
739
740     // Draw inner/center section of sky*/
741     xglBegin( GL_TRIANGLE_FAN );
742     for ( i = 0; i < 4; i++ ) {
743         sky_color[i] = (GLubyte)(l->sky_color[i] * 255);
744     }
745     xglColor4fv(l->sky_color);
746     xglVertex3f(0.0, 0.0, CENTER_ELEV);
747     for ( i = 11; i >= 0; i-- ) {
748         xglColor4ubv( upper_color );
749         xglVertex3fv( inner_vertex[i] );
750     }
751     xglColor4ubv( upper_color );
752     xglVertex3fv( inner_vertex[11] );
753     xglEnd();
754
755     // Draw the middle ring
756     xglBegin( GL_TRIANGLE_STRIP );
757     for ( i = 0; i < 12; i++ ) {
758         xglColor4ubv( middle_color );
759         // printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
760         //        middle_color[i][0], middle_color[i][1], middle_color[i][2], 
761         //        middle_color[i][3]);
762         // xglColor4f(1.0, 0.0, 0.0, 1.0);
763         xglVertex3fv( middle_vertex[i] );
764         xglColor4ubv( upper_color );
765         // printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, 
766         //        upper_color[i][0], upper_color[i][1], upper_color[i][2], 
767         //        upper_color[i][3]);
768         // xglColor4f(0.0, 0.0, 1.0, 1.0);
769         xglVertex3fv( inner_vertex[i] );
770     }
771     xglColor4ubv( middle_color );
772     // xglColor4f(1.0, 0.0, 0.0, 1.0);
773     xglVertex3fv( middle_vertex[0] );
774     xglColor4ubv( upper_color );
775     // xglColor4f(0.0, 0.0, 1.0, 1.0);
776     xglVertex3fv( inner_vertex[0] );
777     xglEnd();
778
779     // Draw the outer ring
780     xglBegin( GL_TRIANGLE_STRIP );
781     for ( i = 0; i < 12; i++ ) {
782         xglColor4ubv( lower_color );
783         xglVertex3fv( outer_vertex[i] );
784         xglColor4ubv( middle_color );
785         xglVertex3fv( middle_vertex[i] );
786     }
787     xglColor4ubv( lower_color );
788     xglVertex3fv( outer_vertex[0] );
789     xglColor4ubv( middle_color );
790     xglVertex3fv( middle_vertex[0] );
791     xglEnd();
792
793     // Draw the bottom skirt
794     xglBegin( GL_TRIANGLE_STRIP );
795     xglColor4ubv( lower_color );
796     for ( i = 0; i < 12; i++ ) {
797         xglVertex3fv( bottom_vertex[i] );
798         xglVertex3fv( outer_vertex[i] );
799     }
800     xglVertex3fv( bottom_vertex[0] );
801     xglVertex3fv( outer_vertex[0] );
802     xglEnd();
803
804     xglPopMatrix();
805 }
806
807
808 #endif