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