]> git.mxchange.org Git - flightgear.git/blob - Cockpit/hud.c
Thursday's tweaks.
[flightgear.git] / Cockpit / hud.c
1 /**************************************************************************
2  * hud.c -- hud defines and prototypes
3  *
4  * Written by Michele America, started September 1997.
5  *
6  * Copyright (C) 1997  Michele F. America  - nomimarketing@mail.telepac.pt
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  * (Log is kept at end of this file)
24  **************************************************************************/
25  
26
27 #ifdef WIN32
28 #  include <windows.h>
29 #endif
30
31 #include <GL/glut.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifndef WIN32
36 #  include <values.h>  // for MAXINT
37 #endif //
38
39 #include "hud.h"
40
41 #include <Include/fg_constants.h>
42 #include <Aircraft/aircraft.h>
43 #include <Main/fg_debug.h>
44 #include <Math/fg_random.h>
45 #include <Math/mat3.h>
46 #include <Math/polar.h>
47 #include <Scenery/scenery.h>
48 #include <Time/fg_timer.h>
49 #include <Weather/weather.h>
50
51 // #define DEBUG
52
53 #define drawOneLine(x1,y1,x2,y2)  glBegin(GL_LINES);  \
54    glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
55
56
57 // The following routines obtain information concerntin the aircraft's
58 // current state and return it to calling instrument display routines.
59 // They should eventually be member functions of the aircraft.
60 //
61
62 double get_throttleval( void )
63 {
64         fgCONTROLS *pcontrols;
65
66   pcontrols = current_aircraft.controls;
67   return pcontrols->throttle[0];     // Hack limiting to one engine
68 }
69
70 double get_aileronval( void )
71 {
72         fgCONTROLS *pcontrols;
73
74   pcontrols = current_aircraft.controls;
75   return pcontrols->aileron;
76 }
77
78 double get_elevatorval( void )
79 {
80         fgCONTROLS *pcontrols;
81
82   pcontrols = current_aircraft.controls;
83   return pcontrols->elevator;
84 }
85
86 double get_elev_trimval( void )
87 {
88         fgCONTROLS *pcontrols;
89
90   pcontrols = current_aircraft.controls;
91   return pcontrols->elevator_trim;
92 }
93
94 double get_rudderval( void )
95 {
96         fgCONTROLS *pcontrols;
97
98   pcontrols = current_aircraft.controls;
99   return pcontrols->rudder;
100 }
101
102 double get_speed( void )
103 {
104         fgFLIGHT *f;
105
106         f = current_aircraft.flight;
107         return( FG_V_equiv_kts );    // Make an explicit function call.
108 }
109
110 double get_aoa( void )
111 {
112         fgFLIGHT *f;
113               
114         f = current_aircraft.flight;
115         return( FG_Gamma_vert_rad * RAD_TO_DEG );
116 }
117
118 double get_roll( void )
119 {
120         fgFLIGHT *f;
121
122         f = current_aircraft.flight;
123         return( FG_Phi );
124 }
125
126 double get_pitch( void )
127 {
128         fgFLIGHT *f;
129               
130         f = current_aircraft.flight;
131         return( FG_Theta );
132 }
133
134 double get_heading( void )
135 {
136         fgFLIGHT *f;
137
138         f = current_aircraft.flight;
139         return( FG_Psi*RAD_TO_DEG );
140 }
141
142 double get_altitude( void )
143 {
144         fgFLIGHT *f;
145         // double rough_elev;
146
147         f = current_aircraft.flight;
148         // rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
149         //                                 FG_Latitude  * RAD_TO_ARCSEC);
150
151         return( FG_Altitude * FEET_TO_METER /* -rough_elev */ );
152 }
153
154 double get_sideslip( void )
155 {
156         fgFLIGHT *f;
157         
158         f = current_aircraft.flight;
159         
160         return( FG_Beta );
161 }
162
163 //
164 // The following code deals with painting the "instrument" on the display
165 //
166    /* textString - Bitmap font string */
167
168 static void textString(int x, int y, char *msg, void *font)
169 {
170         glRasterPos2f(x, y);
171         while (*msg) {
172                 glutBitmapCharacter(font, *msg);
173                 msg++;
174     }
175 }
176
177 /* strokeString - Stroke font string */
178 /*
179 static void strokeString(int x, int y, char *msg, void *font)
180 {
181         glPushMatrix();
182         glTranslatef(x, y, 0);
183         glScalef(.04, .04, .04);
184         while (*msg) {
185                 glutStrokeCharacter(font, *msg);
186                 msg++;
187         }
188         glPopMatrix();
189 }
190 */
191
192 /*
193
194         Draws a measuring scale anywhere on the HUD
195
196
197         Needs: HUD_scale struct
198
199 */
200 static void drawscale( HUD_scale * pscale )
201 {
202   double vmin, vmax;
203   int marker_x;
204   int marker_y;
205   int scr_span;
206   int mid_scr;
207   register i;
208   double factor;
209   char TextScale[80];
210   int condition;
211   double cur_value = (*(pscale->load_value))();
212
213   vmin = cur_value - pscale->width_units / 2.0; // width units == needle travel
214   vmax = cur_value + pscale->width_units / 2.0; // or picture unit span.
215
216   scr_span = pscale->scr_max - pscale->scr_min; // Run of scan in pix coord
217   scr_span |= 1;  // If span is odd number of units, mid will be correct.
218                   // If not it will be high by one coordinate unit. This is
219                   // an artifact of integer division needed for screen loc's.
220
221   mid_scr  = (scr_span >> 1) + pscale->scr_min; // Middle is half that +
222                                                 // starting point.
223
224              // Calculate the number of screen units per indicator unit
225              // We must force floating point calculation or the factor
226              // will be low and miss locate tics by several units.
227
228   factor   = (double)scr_span / (double)pscale->width_units;
229
230              // Separate calculations for location of markings by scale
231              // type V vs H.
232
233   if( pscale->type == VERTICAL )     // Vertical scale
234     {
235
236     if( pscale->orientation == LEFT )     // Calculate x marker offset
237       marker_x = pscale->scr_pos-6;
238     else
239       if( pscale->orientation == RIGHT )
240         marker_x = pscale->scr_pos;
241
242     // Draw the basic markings for the scale...
243
244     drawOneLine( pscale->scr_pos,         // Vertical bar
245                  pscale->scr_min,
246                  pscale->scr_pos,
247                  pscale->scr_max );
248     if( pscale->orientation == LEFT )
249       {
250       drawOneLine( pscale->scr_pos-3,     // Bottom tick bar
251                    pscale->scr_min,
252                    pscale->scr_pos,
253                    pscale->scr_min );
254
255       drawOneLine( pscale->scr_pos-3,     // Top tick bar
256                    pscale->scr_max,
257                    pscale->scr_pos,
258                    pscale->scr_max );
259
260       drawOneLine( pscale->scr_pos,       // Middle tick bar /Index
261                    mid_scr,
262                    pscale->scr_pos+6,
263                    mid_scr );
264
265       }
266     else
267       if( pscale->orientation == RIGHT )
268         {
269         drawOneLine( pscale->scr_pos,
270                      pscale->scr_min,
271                      pscale->scr_pos+3,
272                      pscale->scr_min );
273
274         drawOneLine( pscale->scr_pos,
275                      pscale->scr_max,
276                      pscale->scr_pos+3,
277                      pscale->scr_max );
278
279         drawOneLine( pscale->scr_pos,
280                      mid_scr,
281                      pscale->scr_pos-6,
282                      mid_scr );
283         }
284
285     // Work through from bottom to top of scale. Calculating where to put
286     // minor and major ticks.
287
288     for( i = vmin; i <= vmax; i++ )
289       {
290       if( pscale->sub_type == LIMIT ) {           // Don't show ticks
291         condition = (i >= pscale->minimum_value); // below Minimum value.
292         }
293       else {
294         if( pscale->sub_type == NOLIMIT ) {
295           condition = 1;
296           }
297         }
298       if( condition )   // Show a tick if necessary
299         {
300         // Calculate the location of this tick
301         marker_y = pscale->scr_min + (i - vmin) * factor;
302
303         // Block calculation artifact from drawing ticks below min coordinate.
304         // Calculation here accounts for text height.
305
306         if( marker_y < (pscale->scr_min + 4)) {  // Magic number!!!
307           continue;
308           }
309         if( (i%pscale->div_min) == 0) {
310           if( pscale->orientation == LEFT )
311             {
312             drawOneLine( marker_x + 3, marker_y, marker_x + 6, marker_y );
313             }
314           else {
315             if( pscale->orientation == RIGHT )
316               {
317               drawOneLine( marker_x, marker_y, marker_x + 3, marker_y );
318               }
319             }
320           }
321         if( (i%pscale->div_max) == 0 )            {
322           drawOneLine( marker_x,     marker_y,
323                        marker_x + 6, marker_y );
324           sprintf( TextScale, "%d", i );
325           if( pscale->orientation == LEFT )              {
326             textString( marker_x -  8 * strlen(TextScale) - 2, marker_y - 4,
327                         TextScale, GLUT_BITMAP_8_BY_13 );
328             }
329           else  {
330             if( pscale->orientation == RIGHT )              {
331             textString( marker_x + 10,                         marker_y - 4,
332                         TextScale, GLUT_BITMAP_8_BY_13 );
333               }
334             }
335           }
336         } // End if condition
337       } // End for range of i from vmin to vmax
338     }  // End if VERTICAL SCALE TYPE
339   if( pscale->type == HORIZONTAL )     // Horizontal scale
340     {
341     if( pscale->orientation == TOP ) {
342       marker_y = pscale->scr_pos;
343       }
344     else {
345       if( pscale->orientation == BOTTOM ) {
346         marker_y = pscale->scr_pos - 6;
347         }
348       }
349     drawOneLine( pscale->scr_min,
350                  pscale->scr_pos,
351                  pscale->scr_max,
352                  pscale->scr_pos );
353     if( pscale->orientation == TOP )
354       {
355       drawOneLine( pscale->scr_min,
356                    pscale->scr_pos,
357                    pscale->scr_min,
358                    pscale->scr_pos-3 );
359
360       drawOneLine( pscale->scr_max,
361                    pscale->scr_pos,
362                    pscale->scr_max,
363                    pscale->scr_pos-3 );
364
365       drawOneLine( mid_scr,
366                    pscale->scr_pos,
367                    mid_scr,
368                    pscale->scr_pos-6 );
369
370       }
371     else {
372       if( pscale->orientation == BOTTOM )
373         {
374         drawOneLine( pscale->scr_min,
375                      pscale->scr_pos,
376                      pscale->scr_min,
377                      pscale->scr_pos+3 );
378
379         drawOneLine( pscale->scr_max,
380                      pscale->scr_pos,
381                      pscale->scr_max,
382                      pscale->scr_pos+3 );
383
384         drawOneLine( mid_scr,
385                      pscale->scr_pos,
386                      mid_scr,
387                      pscale->scr_pos+6 );
388         }
389       }
390
391     for( i = vmin; i <= vmax; i++ )  // increment is faster than addition
392       {
393       if( pscale->sub_type == LIMIT ) {
394         condition = (i >= pscale->minimum_value);
395         }
396       else {
397         if( pscale->sub_type == NOLIMIT ) {
398           condition = 1;
399           }
400         }
401       if( condition )        {
402         marker_x = pscale->scr_min+(i-vmin)*factor;
403         if( i%pscale->div_min==0 ) {
404           if( pscale->orientation == TOP )
405             {
406             drawOneLine( marker_x, marker_y, marker_x, marker_y+3 );
407             }
408           else {
409             if( pscale->orientation == BOTTOM )
410               {
411               drawOneLine( marker_x, marker_y+3, marker_x, marker_y+6 );
412               }
413             }
414           }
415         if( i%pscale->div_max==0 )
416           {
417           sprintf( TextScale, "%d", i );
418           if( pscale->orientation == TOP )
419             {
420             drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
421             textString ( marker_x-4*strlen(TextScale), marker_y+14,
422                          TextScale, GLUT_BITMAP_8_BY_13 );
423             }
424           else {
425             if( pscale->orientation == BOTTOM )
426               {
427               drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
428               textString ( marker_x+10, marker_y-4,
429                            TextScale, GLUT_BITMAP_8_BY_13 );
430               }
431             }
432           }
433         }
434       }
435     }
436
437 }
438
439 //
440 //      Draws a climb ladder in the center of the HUD
441 //
442
443 static void drawladder( HUD_ladder *ladder )
444 {
445   double vmin, vmax;
446   double roll_value, pitch_value;
447   int marker_x, marker_y;
448 #ifdef DEBUGHUD
449   int mid_scr;
450 #endif
451   int scr_min, scr_max;
452   int x_ini, x_end;
453   int y_ini, y_end;
454   int new_x_ini, new_x_end;
455   int new_y_ini, new_y_end;
456   register i;
457   double factor;
458   char TextLadder[80];
459   int condition;
460
461   roll_value = (*ladder->load_roll)();
462   pitch_value = (*ladder->load_pitch)()*RAD_TO_DEG;
463
464   vmin = pitch_value - ladder->width_units/2;
465   vmax = pitch_value + ladder->width_units/2;
466
467   scr_min = ladder->y_pos - (ladder->scr_height/2);
468   scr_max = scr_min       + ladder->scr_height;
469
470 #ifdef DEBUGHUD
471   mid_scr = scr_min       + (scr_max-scr_min)/2;
472 #endif
473
474   marker_x = ladder->x_pos - ladder->scr_width/2;
475
476   factor = (scr_max-scr_min)/ladder->width_units;
477
478   for( i=vmin; i<=vmax; i+=1 )
479     {
480     condition = 1;
481     if( condition )
482       {
483       marker_y = scr_min+(i-vmin)*factor;
484       if( i%ladder->div_units==0 )
485         {
486         sprintf( TextLadder, "%d", i );
487         if( ladder->scr_hole == 0 )
488           {
489           if( i ) {
490             x_ini = ladder->x_pos - ladder->scr_width/2;
491             }
492           else {
493             x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
494             }
495           y_ini = marker_y;
496           x_end = ladder->x_pos + ladder->scr_width/2;
497           y_end = marker_y;
498           new_x_ini = ladder->x_pos +                             \
499                       (x_ini - ladder->x_pos) * cos(roll_value) - \
500                       (y_ini - ladder->y_pos) * sin(roll_value);
501           new_y_ini = ladder->y_pos +                             \
502                       (x_ini - ladder->x_pos) * sin(roll_value) + \
503                       (y_ini - ladder->y_pos) * cos(roll_value);
504           new_x_end = ladder->x_pos +                             \
505                       (x_end - ladder->x_pos) * cos(roll_value) - \
506                       (y_end - ladder->y_pos) * sin(roll_value);
507           new_y_end = ladder->y_pos +                             \
508                       (x_end - ladder->x_pos) * sin(roll_value) + \
509                       (y_end - ladder->y_pos) * cos(roll_value);
510
511           if( i >= 0 )
512             {
513             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
514             }
515           else
516             {
517             glEnable(GL_LINE_STIPPLE);
518             glLineStipple( 1, 0x00FF );
519             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
520             glDisable(GL_LINE_STIPPLE);
521             }
522           textString( new_x_ini -  8 * strlen(TextLadder) - 8,
523                       new_y_ini -  4,
524                       TextLadder, GLUT_BITMAP_8_BY_13 );
525           textString( new_x_end + 10,
526                       new_y_end -  4,
527                       TextLadder, GLUT_BITMAP_8_BY_13 );
528           }
529         else
530           {
531           if( i != 0 )  {
532             x_ini = ladder->x_pos - ladder->scr_width/2;
533             }
534           else          {
535             x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
536             }
537           y_ini = marker_y;
538           x_end = ladder->x_pos - ladder->scr_width/2 + ladder->scr_hole/2;
539           y_end = marker_y;
540           new_x_ini = ladder->x_pos+                             \
541                       (x_ini - ladder->x_pos) * cos(roll_value) -\
542                       (y_ini - ladder->y_pos) * sin(roll_value);
543           new_y_ini = ladder->y_pos+                             \
544                       (x_ini - ladder->x_pos) * sin(roll_value) +\
545                       (y_ini - ladder->y_pos) * cos(roll_value);
546           new_x_end = ladder->x_pos+                             \
547                       (x_end - ladder->x_pos) * cos(roll_value) -\
548                       (y_end - ladder->y_pos) * sin(roll_value);
549           new_y_end = ladder->y_pos+                             \
550                       (x_end - ladder->x_pos) * sin(roll_value) +\
551                       (y_end - ladder->y_pos) * cos(roll_value);
552
553           if( i >= 0 )
554             {
555             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
556             }
557           else
558             {
559             glEnable(GL_LINE_STIPPLE);
560             glLineStipple( 1, 0x00FF );
561             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
562             glDisable(GL_LINE_STIPPLE);
563             }
564           textString( new_x_ini - 8 * strlen(TextLadder) - 8,
565                       new_y_ini - 4,
566                       TextLadder, GLUT_BITMAP_8_BY_13 );
567
568           x_ini = ladder->x_pos + ladder->scr_width/2 - ladder->scr_hole/2;
569           y_ini = marker_y;
570           if( i != 0 )  {
571             x_end = ladder->x_pos + ladder->scr_width/2;
572             }
573           else          {
574             x_end = ladder->x_pos + ladder->scr_width/2 + 10;
575             }
576           y_end = marker_y;
577           new_x_ini = ladder->x_pos +                        \
578                       (x_ini-ladder->x_pos)*cos(roll_value) -\
579                       (y_ini-ladder->y_pos)*sin(roll_value);
580           new_y_ini = ladder->y_pos +                        \
581                       (x_ini-ladder->x_pos)*sin(roll_value) +\
582                       (y_ini-ladder->y_pos)*cos(roll_value);
583           new_x_end = ladder->x_pos +                        \
584                       (x_end-ladder->x_pos)*cos(roll_value) -\
585                                          (y_end-ladder->y_pos)*sin(roll_value);
586           new_y_end = ladder->y_pos +                        \
587                       (x_end-ladder->x_pos)*sin(roll_value) +\
588                       (y_end-ladder->y_pos)*cos(roll_value);
589
590           if( i >= 0 )
591             {
592             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
593             }
594           else
595             {
596             glEnable(GL_LINE_STIPPLE);
597             glLineStipple( 1, 0x00FF );
598             drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
599             glDisable(GL_LINE_STIPPLE);
600             }
601           textString( new_x_end+10, new_y_end-4,
602                       TextLadder, GLUT_BITMAP_8_BY_13 );
603           }
604         }
605             /* if( i%pscale->div_max==0 )
606             {
607                 drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
608                 sprintf( TextScale, "%d", i );
609                 if( pscale->orientation == LEFT )
610                 {
611                         textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
612                               TextScale, GLUT_BITMAP_8_BY_13 );
613                 }
614                 else if( pscale->orientation == RIGHT )
615                 {
616                         textString( marker_x+10, marker_y-4,
617                               TextScale, GLUT_BITMAP_8_BY_13 );
618                 }
619             } */
620         }
621     }
622
623 }
624
625 //
626 //      Draws an artificial horizon line in the center of the HUD
627 //      (with or without a center hole)
628 //
629 //      Needs: x_center, y_center, length, hole
630 //
631
632 static void drawhorizon( HUD_horizon *horizon )
633 {
634   int x_inc1, y_inc1;
635   int x_inc2, y_inc2;
636   int x_t_inc1, y_t_inc1;
637   
638   int d_bottom_x, d_bottom_y;
639   int d_right_x, d_right_y;
640   int d_top_x, d_top_y;
641   int d_left_x, d_left_y;
642   
643 //      struct fgFLIGHT *f = &current_aircraft.flight;
644   double sin_bank, cos_bank;
645   double bank_angle, sideslip_angle;
646   double sin_sideslip, cos_sideslip;
647   double ss_const; // sideslip angle pixels per rad
648
649   bank_angle = (*horizon->load_roll)();
650   sideslip_angle = (*horizon->load_sideslip)();
651
652         // sin_bank = sin( FG_2PI-FG_Phi );
653         // cos_bank = cos( FG_2PI-FG_Phi );
654   sin_bank = sin(FG_2PI-bank_angle);
655   cos_bank = cos(FG_2PI-bank_angle);
656   sin_sideslip = sin(sideslip_angle);
657   cos_sideslip = cos(sideslip_angle);
658   
659   x_inc1 = (int)(horizon->scr_width * cos_bank);
660   y_inc1 = (int)(horizon->scr_width * sin_bank);
661   x_inc2 = (int)(horizon->scr_hole  * cos_bank);
662   y_inc2 = (int)(horizon->scr_hole  * sin_bank);
663   
664   x_t_inc1 = (int)(horizon->tee_height * sin_bank);
665   y_t_inc1 = (int)(horizon->tee_height * cos_bank);
666   
667   d_bottom_x = horizon->x_pos;
668   d_bottom_y = horizon->y_pos-horizon->scr_hole;
669   d_right_x  = horizon->x_pos+horizon->scr_hole;
670   d_right_y  = horizon->y_pos;
671   d_top_x    = horizon->x_pos;
672   d_top_y    = horizon->y_pos+horizon->scr_hole;
673   d_left_x   = horizon->x_pos-horizon->scr_hole;
674   d_left_y   = horizon->y_pos;
675   
676   ss_const = (FG_PI_2/2)/(2*horizon->scr_width-2*horizon->scr_hole);
677
678   d_bottom_x += sideslip_angle*ss_const; // horizon->scr_width-horizon->scr_hole;
679   d_right_x  += sideslip_angle*ss_const; // horizon->scr_width-horizon->scr_hole;
680   d_left_x   += sideslip_angle*ss_const; // horizon->scr_width-horizon->scr_hole;
681   d_top_x    += sideslip_angle*ss_const; // horizon->scr_width-horizon->scr_hole;
682    
683   if( horizon->scr_hole == 0 )
684     {
685     drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
686                  horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
687     }
688   else
689     {
690     drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
691                  horizon->x_pos - x_inc2, horizon->y_pos - y_inc2 );
692     drawOneLine( horizon->x_pos + x_inc2, horizon->y_pos + y_inc2, \
693                  horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
694     }
695     
696   // draw teemarks (?) 
697   drawOneLine( horizon->x_pos + x_inc2, horizon->y_pos + y_inc2, \
698                horizon->x_pos + x_inc2 + x_t_inc1, horizon->y_pos + y_inc2 - y_t_inc1 );
699   drawOneLine( horizon->x_pos - x_inc2, horizon->y_pos - y_inc2, \
700                horizon->x_pos - x_inc2 + x_t_inc1, horizon->y_pos - y_inc2 - y_t_inc1 );
701                
702   // draw sideslip diamond (it is not yet positioned correctly )
703   drawOneLine( d_bottom_x, d_bottom_y, d_right_x, d_right_y )
704   drawOneLine( d_right_x, d_right_y, d_top_x, d_top_y );
705   drawOneLine( d_top_x, d_top_y, d_left_x, d_left_y );
706   drawOneLine( d_left_x, d_left_y, d_bottom_x, d_bottom_y );
707 }
708
709 //  drawControlSurfaces()
710 //      Draws a representation of the control surfaces in their current state
711 //      anywhere in the HUD
712 //
713
714 static void drawControlSurfaces( HUD_control_surfaces *ctrl_surf )
715 {
716         int x_ini, y_ini;
717         int x_end, y_end;
718         /* int x_1, y_1; */
719         /* int x_2, y_2; */
720         fgCONTROLS *pCtls;
721
722         x_ini = ctrl_surf->x_pos;
723         y_ini = ctrl_surf->y_pos;
724         x_end = x_ini + 150;
725         y_end = y_ini + 60;
726
727         drawOneLine( x_ini, y_ini, x_end, y_ini );
728         drawOneLine( x_ini, y_ini, x_ini, y_end );
729         drawOneLine( x_ini, y_end, x_end, y_end );
730         drawOneLine( x_end, y_end, x_end, y_ini );
731         drawOneLine( x_ini + 30, y_ini, x_ini + 30, y_end );
732         drawOneLine( x_ini + 30, y_ini + 30, x_ini + 90, y_ini + 30 );
733         drawOneLine( x_ini + 90, y_ini, x_ini + 90, y_end );
734         drawOneLine( x_ini + 120, y_ini, x_ini + 120, y_end );
735
736         pCtls = current_aircraft.controls;
737
738         /* Draw elevator diagram */
739         textString( x_ini + 1, y_end-11, "E", GLUT_BITMAP_8_BY_13 );
740         drawOneLine( x_ini + 15, y_ini + 5, x_ini + 15, y_ini + 55 );
741         drawOneLine( x_ini + 14, y_ini + 30, x_ini + 16, y_ini + 30 );
742         if( pCtls->elevator <= -0.01 || pCtls->elevator >= 0.01 )
743         {
744                 drawOneLine( x_ini + 10, y_ini + 5 + (int)(((pCtls->elevator + 1.0)/2)*50.0), \
745                                 x_ini + 20, y_ini + 5 + (int)(((pCtls->elevator + 1.0)/2)*50.0) );
746         }
747         else
748         {
749                 drawOneLine( x_ini + 7, y_ini + 5 + (int)(((pCtls->elevator + 1.0)/2)*50.0), \
750                                 x_ini + 23, y_ini + 5 + (int)(((pCtls->elevator + 1.0)/2)*50.0) );
751         }
752
753         /* Draw aileron diagram */
754         textString( x_ini + 30 + 1, y_end-11, "A", GLUT_BITMAP_8_BY_13 );
755         drawOneLine( x_ini + 35, y_end-15, x_ini + 85, y_end-15 );
756         drawOneLine( x_ini + 60, y_end-14, x_ini + 60, y_end-16 );
757         if( pCtls->aileron <= -0.01 || pCtls->aileron >= 0.01 )
758         {
759                 drawOneLine( x_ini + 35 + (int)(((pCtls->aileron + 1.0)/2)*50.0), y_end-20, \
760                                 x_ini + 35 + (int)(((pCtls->aileron + 1.0)/2)*50.0), y_end-10 );
761         }
762         else
763         {
764                 drawOneLine( x_ini + 35 + (int)(((pCtls->aileron + 1.0) / 2) * 50.0),
765                  y_end - 25,
766                  x_ini + 35 + (int)(((pCtls->aileron + 1.0) / 2) * 50.0),
767                  y_end -  5 );
768         }
769
770         /* Draw rudder diagram */
771         textString ( x_ini + 30 + 1, y_ini + 21, "R", GLUT_BITMAP_8_BY_13 );
772         drawOneLine( x_ini + 35, y_ini + 15, x_ini + 85, y_ini + 15 );
773         drawOneLine( x_ini + 60, y_ini + 14, x_ini + 60, y_ini + 16 );
774
775         if( pCtls->rudder <= -0.01 || pCtls->rudder >= 0.01 )
776         {
777                 drawOneLine( x_ini + 35 + (int)(((pCtls->rudder + 1.0) / 2) * 50.0),
778                  y_ini + 20,
779                                          x_ini + 35 + (int)(((pCtls->rudder + 1.0) / 2) * 50.0),
780                  y_ini + 10 );
781         }
782         else
783         {
784                 drawOneLine( x_ini + 35 + (int)(((pCtls->rudder + 1.0) / 2) * 50.0),
785                  y_ini + 25,
786                  x_ini + 35 + (int)(((pCtls->rudder + 1.0) / 2) * 50.0),
787                  y_ini +  5 );
788         }
789
790
791         /* Draw throttle diagram */
792         textString( x_ini + 90 + 1, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
793         textString( x_ini + 90 + 1, y_end-21, "r", GLUT_BITMAP_8_BY_13 );
794         drawOneLine( x_ini + 105, y_ini + 5, x_ini + 105, y_ini + 55 );
795         drawOneLine( x_ini + 100, y_ini + 5 + (int)(pCtls->throttle[0]*50.0), \
796                         x_ini + 110, y_ini + 5 + (int)(pCtls->throttle[0]*50.0) );
797
798
799         /* Draw elevator trim diagram */
800         textString( x_ini + 121, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
801         textString( x_ini + 121, y_end-22, "m", GLUT_BITMAP_8_BY_13 );
802         drawOneLine( x_ini + 135, y_ini + 5, x_ini + 135, y_ini + 55 );
803         drawOneLine( x_ini + 134, y_ini + 30, x_ini + 136, y_ini + 30 );
804         if( pCtls->elevator_trim <= -0.01 || pCtls->elevator_trim >= 0.01 )
805         {
806                 drawOneLine( x_ini + 130, y_ini + 5 + (int)(((pCtls->elevator_trim + 1)/2)*50.0), \
807                                 x_ini + 140, y_ini + 5 + (int)(((pCtls->elevator_trim + 1.0)/2)*50.0) );
808         }
809         else
810         {
811                 drawOneLine( x_ini + 127, y_ini + 5 + (int)(((pCtls->elevator_trim + 1.0)/2)*50.0), \
812                                 x_ini + 143, y_ini + 5 + (int)(((pCtls->elevator_trim + 1.0)/2)*50.0) );
813         }
814
815 }
816
817 //
818 // Draws a label anywhere in the HUD
819 //
820 //
821
822 static void drawlabel( HUD_label *label )
823 {
824   char buffer[80];
825   char string[80];
826   int posincr;
827   int lenstr;
828
829   if( !label ) { // Eliminate the possible, but absurd case.
830     return;
831     }
832
833   if( label->pre_str != NULL) {
834     if( label->post_str != NULL ) {
835       sprintf( buffer, "%s%s%s", label->pre_str,  \
836                                  label->format,   \
837                                  label->post_str );
838       }
839     else {
840       sprintf( buffer, "%s%s",   label->pre_str, \
841                                  label->format );
842       }
843     }
844   else {
845     if( label->post_str != NULL ) {
846       sprintf( buffer, "%s%s",   label->format,  \
847                                  label->post_str );
848       }
849     } // else do nothing if both pre and post strings are nulls. Interesting.
850
851
852   sprintf( string, buffer, (*label->load_value)() );
853 #ifdef DEBUGHUD
854         fgPrintf( FG_COCKPIT, FG_DEBUG,  buffer );
855         fgPrintf( FG_COCKPIT, FG_DEBUG,  "\n" );
856         fgPrintf( FG_COCKPIT, FG_DEBUG, string );
857         fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
858 #endif
859   lenstr = strlen( string );
860   if( label->justify == LEFT_JUST ) {
861    posincr = -lenstr*8;
862    }
863   else {
864     if( label->justify == CENTER_JUST ) {
865       posincr = -lenstr*4;
866       }
867     else {
868       if( label->justify == RIGHT_JUST ) {
869         posincr = 0;
870         }
871       }
872     }
873
874   if( label->size == SMALL ) {
875     textString( label->x_pos + posincr, label->y_pos,
876                 string, GLUT_BITMAP_8_BY_13);
877     }
878   else  {
879     if( label->size == LARGE ) {
880       textString( label->x_pos + posincr, label->y_pos,
881                   string, GLUT_BITMAP_9_BY_15);
882       }
883     }
884 }
885 // The following routines concern HUD object/component object construction
886 //
887
888 // fgHUDInit
889 //
890 // Constructs a HUD object and then adds in instruments. At the present
891 // the instruments are hard coded into the routine. Ultimately these need
892 // to be defined by the aircraft's instrumentation records so that the
893 // display for a Piper Cub doesn't show the speed range of a North American
894 // mustange and the engine readouts of a B36!
895 //
896 Hptr fgHUDInit( fgAIRCRAFT *current_aircraft )
897 {
898   Hptr hud;
899
900   fgPrintf( FG_COCKPIT, FG_INFO, "Initializing HUD\n" );
901
902   hud = (Hptr)calloc(sizeof( HUD),1);
903   if( hud == NULL )
904     return( NULL );
905
906   hud->code = 1;
907   hud->status = 0;
908
909   // For now lets just hardcode the hud here.
910   // In the future, hud information has to come from the same place
911   // aircraft information came from.
912   
913   fgHUDSetTimeMode( hud, NIGHT );
914   fgHUDSetBrightness( hud, BRT_LIGHT ); 
915
916   // Small, original HUD configuration
917   // fgHUDAddHorizon( hud, 590, 50, 40, 5, 10, get_roll, get_sideslip );
918   // fgHUDAddLadder ( hud, 330, 190, 90, 180, 70, 10,
919   //                  NONE, 45, get_roll, get_pitch );
920   // fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 220, 100, 280, 5, 10,
921   //                     LEFT,    0, 100, 50, get_speed );
922   // fgHUDAddScale  ( hud, VERTICAL,   NOLIMIT, 440, 100, 280, 1,  5, RIGHT,
923   //                     -40, 50, 25, get_aoa );
924   // fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 280, 220, 440, 5, 10,
925   //                     TOP,     0,  50, 50, get_heading );
926   // fgHUDAddLabel  ( hud, 180, 85, SMALL, NOBLINK,
927   //                  RIGHT_JUST, NULL, " Kts", "%5.0f", get_speed );
928   // fgHUDAddLabel  ( hud, 180, 73, SMALL, NOBLINK,
929   //                  RIGHT_JUST, NULL, " m", "%5.0f", get_altitude );
930   // fgHUDAddControlSurfaces( hud, 10, 10, NULL );
931   
932   // Bigger and placed a bit higher HUD configuration
933   fgHUDAddHorizon( hud, 590, 50, 40, 5, 10, get_roll, get_sideslip );
934   fgHUDAddLadder ( hud, 330, 270, 120, 180, 70, 10,
935                    NONE, 45, get_roll, get_pitch );
936   fgHUDAddScale  ( hud, VERTICAL,     LIMIT, 200, 180, 380, 5, 10,
937                       LEFT,    0, 100, 50, get_speed );
938   fgHUDAddScale  ( hud, VERTICAL,   NOLIMIT, 460, 180, 380, 1,  5,
939                       RIGHT, -40,  50, 25, get_aoa );
940   fgHUDAddScale  ( hud, HORIZONTAL, NOLIMIT, 380, 200, 460, 5, 10,
941                       TOP,     0,  50, 50, get_heading );
942   fgHUDAddLabel  ( hud, 160, 165, SMALL, NOBLINK,
943                    RIGHT_JUST, NULL, " Kts", "%5.0f", get_speed );
944   fgHUDAddLabel  ( hud, 160, 153, SMALL, NOBLINK,
945                    RIGHT_JUST, NULL, " m", "%5.0f", get_altitude );
946   fgHUDAddControlSurfaces( hud, 10, 10, NULL );
947
948 //  fgHUDAddControl( hud, HORIZONTAL, 50,  25, get_aileronval  ); // was 10, 10
949 //  fgHUDAddControl( hud, VERTICAL,   150, 25, get_elevatorval ); // was 10, 10
950 //  fgHUDAddControl( hud, HORIZONTAL, 250, 25, get_rudderval   ); // was 10, 10
951
952   return( hud );
953 }
954
955 // add_instrument
956 //
957 // This is a stand in for linked list code that will get replaced later
958 // by some more elegant list handling code.
959
960 void add_instrument( Hptr hud, HIptr pinstrument )
961 {
962     if( !hud || !pinstrument ) {
963         return;
964     }
965
966     pinstrument->next = hud->instruments;
967     hud->instruments = pinstrument;
968 }
969
970
971 // fgHUDAddHorizon
972 //
973 // Constructs a HUD_horizon "object" and installs it into the hud instrument
974 // list.
975
976 Hptr fgHUDAddHorizon( Hptr hud,      \
977                       int x_pos,     \
978                       int y_pos,     \
979                       int length,    \
980                       int hole_len,  \
981                       int tee_height,\
982                       double (*load_roll)(),\
983                       double (*load_sideslip)() )
984 {
985     HUD_horizon *phorizon;
986     HUD_instr   *pinstrument;
987
988     if( !hud ) {
989         return NULL;
990     }
991                                        // construct the parent object
992     pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
993     if( pinstrument == NULL ) {
994         return( NULL );
995     }
996     pinstrument->type    = HUDhorizon;  //  ARTIFICIAL_HORIZON;
997
998                                       // Construct the horizon
999     phorizon = (HUD_horizon *) calloc( sizeof(HUD_horizon),1);
1000     if( phorizon == NULL )   {
1001         return( NULL );
1002     }
1003
1004     phorizon->x_pos         = x_pos;
1005     phorizon->y_pos         = y_pos;
1006     phorizon->scr_width     = length;
1007     phorizon->scr_hole      = hole_len;
1008     phorizon->tee_height    = tee_height;
1009     phorizon->load_roll     = load_roll;
1010     phorizon->load_sideslip = load_sideslip;
1011     //  Install the horizon in the parent.
1012     pinstrument->instr      = phorizon;
1013     //  Install the instrument into hud.
1014     add_instrument( hud, pinstrument);
1015
1016     return( hud );
1017 }
1018
1019 // fgHUDAddScale
1020 //
1021 // Constructs a HUD_scale "object" and installs it into the hud instrument
1022 // list.
1023
1024 Hptr fgHUDAddScale( Hptr hud,        \
1025                     int type,        \
1026                     int sub_type,    \
1027                     int scr_pos,     \
1028                     int scr_min,     \
1029                     int scr_max,     \
1030                     int div_min,     \
1031                     int div_max,     \
1032                     int orientation, \
1033                     int min_value,   \
1034                     int max_value,   \
1035                     int width_units, \
1036                     double (*load_value)() )
1037 {
1038   HUD_scale *pscale;
1039   HUD_instr *pinstrument;
1040
1041   if( !hud ) {
1042     return NULL;
1043     }
1044
1045         pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1046         if( pinstrument == NULL ) {
1047      return( NULL );
1048      }
1049
1050   pinstrument->type = HUDscale;
1051
1052   pscale = ( HUD_scale *)calloc(sizeof(HUD_scale),1);
1053   if( pscale == NULL )   {
1054      return( NULL );
1055     }
1056   pscale->type          = type;
1057   pscale->sub_type      = sub_type;
1058   pscale->scr_pos       = scr_pos;
1059   pscale->scr_min       = scr_min;
1060   pscale->scr_max       = scr_max;
1061   pscale->div_min       = div_min;
1062   pscale->div_max       = div_max;
1063   pscale->orientation   = orientation;
1064   pscale->minimum_value = min_value;
1065   pscale->maximum_value = max_value;
1066   pscale->width_units   = width_units;
1067   pscale->load_value    = load_value;
1068                                      // Install the scale
1069   pinstrument->instr = pscale;
1070                                       //  Install the instrument into hud.
1071   add_instrument( hud, pinstrument);
1072
1073   return( hud );
1074 }
1075
1076 // fgHUDAddLabel
1077 //
1078 // Constructs a HUD_Label object and installs it into the hud instrument
1079 // list.
1080 Hptr fgHUDAddLabel( Hptr hud,       \
1081                     int x_pos,      \
1082                     int y_pos,      \
1083                     int size,       \
1084                     int blink,      \
1085                     int justify,    \
1086                                                   char *pre_str,  \
1087                     char *post_str, \
1088                     char *format,   \
1089                     double (*load_value)() )
1090 {
1091         HUD_label *plabel;
1092         HUD_instr *pinstrument;
1093
1094   if( !hud ) {
1095     return NULL;
1096     }
1097
1098         pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1099         if( pinstrument == NULL ) {
1100     return NULL;
1101     }
1102         pinstrument->type = HUDlabel;
1103
1104         plabel = (HUD_label *)calloc(sizeof(HUD_label),1);
1105         if( plabel == NULL ){
1106     return NULL;
1107     }
1108
1109   plabel->x_pos      = x_pos;
1110   plabel->y_pos      = y_pos;
1111   plabel->size       = size;
1112   plabel->blink      = blink;
1113   plabel->justify    = justify;
1114   plabel->pre_str    = pre_str;
1115   plabel->post_str   = post_str;
1116   plabel->format     = format;
1117   plabel->load_value = load_value;
1118                                       // Install the label
1119         pinstrument->instr = plabel;
1120                                       //  Install the instrument into hud.
1121   add_instrument( hud, pinstrument);
1122
1123         return( hud );
1124 }
1125
1126 // fgHUDAddLadder
1127 //
1128 // Contains code that constructs a ladder "object" and installs it as
1129 // a hud instrument in the hud instrument list.
1130 //
1131 Hptr fgHUDAddLadder( Hptr hud,        \
1132                      int x_pos,       \
1133                      int y_pos,       \
1134                      int scr_width,   \
1135                      int scr_height,  \
1136                                                    int hole_len,    \
1137                      int div_units,   \
1138                      int label_pos,   \
1139                      int width_units, \
1140                                                    double (*load_roll)(),
1141                      double (*load_pitch)() )
1142 {
1143         HUD_ladder *pladder;
1144         HUD_instr  *pinstrument;
1145
1146   if( !hud ) {
1147     return NULL;
1148     }
1149
1150         pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1151         if( pinstrument == NULL )
1152                 return( NULL );
1153
1154         pinstrument->type = HUDladder;
1155
1156         pladder = (HUD_ladder *)calloc(sizeof(HUD_ladder),1);
1157         if( pladder == NULL )
1158                 return( NULL );
1159
1160   pladder->type           = 0; // Not used.
1161   pladder->x_pos          = x_pos;
1162   pladder->y_pos          = y_pos;
1163   pladder->scr_width      = scr_width;
1164   pladder->scr_height     = scr_height;
1165   pladder->scr_hole       = hole_len;
1166   pladder->div_units      = div_units;
1167   pladder->label_position = label_pos;
1168   pladder->width_units    = width_units;
1169   pladder->load_roll      = load_roll;
1170   pladder->load_pitch     = load_pitch;
1171
1172   pinstrument->instr      = pladder;
1173                                       //  Install the instrument into hud.
1174   add_instrument( hud, pinstrument);
1175         return hud;
1176 }
1177
1178 //   fgHUDAddControlSurfaces()
1179 //
1180 //   Adds the control surface indicators which make up for the lack of seat
1181 //   of the pants feel. Should be unnecessary with joystick and pedals
1182 //   enabled. But that is another improvement. Also, what of flaps? Spoilers?
1183 //   This may need to be expanded or flattened into multiple indicators,
1184 //   vertical and horizontal.
1185
1186 Hptr fgHUDAddControlSurfaces( Hptr hud,
1187                               int x_pos,
1188                               int y_pos,
1189                               double (*load_value)() )
1190 {
1191         HUD_control_surfaces *pcontrol_surfaces;
1192         HUD_instr *pinstrument;
1193
1194     if( !hud ) {
1195       return NULL;
1196     }
1197
1198     // Construct shell
1199     pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1200     if( !pinstrument ) {
1201       return NULL;
1202       }
1203     pinstrument->type = HUDcontrol_surfaces;
1204
1205     // Construct core
1206     pcontrol_surfaces = (HUD_control_surfaces *)calloc(sizeof(HUD_control),1);
1207     if( !pcontrol_surfaces ) {
1208       return( NULL );
1209       }
1210
1211     pcontrol_surfaces->x_pos = x_pos;
1212     pcontrol_surfaces->y_pos = y_pos;
1213     pcontrol_surfaces->load_value = load_value;
1214
1215     pinstrument->instr     = pcontrol_surfaces;
1216                                                    // Install
1217     add_instrument( hud, pinstrument);
1218
1219     return hud;
1220 }
1221
1222 // fgHUDAddControl
1223 //
1224 //
1225
1226 Hptr fgHUDAddControl( Hptr hud,        \
1227                       int ctrl_x,      \
1228                       int ctrl_y,      \
1229                       int ctrl_length, \
1230                       int orientation, \
1231                       int alignment,   \
1232                       int min_value,   \
1233                       int max_value,   \
1234                       int width_units, \
1235                       double (*load_value)() )
1236 {
1237     HUD_control *pcontrol;
1238     HUD_instr *pinstrument;
1239
1240     if( !hud ) {
1241       return NULL;
1242     }
1243
1244     // Construct shell
1245     pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1246     if( !pinstrument ) {
1247       return NULL;
1248       }
1249     pinstrument->type = HUDcontrol;
1250
1251     // Construct core
1252     pcontrol = (HUD_control *)calloc(sizeof(HUD_control),1);
1253     if( !(pcontrol == NULL) ) {
1254       return( NULL );
1255       }
1256     pcontrol->ctrl_x        = ctrl_x;
1257     pcontrol->ctrl_y        = ctrl_y;
1258     pcontrol->ctrl_length   = ctrl_length;
1259     pcontrol->orientation   = orientation;
1260     pcontrol->alignment     = alignment;
1261     pcontrol->min_value     = min_value;
1262     pcontrol->max_value     = max_value;
1263     pcontrol->width_units   = width_units;
1264     pcontrol->load_value    = load_value;
1265                                                    // Integrate
1266     pinstrument->instr     = pcontrol;
1267                                                    // Install
1268     add_instrument( hud, pinstrument);
1269
1270     return hud;
1271 }
1272
1273 /*
1274 Hptr fgHUDAddMovingHorizon(  Hptr hud,     \
1275                              int x_pos,    \
1276                              int y_pos,    \
1277                              int length,   \
1278                              int hole_len, \
1279                              int color )
1280 {
1281
1282 }
1283
1284 Hptr fgHUDAddCircularLadder( Hptr hud,    \
1285                              int scr_min, \
1286                              int scr_max, \
1287                              int div_min, \
1288                              int div_max, \
1289                              int max_value )
1290 {
1291
1292 }
1293
1294 Hptr fgHUDAddNumDisp( Hptr hud,           \
1295                       int x_pos,          \
1296                       int y_pos,          \
1297                       int size,           \
1298                       int color,          \
1299                       int blink,          \
1300                                                           char *pre_str,      \
1301                       char *post_str )
1302 {
1303
1304 }
1305 */
1306
1307 // fgUpdateHUD
1308 //
1309 // Performs a once around the list of calls to instruments installed in
1310 // the HUD object with requests for redraw. Kinda. It will when this is
1311 // all C++.
1312 //
1313
1314 void fgUpdateHUD( Hptr hud ) {
1315     HIptr phud_instr;
1316
1317     glMatrixMode(GL_PROJECTION);
1318     glPushMatrix();
1319
1320     glLoadIdentity();
1321     gluOrtho2D(0, 640, 0, 480);
1322     glMatrixMode(GL_MODELVIEW);
1323     glPushMatrix();
1324     glLoadIdentity();
1325
1326     glColor3f(1.0, 1.0, 1.0);
1327     glIndexi(7);
1328
1329     glDisable(GL_DEPTH_TEST);
1330     glDisable(GL_LIGHTING);
1331
1332     glLineWidth(1);
1333     
1334     if( hud->time_of_day==DAY) {
1335       switch (hud->brightness) {
1336          case BRT_LIGHT:
1337            glColor3f (0.1, 0.9, 0.1);
1338            break;
1339          case BRT_MEDIUM:
1340            glColor3f (0.1, 0.7, 0.0);
1341            break;
1342          case BRT_DARK:
1343            glColor3f (0.0, 0.5, 0.0);
1344          }
1345       }
1346     else if( hud->time_of_day==NIGHT) {
1347       switch (hud->brightness) {
1348          case BRT_LIGHT:
1349            glColor3f (0.9, 0.1, 0.1);
1350            break;
1351          case BRT_MEDIUM:
1352            glColor3f (0.7, 0.0, 0.1);
1353            break;
1354          case BRT_DARK:
1355            glColor3f (0.5, 0.0, 0.0);
1356          }
1357       }
1358
1359     fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d  Status %d\n",
1360               hud->code, hud->status );
1361
1362     phud_instr = hud->instruments;
1363     while( phud_instr ) {
1364         /* printf("Drawing Instrument %d\n", phud_instr->type); */
1365
1366         switch (phud_instr->type) {
1367     case HUDhorizon:   // ARTIFICIAL HORIZON
1368             drawhorizon( (pHUDhorizon)phud_instr->instr );
1369             break;
1370
1371     case HUDscale:     // Need to simplify this call.
1372             drawscale (  (pHUDscale)  phud_instr->instr  );
1373             break;
1374
1375     case HUDlabel:
1376             drawlabel (  (pHUDlabel)  phud_instr->instr  );
1377             break;
1378
1379     case HUDladder:
1380             drawladder(  (pHUDladder) phud_instr->instr  );
1381             break;
1382
1383 //    case HUDcontrol:
1384 //      drawControl( (pHUDcontrol) phud_instr->instr );
1385 //      break;
1386
1387     case HUDcontrol_surfaces:
1388             drawControlSurfaces( (pHUDControlSurfaces) phud_instr->instr );
1389             break;
1390
1391     default:; // Ignore anything you don't know about.
1392     }
1393
1394   phud_instr = phud_instr->next;
1395   }
1396
1397   glEnable(GL_DEPTH_TEST);
1398   glEnable(GL_LIGHTING);
1399   glMatrixMode(GL_PROJECTION);
1400   glPopMatrix();
1401   glMatrixMode(GL_MODELVIEW);
1402   glPopMatrix();
1403 }
1404
1405 void fgHUDSetTimeMode( Hptr hud, int time_of_day )
1406 {
1407
1408   hud->time_of_day = time_of_day;
1409
1410 }
1411
1412 void fgHUDSetBrightness( Hptr hud, int brightness )
1413 {
1414
1415   hud->brightness = brightness;
1416
1417 }
1418
1419 /* $Log$
1420 /* Revision 1.17  1998/02/20 00:16:21  curt
1421 /* Thursday's tweaks.
1422 /*
1423  * Revision 1.16  1998/02/19 13:05:49  curt
1424  * Incorporated some HUD tweaks from Michelle America.
1425  * Tweaked the sky's sunset/rise colors.
1426  * Other misc. tweaks.
1427  *
1428  * Revision 1.15  1998/02/16 13:38:39  curt
1429  * Integrated changes from Charlie Hotchkiss.
1430  *
1431  * Revision 1.14  1998/02/12 21:59:41  curt
1432  * Incorporated code changes contributed by Charlie Hotchkiss
1433  * <chotchkiss@namg.us.anritsu.com>
1434  *
1435  * Revision 1.12  1998/02/09 15:07:48  curt
1436  * Minor tweaks.
1437  *
1438  * Revision 1.11  1998/02/07 15:29:34  curt
1439  * Incorporated HUD changes and struct/typedef changes from Charlie Hotchkiss
1440  * <chotchkiss@namg.us.anritsu.com>
1441  *
1442  * Revision 1.10  1998/02/03 23:20:14  curt
1443  * Lots of little tweaks to fix various consistency problems discovered by
1444  * Solaris' CC.  Fixed a bug in fg_debug.c with how the fgPrintf() wrapper
1445  * passed arguments along to the real printf().  Also incorporated HUD changes
1446  * by Michele America.
1447  *
1448  * Revision 1.9  1998/01/31 00:43:04  curt
1449  * Added MetroWorks patches from Carmen Volpe.
1450  *
1451  * Revision 1.8  1998/01/27 00:47:51  curt
1452  * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
1453  * system and commandline/config file processing code.
1454  *
1455  * Revision 1.7  1998/01/19 18:40:20  curt
1456  * Tons of little changes to clean up the code and to remove fatal errors
1457  * when building with the c++ compiler.
1458  *
1459  * Revision 1.6  1997/12/15 23:54:34  curt
1460  * Add xgl wrappers for debugging.
1461  * Generate terrain normals on the fly.
1462  *
1463  * Revision 1.5  1997/12/10 22:37:39  curt
1464  * Prepended "fg" on the name of all global structures that didn't have it yet.
1465  * i.e. "struct WEATHER {}" became "struct fgWEATHER {}"
1466  *
1467  * Revision 1.4  1997/09/23 00:29:32  curt
1468  * Tweaks to get things to compile with gcc-win32.
1469  *
1470  * Revision 1.3  1997/09/05 14:17:26  curt
1471  * More tweaking with stars.
1472  *
1473  * Revision 1.2  1997/09/04 02:17:30  curt
1474  * Shufflin' stuff.
1475  *
1476  * Revision 1.1  1997/08/29 18:03:22  curt
1477  * Initial revision.
1478  *
1479  */