]> git.mxchange.org Git - flightgear.git/blob - Cockpit/hud.c
Added MetroWorks patches from Carmen Volpe.
[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 #include <GL/glut.h>
28 #include <stdlib.h>
29 #ifndef WIN32
30 #  include <values.h>  /* for MAXINT */
31 #endif /* not WIN32 */
32 #include "hud.h"
33
34 #include <Include/fg_constants.h>
35
36 #include <Aircraft/aircraft.h>
37 /* #include <Scenery/mesh.h> */
38 #include <Scenery/scenery.h>
39 #include <Math/mat3.h>
40 #include <Math/polar.h>
41 #include <Time/fg_timer.h>
42 #include <Math/fg_random.h>
43 #include <Weather/weather.h>
44
45 // #define DEBUG
46
47 #define drawOneLine(x1,y1,x2,y2)  glBegin(GL_LINES);  \
48    glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
49    
50 /* textString - Bitmap font string */
51
52 static void textString(int x, int y, char *msg, void *font)
53 {
54         glRasterPos2f(x, y);
55         while (*msg) {
56                 glutBitmapCharacter(font, *msg);
57                 msg++;
58     }
59 }
60
61 /* strokeString - Stroke font string */
62 /* static void strokeString(int x, int y, char *msg, void *font) */
63 /* { */
64 /*      glPushMatrix(); */
65 /*      glTranslatef(x, y, 0); */
66 /*      glScalef(.04, .04, .04); */
67 /*      while (*msg) { */
68 /*              glutStrokeCharacter(font, *msg); */
69 /*              msg++; */
70 /*      } */
71 /*      glPopMatrix(); */
72 /* } */
73
74 /*
75
76         Draws a measuring scale anywhere on the HUD
77                 
78         
79         Needs: HUD_scale struct
80
81 */
82 static void drawscale( int type, int sub_type, int min_value, int orientation, int scr_pos, \
83                 int scr_min, int scr_max, double total_amount, int min_div, int max_div, \
84                 double cur_value )
85 {
86     double vmin, vmax;
87     int marker_x, marker_y;
88     int mid_scr;
89     // int scale_min, scale_max;
90     register i;
91     double factor;
92     char TextScale[80];
93     int condition;
94
95     vmin = cur_value-total_amount/2;
96     vmax = cur_value+total_amount/2;
97     
98     mid_scr = scr_min+(scr_max-scr_min)/2;
99     
100     if( type == VERTICAL )     // Vertical scale
101     {
102         if( orientation == LEFT )
103             marker_x = scr_pos-6;
104         else if( orientation == RIGHT )
105             marker_x = scr_pos;
106         drawOneLine( scr_pos, scr_min, scr_pos, scr_max );
107         if( orientation == LEFT )
108         {
109             drawOneLine( scr_pos-3, scr_min, scr_pos, scr_min );
110             drawOneLine( scr_pos-3, scr_max, scr_pos, scr_max );
111             drawOneLine( scr_pos, mid_scr, scr_pos+6, mid_scr );
112         } else if( orientation == RIGHT )
113         {
114             drawOneLine( scr_pos, scr_min, scr_pos+3, scr_min );
115             drawOneLine( scr_pos, scr_max, scr_pos+3, scr_max );
116             drawOneLine( scr_pos, mid_scr, scr_pos-6, mid_scr );
117         }
118
119         factor = (scr_max-scr_min)/total_amount;
120
121         for( i=vmin; i<=vmax; i+=1 )
122         {
123                 if( sub_type == LIMIT )
124                         condition = i>= min_value;
125                 else if( sub_type == NOLIMIT )
126                         condition = 1;
127                         
128             if( condition )
129             {
130                 marker_y = scr_min+(i-vmin)*factor;
131                 if( i%min_div==0 )
132                     if( orientation == LEFT )
133                     {
134                         drawOneLine( marker_x+3, marker_y, marker_x+6, marker_y );
135                     }
136                     else if( orientation == RIGHT )
137                     {
138                         drawOneLine( marker_x, marker_y, marker_x+3, marker_y );
139                     }
140                 if( i%max_div==0 )
141                 {
142                         drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
143                     sprintf( TextScale, "%d", i );
144                     if( orientation == LEFT )
145                     {
146                         textString( marker_x-8*strlen(TextScale)-2, marker_y-4, TextScale, GLUT_BITMAP_8_BY_13 );
147                     }
148                     else if( orientation == RIGHT )
149                     {
150                         textString( marker_x+10, marker_y-4, TextScale, GLUT_BITMAP_8_BY_13 );
151                     }
152                 }
153             }
154         }
155     }
156     if( type == HORIZONTAL )     // Horizontal scale
157     {
158         if( orientation == TOP )
159             marker_y = scr_pos;
160         else if( orientation == BOTTOM )
161             marker_y = scr_pos-6;
162         drawOneLine( scr_min, scr_pos, scr_max, scr_pos );
163         if( orientation == TOP )
164         {
165                 drawOneLine( scr_min, scr_pos, scr_min, scr_pos-3 );
166             drawOneLine( scr_max, scr_pos, scr_max, scr_pos-3 );
167             drawOneLine( mid_scr, scr_pos, mid_scr, scr_pos-6 );
168         } else if( orientation == BOTTOM )
169         {
170                 drawOneLine( scr_min, scr_pos, scr_min, scr_pos+3 );
171             drawOneLine( scr_max, scr_pos, scr_max, scr_pos+3 );
172             drawOneLine( mid_scr, scr_pos, mid_scr, scr_pos+6 );
173         }
174
175         factor = (scr_max-scr_min)/total_amount;
176
177         for( i=vmin; i<=vmax; i+=1 )
178         {
179                 if( sub_type == LIMIT )
180                         condition = i>= min_value;
181                 else if( sub_type == NOLIMIT )
182                         condition = 1;
183                         
184             if( condition )
185             {
186                 marker_x = scr_min+(i-vmin)*factor;
187                 if( i%min_div==0 )
188                     if( orientation == TOP )
189                     {
190                         drawOneLine( marker_x, marker_y, marker_x, marker_y+3 );
191                         }
192                     else if( orientation == BOTTOM )
193                     {
194                         drawOneLine( marker_x, marker_y+3, marker_x, marker_y+6 );
195                     }
196                 if( i%max_div==0 )
197                 {
198                     sprintf( TextScale, "%d", i );
199                     if( orientation == TOP )
200                     {
201                         drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
202                         textString( marker_x-4*strlen(TextScale), marker_y+14, TextScale, GLUT_BITMAP_8_BY_13 );
203                     }
204                     else if( orientation == BOTTOM )
205                     {
206                         drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
207                         textString( marker_x+10, marker_y-4, TextScale, GLUT_BITMAP_8_BY_13 );
208                     }
209                 }
210             }
211         }
212     }
213
214 }              
215
216 /*
217
218         Draws a climb ladder in the center of the HUD
219                 
220         
221         Needs: HUD_ladder struct
222
223 */
224 static void drawladder( struct HUD_ladder ladder )
225 {
226     double vmin, vmax;
227     double roll_value, pitch_value;
228     /* double cos_roll, sin_roll; */
229     int marker_x, marker_y;
230     int mid_scr;
231     int scr_min, scr_max;
232     int x_ini, x_end;
233     int y_ini, y_end;
234     int new_x_ini, new_x_end;
235     int new_y_ini, new_y_end;
236     register i;
237     double factor;
238     char TextLadder[80];
239     int condition;
240
241         roll_value = (*ladder.load_roll)();
242         pitch_value = (*ladder.load_pitch)()*RAD_TO_DEG;
243         
244     vmin = pitch_value-ladder.width_units/2;
245     vmax = pitch_value+ladder.width_units/2;
246     
247     scr_min = ladder.y_pos-(ladder.scr_height/2);
248     scr_max = scr_min+ladder.scr_height;
249     
250     mid_scr = scr_min+(scr_max-scr_min)/2;
251
252         marker_x = ladder.x_pos-ladder.scr_width/2;
253         
254     factor = (scr_max-scr_min)/ladder.width_units;
255
256     for( i=vmin; i<=vmax; i+=1 )
257     {
258         condition = 1;
259         if( condition )
260         {
261             marker_y = scr_min+(i-vmin)*factor;
262             if( i%ladder.div_units==0 )
263             {
264                 sprintf( TextLadder, "%d", i );
265                 if( ladder.scr_hole == 0 )
266                 {
267                         if( i != 0 )
268                                 x_ini = ladder.x_pos-ladder.scr_width/2;
269                         else
270                                 x_ini = ladder.x_pos-ladder.scr_width/2-10;
271                         y_ini = marker_y;
272                         x_end = ladder.x_pos+ladder.scr_width/2;
273                         y_end = marker_y;
274                                 new_x_ini = ladder.x_pos+(x_ini-ladder.x_pos)*cos(roll_value)-\
275                                         (y_ini-ladder.y_pos)*sin(roll_value);
276                                 new_y_ini = ladder.y_pos+(x_ini-ladder.x_pos)*sin(roll_value)+\
277                                         (y_ini-ladder.y_pos)*cos(roll_value);
278                                 new_x_end = ladder.x_pos+(x_end-ladder.x_pos)*cos(roll_value)-\
279                                         (y_end-ladder.y_pos)*sin(roll_value);
280                                 new_y_end = ladder.y_pos+(x_end-ladder.x_pos)*sin(roll_value)+\
281                                         (y_end-ladder.y_pos)*cos(roll_value);
282    
283                                         if( i >= 0 )
284                                         {
285                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
286                         }
287                         else
288                         {
289                                 glEnable(GL_LINE_STIPPLE);
290                                 glLineStipple( 1, 0x00FF );
291                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
292                                 glDisable(GL_LINE_STIPPLE);
293                         }
294                         textString( new_x_ini-8*strlen(TextLadder)-8, new_y_ini-4, TextLadder, GLUT_BITMAP_8_BY_13 );
295                         textString( new_x_end+10, new_y_end-4, TextLadder, GLUT_BITMAP_8_BY_13 );
296                 }
297                 else
298                 {
299                         if( i != 0 )
300                                 x_ini = ladder.x_pos-ladder.scr_width/2;
301                         else
302                                 x_ini = ladder.x_pos-ladder.scr_width/2-10;
303                         y_ini = marker_y;
304                         x_end = ladder.x_pos-ladder.scr_width/2+ladder.scr_hole/2;
305                         y_end = marker_y;
306                                 new_x_ini = ladder.x_pos+(x_ini-ladder.x_pos)*cos(roll_value)-\
307                                         (y_ini-ladder.y_pos)*sin(roll_value);
308                                 new_y_ini = ladder.y_pos+(x_ini-ladder.x_pos)*sin(roll_value)+\
309                                         (y_ini-ladder.y_pos)*cos(roll_value);
310                                 new_x_end = ladder.x_pos+(x_end-ladder.x_pos)*cos(roll_value)-\
311                                         (y_end-ladder.y_pos)*sin(roll_value);
312                                 new_y_end = ladder.y_pos+(x_end-ladder.x_pos)*sin(roll_value)+\
313                                         (y_end-ladder.y_pos)*cos(roll_value);
314             
315                         if( i >= 0 )
316                         {
317                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
318                         }
319                         else
320                         {
321                                 glEnable(GL_LINE_STIPPLE);
322                                 glLineStipple( 1, 0x00FF );
323                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
324                                 glDisable(GL_LINE_STIPPLE);
325                         }
326                         textString( new_x_ini-8*strlen(TextLadder)-8, new_y_ini-4, TextLadder, GLUT_BITMAP_8_BY_13 );
327                         
328                         x_ini = ladder.x_pos+ladder.scr_width/2-ladder.scr_hole/2;
329                         y_ini = marker_y;
330                         if( i != 0 )
331                                 x_end = ladder.x_pos+ladder.scr_width/2;
332                         else
333                                 x_end = ladder.x_pos+ladder.scr_width/2+10;
334                         y_end = marker_y;
335                                 new_x_ini = ladder.x_pos+(x_ini-ladder.x_pos)*cos(roll_value)-\
336                                         (y_ini-ladder.y_pos)*sin(roll_value);
337                                 new_y_ini = ladder.y_pos+(x_ini-ladder.x_pos)*sin(roll_value)+\
338                                     (y_ini-ladder.y_pos)*cos(roll_value);
339                                 new_x_end = ladder.x_pos+(x_end-ladder.x_pos)*cos(roll_value)-\
340                                         (y_end-ladder.y_pos)*sin(roll_value);
341                                 new_y_end = ladder.y_pos+(x_end-ladder.x_pos)*sin(roll_value)+\
342                                         (y_end-ladder.y_pos)*cos(roll_value);
343             
344                         if( i >= 0 )
345                         {
346                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
347                         }
348                         else
349                         {
350                                 glEnable(GL_LINE_STIPPLE);
351                                 glLineStipple( 1, 0x00FF );
352                                 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
353                                 glDisable(GL_LINE_STIPPLE);
354                         }
355                         textString( new_x_end+10, new_y_end-4, TextLadder, GLUT_BITMAP_8_BY_13 );
356                 }
357             }
358             /* if( i%max_div==0 )
359             {
360                 drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
361                 sprintf( TextScale, "%d", i );
362                 if( orientation == LEFT )
363                 {
364                         textString( marker_x-8*strlen(TextScale)-2, marker_y-4, TextScale, GLUT_BITMAP_8_BY_13 );
365                 }
366                 else if( orientation == RIGHT )
367                 {
368                         textString( marker_x+10, marker_y-4, TextScale, GLUT_BITMAP_8_BY_13 );
369                 }
370             } */
371         }
372     }
373
374 }
375
376 /*
377
378         Draws an artificial horizon line in the center of the HUD
379                 (with or without a center hole)
380         
381         Needs: x_center, y_center, length, hole
382
383 */
384 static void drawhorizon( struct HUD_horizon horizon )
385 {
386         int x_inc1, y_inc1;
387         int x_inc2, y_inc2;
388         /* struct fgFLIGHT *f; */
389         double sin_bank, cos_bank;
390         double bank_angle;
391               
392         /* f = &current_aircraft.flight; */
393         
394         bank_angle = (*horizon.load_value)();
395
396         // sin_bank = sin( FG_2PI-FG_Phi );
397         // cos_bank = cos( FG_2PI-FG_Phi );
398         sin_bank = sin(FG_2PI-bank_angle);
399         cos_bank = cos(FG_2PI-bank_angle);
400         x_inc1 = (int)(horizon.scr_width*cos_bank);
401         y_inc1 = (int)(horizon.scr_width*sin_bank);
402         x_inc2 = (int)(horizon.scr_hole*cos_bank);
403         y_inc2 = (int)(horizon.scr_hole*sin_bank);
404         
405         if( horizon.scr_hole == 0 )
406         {
407                 drawOneLine( horizon.x_pos-x_inc1, horizon.y_pos-y_inc1, \
408                                                 horizon.x_pos+x_inc1, horizon.y_pos+y_inc1 );
409         }
410         else
411         {
412                 drawOneLine( horizon.x_pos-x_inc1, horizon.y_pos-y_inc1, \
413                                                 horizon.x_pos-x_inc2, horizon.y_pos-y_inc2 );
414                 drawOneLine( horizon.x_pos+x_inc2, horizon.y_pos+y_inc2, \
415                                                 horizon.x_pos+x_inc1, horizon.y_pos+y_inc1 );
416         }       
417 }
418
419 /*
420
421         Draws a label anywhere in the HUD
422         
423         Needs: HUD_label struct
424
425 */      
426 static void drawlabel( struct HUD_label label )
427 {
428         char buffer[80];
429         char string[80];
430         int posincr;
431         int lenstr;
432         
433         if( label.pre_str != NULL && label.post_str != NULL )
434                 sprintf( buffer, "%s%s%s", label.pre_str, label.format, label.post_str );
435         else if( label.pre_str == NULL && label.post_str != NULL )
436                 sprintf( buffer, "%s%s", label.format, label.post_str );
437         else if( label.pre_str != NULL && label.post_str == NULL )
438                 sprintf( buffer, "%s%s", label.pre_str, label.format );
439
440         sprintf( string, buffer, (*label.load_value)() );
441
442 #ifdef DEBUG    
443         fgPrintf( FG_COCKPIT, FG_DEBUG,  buffer );
444         fgPrintf( FG_COCKPIT, FG_DEBUG,  "\n" );
445         fgPrintf( FG_COCKPIT, FG_DEBUG, string );
446         fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
447 #endif
448
449         lenstr = strlen( string );
450         if( label.justify == LEFT_JUST )
451                 posincr = -lenstr*8;
452         else if( label.justify == CENTER_JUST )
453                 posincr = -lenstr*4;
454         else if( label.justify == RIGHT_JUST )
455                 posincr = 0;
456         
457         if( label.size == SMALL )
458                 textString( label.x_pos+posincr, label.y_pos, string, GLUT_BITMAP_8_BY_13);
459         else if( label.size == LARGE )
460                 textString( label.x_pos+posincr, label.y_pos, string, GLUT_BITMAP_9_BY_15);
461         
462 }
463
464 double get_speed( void )
465 {
466         struct fgFLIGHT *f;
467               
468         f = &current_aircraft.flight;
469         return( FG_V_equiv_kts );
470 }
471
472 double get_aoa( void )
473 {
474         struct fgFLIGHT *f;
475               
476         f = &current_aircraft.flight;
477         return( FG_Gamma_vert_rad*RAD_TO_DEG );
478 }
479
480 double get_roll( void )
481 {
482         struct fgFLIGHT *f;
483               
484         f = &current_aircraft.flight;
485         return( FG_Phi );
486 }
487
488 double get_pitch( void )
489 {
490         struct fgFLIGHT *f;
491               
492         f = &current_aircraft.flight;
493         return( FG_Theta );
494 }
495
496 double get_heading( void )
497 {
498         struct fgFLIGHT *f;
499               
500         f = &current_aircraft.flight;
501         return( FG_Psi*RAD_TO_DEG ); 
502 }
503
504 double get_altitude( void )
505 {
506         struct fgFLIGHT *f;
507         /* double rough_elev; */
508               
509         f = &current_aircraft.flight;
510         /* rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
511                                            FG_Latitude  * RAD_TO_ARCSEC); */
512                                                    
513         return( FG_Altitude * FEET_TO_METER /* - rough_elev */ );
514 }
515
516 void add_instrument( Hptr hud, HIptr instrument )
517 {
518         HIptr instruments;
519         
520         instruments = hud->instruments;
521         // while( ++instruments
522 }
523
524 Hptr fgHUDInit( struct fgAIRCRAFT current_aircraft, int color )
525 {
526         Hptr hud;
527         
528         hud = (Hptr)calloc(sizeof(struct HUD),1);
529         if( hud == NULL )
530                 return( NULL );
531                 
532         hud->code = 123;
533         hud->status = 0;
534         
535         // For now lets just hardcode a hud here .
536         // In the future, hud information has to come from the same place 
537         // aircraft information came
538         
539         fgHUDAddHorizon( hud, 590, 50, 40, 20, get_roll );
540         fgHUDAddScale( hud, VERTICAL, 220, 100, 280, 5, 10, LEFT, LEFT, 0, 100, get_speed );
541         fgHUDAddScale( hud, VERTICAL, 440, 100, 280, 1, 5, RIGHT, RIGHT, -400, 25, get_aoa );
542         fgHUDAddScale( hud, HORIZONTAL, 280, 220, 440, 5, 10, TOP, TOP, 0, 50, get_heading );
543         fgHUDAddLabel( hud, 180, 85, SMALL, NOBLINK, RIGHT_JUST, NULL, " Kts", "%5.0f", get_speed );
544         fgHUDAddLabel( hud, 180, 73, SMALL, NOBLINK, RIGHT_JUST, NULL, " m", "%5.0f", get_altitude );
545         fgHUDAddLadder( hud, 330, 190, 90, 180, 70, 10, NONE, 45, get_roll, get_pitch );
546         
547         return( hud );
548 }
549
550 Hptr fgHUDAddHorizon( Hptr hud, int x_pos, int y_pos, int length, \
551                                                 int hole_len, double (*load_value)() )
552 {
553         struct HUD_horizon *horizon;
554         struct HUD_instr *instrument;
555         HIptr tmp_first, tmp_next;
556         
557         tmp_first = hud->instruments;
558         if( tmp_first != NULL )
559                 tmp_next = tmp_first->next;
560         else
561                 tmp_next = NULL;
562         
563         instrument = (HIptr)calloc(sizeof(struct HUD_instr),1);
564         if( instrument == NULL )
565                 return( NULL );
566                 
567         horizon = (struct HUD_horizon *)calloc(sizeof(struct HUD_horizon),1);
568         if( horizon == NULL )
569                 return( NULL );
570         
571         instrument->type = ARTIFICIAL_HORIZON;
572         instrument->instr.horizon = *horizon;
573         instrument->instr.horizon.x_pos = x_pos;
574         instrument->instr.horizon.y_pos = y_pos;
575         instrument->instr.horizon.scr_width = length;
576         instrument->instr.horizon.scr_hole = hole_len;
577         instrument->instr.horizon.load_value = load_value;
578         instrument->next = tmp_first;
579
580         hud->instruments = instrument;
581
582         return( hud );
583 }
584
585 Hptr fgHUDAddScale( Hptr hud, int type, int scr_pos, int scr_min, int scr_max, int div_min, int div_max, \
586                                         int orientation, int with_min, int min_value, int width_units, double (*load_value)() )
587 {
588         struct HUD_scale *scale;
589         struct HUD_instr *instrument;
590         HIptr tmp_first, tmp_next;
591         
592         tmp_first = hud->instruments;
593         if( tmp_first != NULL )
594                 tmp_next = tmp_first->next;
595         else
596                 tmp_next = NULL;
597         
598         instrument = (HIptr)calloc(sizeof(struct HUD_instr),1);
599         if( instrument == NULL )
600                 return( NULL );
601                 
602         scale = (struct HUD_scale *)calloc(sizeof(struct HUD_scale),1);
603         if( scale == NULL )
604                 return( NULL );
605         
606         instrument->type = SCALE;
607         instrument->instr.scale = *scale;
608         instrument->instr.scale.type = type;
609         instrument->instr.scale.scr_pos = scr_pos;
610         instrument->instr.scale.scr_min = scr_min;
611         instrument->instr.scale.scr_max = scr_max;
612         instrument->instr.scale.div_min = div_min;
613         instrument->instr.scale.div_max = div_max;
614         instrument->instr.scale.orientation = orientation;
615         instrument->instr.scale.with_minimum = with_min;
616         instrument->instr.scale.minimum_value = min_value;
617         instrument->instr.scale.width_units = width_units;
618         instrument->instr.scale.load_value = load_value;
619         instrument->next = tmp_first;
620
621         hud->instruments = instrument;
622
623         return( hud );
624 }
625
626 Hptr fgHUDAddLabel( Hptr hud, int x_pos, int y_pos, int size, int blink, int justify, \
627                                         char *pre_str, char *post_str, char *format, double (*load_value)() )
628 {
629         struct HUD_label *label;
630         struct HUD_instr *instrument;
631         HIptr tmp_first, tmp_next;
632         
633         tmp_first = hud->instruments;
634         if( tmp_first != NULL )
635                 tmp_next = tmp_first->next;
636         else
637                 tmp_next = NULL;
638         
639         instrument = (HIptr)calloc(sizeof(struct HUD_instr),1);
640         if( instrument == NULL )
641                 return( NULL );
642                 
643         label = (struct HUD_label *)calloc(sizeof(struct HUD_label),1);
644         if( label == NULL )
645                 return( NULL );
646         
647         instrument->type = LABEL;
648         instrument->instr.label = *label;
649         instrument->instr.label.x_pos = x_pos;
650         instrument->instr.label.y_pos = y_pos;
651         instrument->instr.label.size = size;
652         instrument->instr.label.blink = blink;
653         instrument->instr.label.justify = justify;
654         instrument->instr.label.pre_str = pre_str;
655         instrument->instr.label.post_str = post_str;
656         instrument->instr.label.format = format;
657         instrument->instr.label.load_value = load_value;
658         instrument->next = tmp_first;
659
660         hud->instruments = instrument;
661
662         return( hud );
663 }
664
665 Hptr fgHUDAddLadder( Hptr hud, int x_pos, int y_pos, int scr_width, int scr_height, \
666                                         int hole_len, int div_units, int label_pos, int width_units, \
667                                         double (*load_roll)(), double (*load_pitch)() )
668 {
669         struct HUD_ladder *ladder;
670         struct HUD_instr *instrument;
671         HIptr tmp_first, tmp_next;
672         
673         tmp_first = hud->instruments;
674         if( tmp_first != NULL )
675                 tmp_next = tmp_first->next;
676         else
677                 tmp_next = NULL;
678         
679         instrument = (HIptr)calloc(sizeof(struct HUD_instr),1);
680         if( instrument == NULL )
681                 return( NULL );
682                 
683         ladder = (struct HUD_ladder *)calloc(sizeof(struct HUD_ladder),1);
684         if( ladder == NULL )
685                 return( NULL );
686
687         instrument->type = LADDER;
688         instrument->instr.ladder = *ladder;
689         instrument->instr.ladder.type = 0;      // Not used.
690         instrument->instr.ladder.x_pos = x_pos;
691         instrument->instr.ladder.y_pos = y_pos;
692         instrument->instr.ladder.scr_width = scr_width;
693         instrument->instr.ladder.scr_height = scr_height;
694         instrument->instr.ladder.scr_hole = hole_len;
695         instrument->instr.ladder.div_units = div_units;
696         instrument->instr.ladder.label_position = label_pos;
697         instrument->instr.ladder.width_units = width_units;
698         instrument->instr.ladder.load_roll = load_roll;
699         instrument->instr.ladder.load_pitch = load_pitch;
700         instrument->next = tmp_first;
701
702         hud->instruments = instrument;
703
704         return( hud );
705 }
706
707 /*
708 Hptr fgHUDAddMovingHorizon( Hptr hud, int x_pos, int y_pos, int length, int hole_len, \
709                                                 int color )
710 {
711
712 }
713
714 Hptr fgHUDAddCircularLadder( Hptr hud, int scr_min, int scr_max, int div_min, int div_max, \
715                                                 int max_value )
716 {
717
718 }
719
720 Hptr fgHUDAddNumDisp( Hptr hud, int x_pos, int y_pos, int size, int color, int blink, \
721                                                 char *pre_str, char *post_str )
722 {
723
724 }
725 */
726
727 void fgUpdateHUD( Hptr hud )
728 {
729         HIptr hud_instr;
730         union HUD_instr_data instr_data;
731               
732         glMatrixMode(GL_PROJECTION);
733         glPushMatrix();
734
735         glLoadIdentity();
736         gluOrtho2D(0, 640, 0, 480);
737         glMatrixMode(GL_MODELVIEW);
738         glPushMatrix();
739         glLoadIdentity();
740          
741         glColor3f(1.0, 1.0, 1.0);
742         glIndexi(7);
743               
744         glDisable(GL_DEPTH_TEST);
745         glDisable(GL_LIGHTING);
746                   
747         glLineWidth(1);
748         glColor3f (0.1, 0.9, 0.1);
749                       
750 #ifdef DEBUG    
751     fgPrintf( FG_COCKPIT, FG_DEBUG,  "HUD Code %d  Status %d\n", 
752               hud->code, hud->status ); 
753 #endif
754     hud_instr = hud->instruments;
755         while( hud_instr != NULL )
756         {
757                 instr_data = hud_instr->instr;
758 #ifdef DEBUG
759                 fgPrintf( FG_COCKPIT, FG_DEBUG, 
760                           "Instr Type %d   SubType %d  Orient %d\n", 
761                           hud_instr->type, hud_instr->sub_type, hud_instr->orientation );
762 #endif
763                 if( hud_instr->type == ARTIFICIAL_HORIZON )
764                 {
765                         drawhorizon( instr_data.horizon );
766                         /* drawhorizon( instr_data.horizon.x_pos, instr_data.horizon.y_pos, \
767                                 instr_data.horizon.scr_width, instr_data.horizon.scr_hole ); */
768         }
769         else if( hud_instr->type == SCALE )
770         {
771                 drawscale( instr_data.scale.type, instr_data.scale.with_minimum, \
772                                 instr_data.scale.minimum_value, instr_data.scale.orientation, \
773                                 instr_data.scale.scr_pos, instr_data.scale.scr_min, \
774                                 instr_data.scale.scr_max, instr_data.scale.width_units, \
775                                 instr_data.scale.div_min, instr_data.scale.div_max, \
776                                         (*instr_data.scale.load_value)() );                                     
777         }
778         else if( hud_instr->type == LABEL )
779         {
780                 drawlabel( instr_data.label );
781                 /* drawlabel( instr_data.label.x_pos, instr_data.label.y_pos, instr_data.label.size, \
782                                 instr_data.label.blink, instr_data.label.pre_str, instr_data.label.post_str, \
783                                 instr_data.label.format, (*instr_data.label.load_value)() ); */
784         }
785         else if( hud_instr->type == LADDER )
786         {
787                 drawladder( instr_data.ladder );
788         }
789         hud_instr = hud_instr->next;
790     }
791     
792     
793         glEnable(GL_DEPTH_TEST);
794         glEnable(GL_LIGHTING);
795         glMatrixMode(GL_PROJECTION);
796         glPopMatrix();
797         glMatrixMode(GL_MODELVIEW);
798         glPopMatrix();
799                 
800 }
801
802
803 /* $Log$
804 /* Revision 1.9  1998/01/31 00:43:04  curt
805 /* Added MetroWorks patches from Carmen Volpe.
806 /*
807  * Revision 1.8  1998/01/27 00:47:51  curt
808  * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
809  * system and commandline/config file processing code.
810  *
811  * Revision 1.7  1998/01/19 18:40:20  curt
812  * Tons of little changes to clean up the code and to remove fatal errors
813  * when building with the c++ compiler.
814  *
815  * Revision 1.6  1997/12/15 23:54:34  curt
816  * Add xgl wrappers for debugging.
817  * Generate terrain normals on the fly.
818  *
819  * Revision 1.5  1997/12/10 22:37:39  curt
820  * Prepended "fg" on the name of all global structures that didn't have it yet.
821  * i.e. "struct WEATHER {}" became "struct fgWEATHER {}"
822  *
823  * Revision 1.4  1997/09/23 00:29:32  curt
824  * Tweaks to get things to compile with gcc-win32.
825  *
826  * Revision 1.3  1997/09/05 14:17:26  curt
827  * More tweaking with stars.
828  *
829  * Revision 1.2  1997/09/04 02:17:30  curt
830  * Shufflin' stuff.
831  *
832  * Revision 1.1  1997/08/29 18:03:22  curt
833  * Initial revision.
834  *
835  */