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