]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/hud.cxx
Added Alex's patches for more accurate instrument modeling (compass, vsi,
[flightgear.git] / src / Cockpit / hud.cxx
1 // hud.cxx -- hud defines and prototypes
2 //
3 // Written by Michele America, started September 1997.
4 //
5 // Copyright (C) 1997  Michele F. America  - micheleamerica@geocities.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #ifdef HAVE_WINDOWS_H
29 #  include <windows.h>
30 #endif
31
32 #ifdef __BORLANDC__
33 #  define exception c_exception
34 #endif
35 #include <math.h>
36
37 #include <GL/glut.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #ifdef HAVE_VALUES_H
42 #  include <values.h>  // for MAXINT
43 #endif
44
45 #include <simgear/constants.h>
46 #include <simgear/debug/logstream.hxx>
47 #include <simgear/math/fg_random.h>
48 #include <simgear/math/polar3d.hxx>
49
50 #include <Aircraft/aircraft.hxx>
51 #include <GUI/gui.h>
52 #include <Main/options.hxx>
53 #ifdef FG_NETWORK_OLK
54 #include <NetworkOLK/network.h>
55 #endif
56 #include <Scenery/scenery.hxx>
57 #include <Time/fg_timer.hxx>
58
59 #if defined ( __sun__ ) || defined ( __sgi )
60 extern "C" {
61   extern void *memmove(void *, const void *, size_t);
62 }
63 #endif
64
65 #include "hud.hxx"
66
67 static char units[5];
68
69 // The following routines obtain information concerning the aircraft's
70 // current state and return it to calling instrument display routines.
71 // They should eventually be member functions of the aircraft.
72 //
73
74 deque< instr_item * > HUD_deque;
75
76 fgTextList         HUD_TextList;
77 fgLineList         HUD_LineList;
78 fgLineList         HUD_StippleLineList;
79
80 class locRECT {
81   public:
82     RECT rect;
83
84     locRECT( UINT left, UINT top, UINT right, UINT bottom);
85     RECT get_rect(void) { return rect;}
86 };
87
88 locRECT :: locRECT( UINT left, UINT top, UINT right, UINT bottom)
89 {
90   rect.left   =  left;
91   rect.top    =  top;
92   rect.right  =  right;
93   rect.bottom =  bottom;
94
95 }
96 // #define DEBUG
97
98 void drawOneLine( UINT x1, UINT y1, UINT x2, UINT y2)
99 {
100   glBegin(GL_LINES);
101   glVertex2f(x1, y1);
102   glVertex2f(x2, y2);
103   glEnd();
104 }
105
106 void drawOneLine( RECT &rect)
107 {
108   glBegin(GL_LINES);
109   glVertex2f(rect.left, rect.top);
110   glVertex2f(rect.right, rect.bottom);
111   glEnd();
112 }
113
114 //
115 // The following code deals with painting the "instrument" on the display
116 //
117    /* textString - Bitmap font string */
118
119 void textString( int x, int y, char *msg, void *font ){
120
121     if(*msg)
122     {
123 //      puDrawString (  NULL, msg, x, y );
124         
125         glRasterPos2f(x, y);
126         while (*msg) {
127             glutBitmapCharacter(font, *msg);
128             msg++;
129         }
130     }
131 }
132
133
134 /* strokeString - Stroke font string */
135 void strokeString(int x, int y, char *msg, void *font, float theta)
136 {
137     int xx;
138     int yy;
139     int c;
140     float sintheta,costheta;
141     
142
143     if(*msg)
144     {
145     glPushMatrix();
146     glRotatef(theta * RAD_TO_DEG, 0.0, 0.0, 1.0);
147     sintheta = sin(theta);
148     costheta = cos(theta);
149     xx = (int)(x * costheta + y * sintheta);
150     yy = (int)(y * costheta - x * sintheta);
151     glTranslatef( xx, yy, 0);
152     glScalef(.1, .1, 0.0);
153     while( (c=*msg++) ) {
154         glutStrokeCharacter(font, c);
155     }
156     glPopMatrix();
157     }
158 }
159
160 int getStringWidth ( char *str )
161 {
162     if ( HUDtext && str )
163     {
164         float r, l ;
165         guiFntHandle->getBBox ( str, HUD_TextSize, 0, &l, &r, NULL, NULL ) ;
166         return FloatToInt( r - l );
167     }
168     return 0 ;
169 }
170
171 //========================= End of Class Implementations===================
172 // fgHUDInit
173 //
174 // Constructs a HUD object and then adds in instruments. At the present
175 // the instruments are hard coded into the routine. Ultimately these need
176 // to be defined by the aircraft's instrumentation records so that the
177 // display for a Piper Cub doesn't show the speed range of a North American
178 // mustange and the engine readouts of a B36!
179 //
180
181 #define INSTRDEFS 21
182
183 int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ )
184 {
185   instr_item *HIptr;
186 //  int index;
187   int font_size;
188
189 //  int off = 50;
190   int min_x = 25; //off/2;
191   int max_x = 615; //640-(off/2);
192 //  int min_y = off;
193   int max_y = 430; //480-off;
194   int cen_x = 320;
195   int cen_y = 240;
196   unsigned int text_h = 10;
197   unsigned int ladr_w2 = 60;
198   int ladr_h2 = 90;
199   int ladr_t = 35;
200   int compass_w = 200;
201   int gap = 10;
202
203   font_size = (current_options.get_xsize() > 1000) ? LARGE : SMALL;
204   
205   HUD_style = 1;
206
207   FG_LOG( FG_COCKPIT, FG_INFO, "Initializing current aircraft HUD" );
208
209 //  deque < instr_item * > :: iterator first = HUD_deque.begin();
210 //  deque < instr_item * > :: iterator last = HUD_deque.end();
211 //  HUD_deque.erase( first, last);  // empty the HUD deque  
212
213   HUD_deque.erase( HUD_deque.begin(), HUD_deque.end());  // empty the HUD deque
214
215 //  hud->code = 1;
216 //  hud->status = 0;
217
218   // For now lets just hardcode the hud here.
219   // In the future, hud information has to come from the same place
220   // aircraft information came from.
221
222 //  fgHUDSetTimeMode( hud, NIGHT );
223 //  fgHUDSetBrightness( hud, BRT_LIGHT );
224
225 //      case 0:     // TBI
226 //  int x = 290; /*cen_x-30*/
227 //  int y = 45;  /*off-5*/
228 //  HIptr = (instr_item *) new fgTBI_instr( x, y, ladr_w2, text_h );
229   HIptr = (instr_item *) new fgTBI_instr( 290, 45, 60, 10 );  
230   HUD_deque.insert( HUD_deque.begin(), HIptr);
231
232 //      case 1:     // Artificial Horizon
233   HIptr = (instr_item *) new HudLadder( cen_x-ladr_w2, cen_y-ladr_h2,
234                                         2*ladr_w2, 2*ladr_h2 );
235   HUD_deque.insert( HUD_deque.begin(), HIptr);
236
237 //      case 4:    // GYRO COMPASS
238   HIptr = (instr_item *) new hud_card( cen_x-(compass_w/2),
239                                        max_y,
240                                        compass_w,
241                                        28,
242                                        get_heading,
243                                        HUDS_TOP,
244                                        360, 0,
245                                        1.0,
246                                        5,   1,
247                                        360,
248                                        0,
249                                        25,
250                                        true);
251   HUD_deque.insert( HUD_deque.begin(), HIptr);
252
253 //      case 5:    // AMSL
254   HIptr = (instr_item *) new hud_card( max_x - 35 -15, // 15 to balance speed card
255                                        cen_y-(compass_w/2),
256                                        35,
257                                        compass_w,
258                                        get_altitude,
259 //                                     HUDS_RIGHT | HUDS_VERT,
260                                        HUDS_LEFT | HUDS_VERT,
261                                        5000, -1000,
262                                        1.0,
263                                        100,  25,
264                                        0,
265                                        0,
266                                        250,
267                                        true);
268   HUD_deque.insert( HUD_deque.begin(), HIptr);
269
270 //      case 6:
271   HIptr = (instr_item *) new  guage_instr( cen_x-50,            // x
272                                            cen_y + ladr_h2 -20,  // y
273                                            100,            // width
274                                            20,            // height
275                                            get_aileronval, // data source
276                                            HUDS_BOTTOM | HUDS_NOTEXT,
277                                            100.0,
278                                            +1.0,
279                                            -1.0);
280   HUD_deque.insert( HUD_deque.begin(), HIptr);
281
282 //      case 3:    // Radio Altimeter
283   HIptr = (instr_item *) new hud_card( cen_x + ladr_w2 + gap + 13 + ladr_t,
284                                        cen_y-75,
285                                        25,
286                                        150,
287                                        get_agl,
288                                        HUDS_LEFT | HUDS_VERT,
289                                        1000, 0,
290                                        1.0,
291                                        25, 5,
292                                        0,
293                                        0,
294                                        200.0,
295                                        true);
296   HUD_deque.insert( HUD_deque.begin(), HIptr);
297
298 //      case 7:
299   HIptr = (instr_item *) new  guage_instr( cen_x -ladr_w2 -gap -13 -20 -ladr_t,
300                                            cen_y-50,             // y
301                                            20,             // width
302                                            100,             // height
303                                            get_elevatorval, // data source
304                                            HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT,
305                                            -100.0,           // Scale data
306                                            +1.0,           // Data Range
307                                            -1.0);
308   HUD_deque.insert( HUD_deque.begin(), HIptr);
309
310 //      case 8:
311   HIptr = (instr_item *) new  guage_instr( cen_x-50,             // x
312                                            cen_y -gap -ladr_w2 -20, //-85   // y
313                                            100,             // width
314                                            20,             // height
315                                            get_rudderval,   // data source
316                                            HUDS_TOP | HUDS_NOTEXT,
317                                            100.0,
318                                            +1.0,
319                                            -1.0);
320   HUD_deque.insert( HUD_deque.begin(), HIptr);
321
322 //      case 2:    // KIAS
323   HIptr = (instr_item *) new hud_card( min_x +10 +5, //min_x +18,
324                                        cen_y-(compass_w/2),
325                                        28,
326                                        compass_w,
327                                        get_speed,
328 //                                     HUDS_LEFT | HUDS_VERT,
329                                        HUDS_RIGHT | HUDS_VERT,                                     
330                                        200.0, 0.0,
331                                        1.0,
332                                        10,  5,
333                                        0,
334                                        0,
335                                        50.0,
336                                        true);
337
338   
339  
340   HUD_deque.insert( HUD_deque.begin(), HIptr);
341     
342
343 //      case 10:    // Digital Mach number
344         HIptr = (instr_item *) new instr_label ( min_x , //same as speed tape
345                                                  cen_y-(compass_w/2) -10, //below speed tape
346                                                   40,
347                                                   30,
348                                                  get_mach,
349                                                  "%4.2f",
350                                                  "",
351                                                  NULL,
352                                                  1.0,
353                                                  HUDS_TOP,
354                                                  RIGHT_JUST,
355                                                  font_size,
356                                                  0,
357                                                  TRUE );
358   HUD_deque.insert( HUD_deque.begin(), HIptr);
359
360 //      case 9:
361   HIptr = (instr_item *) new  guage_instr( min_x-10,           // x
362                                            cen_y -75,       // y 
363                                            20,              // width
364                                            150,             // height
365                                            get_throttleval, // data source
366 //                                         HUDS_VERT | HUDS_RIGHT | HUDS_NOTEXT,
367                                            HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT,                                        100.0,
368                                            1.0,
369                                            0.0
370                                           );
371   HUD_deque.insert( HUD_deque.begin(), HIptr);
372 // Remove this when below uncommented       
373 //      case 10:
374   HIptr = (instr_item *) new instr_label( 10,
375                                           25,
376                                           60,
377                                           10,
378                                           get_frame_rate,
379                                           "%5.1f",
380                                           "",
381                                           NULL,
382                                           1.0,
383                                           HUDS_TOP,
384                                           RIGHT_JUST,
385                                           font_size,
386                                           0,
387                                           TRUE );
388   HUD_deque.insert( HUD_deque.begin(), HIptr);
389   
390   HIptr = (instr_item *) new lat_label(  (cen_x - (compass_w/2))/2,
391                                           max_y,    
392                                           1,
393                                           text_h,
394                                           get_latitude,
395                                           "%s%", //"%.0f",
396                                           "", //"Lat ",
397                                           "",
398                                           1.0,
399                                           HUDS_TOP,
400                                           CENTER_JUST,
401                                           font_size,
402                                           0,
403                                           TRUE );
404   HUD_deque.insert( HUD_deque.begin(), HIptr);
405     
406     HIptr = (instr_item *) new lon_label(((cen_x+compass_w/2)+(2*cen_x))/2,
407                                           max_y,
408                                           1, text_h,
409                                           get_longitude,
410                                           "%s%",//"%.0f",
411                                           "", //"Lon ", 
412                                           "",
413                                           1.0,
414                                           HUDS_TOP,
415                                           CENTER_JUST,
416                                           font_size,
417                                           0,
418                                           TRUE );
419   HUD_deque.insert( HUD_deque.begin(), HIptr);
420     
421 /*
422 //      case 10:    // Digital KIAS
423         HIptr = (instr_item *) new instr_label ( 110,
424                                                  150,
425                                                   40,
426                                                   30,
427                                                  get_speed,
428                                                  "%5.0f",
429                                                  NULL,
430                                                  " Kts",
431                                                  1.0,
432                                                  HUDS_TOP,
433                                                  RIGHT_JUST,
434                                                  font_size,
435                                                  0,
436                                                  TRUE );
437   HUD_deque.insert( HUD_deque.begin(), HIptr);
438
439 //      case 11:    // Digital Rate of Climb
440         HIptr = (instr_item *) new instr_label ( 110,
441                                                  135,
442                                                   40,
443                                                   10,
444                                                  get_climb_rate,
445                                                  "%5.0f",
446                                                  " Climb",
447                                                  NULL,
448                                                  1.0,
449                                                  HUDS_TOP,
450                                                  RIGHT_JUST,
451                                                  font_size,
452                                                  0,
453                                                  TRUE );
454   HUD_deque.insert( HUD_deque.begin(), HIptr);
455
456 //      case 12:    // Roll indication diagnostic
457         HIptr = (instr_item *) new instr_label ( 110,
458                                                  120,
459                                                   40,
460                                                   10,
461                                                  get_roll,
462                                                  "%5.2f",
463                                                  " Roll",
464                                                  " Deg",
465                                                  1.0,
466                                                  HUDS_TOP,
467                                                  RIGHT_JUST,
468                                                  font_size,
469                                                  0,
470                                                  TRUE );
471   HUD_deque.insert( HUD_deque.begin(), HIptr);
472
473 //      case 13:    // Angle of attack diagnostic
474         HIptr = (instr_item *) new instr_label ( 440,
475                                                  150,
476                                                   60,
477                                                   10,
478                                                  get_aoa,
479                                                  "      %5.2f",
480                                                  "AOA",
481                                                  " Deg",
482                                                  1.0,
483                                                  HUDS_TOP,
484                                                  RIGHT_JUST,
485                                                  font_size,
486                                                  0,
487                                                  TRUE );
488   HUD_deque.insert( HUD_deque.begin(), HIptr);
489
490 //      case 14:
491         HIptr = (instr_item *) new instr_label ( 440,
492                                                  135,
493                                                   60,
494                                                   10,
495                                                  get_heading,
496                                                  " %5.1f",
497                                                  "Heading ",
498                                                  " Deg",
499                                                  1.0,
500                                                  HUDS_TOP,
501                                                  RIGHT_JUST,
502                                                  font_size,
503                                                  0,
504                                                  TRUE );
505   HUD_deque.insert( HUD_deque.begin(), HIptr);
506
507 //      case 15:
508         HIptr = (instr_item *) new instr_label ( 440,
509                                                  120,
510                                                   60,
511                                                   10,
512                                                  get_sideslip,
513                                                  "%5.2f",
514                                                  "Sideslip ",
515                                                  NULL,
516                                                  1.0,
517                                                  HUDS_TOP,
518                                                  RIGHT_JUST,
519                                                  font_size,
520                                                  0,
521                                                  TRUE );
522   HUD_deque.insert( HUD_deque.begin(), HIptr);
523
524 //      case 16:
525         HIptr = (instr_item *) new instr_label( 440,
526                                                 100,
527                                                  60,
528                                                  10,
529                                                 get_throttleval,
530                                                 "%5.2f",
531                                                 "Throttle ",
532                                                 NULL,
533                                                  1.0,
534                                                 HUDS_TOP,
535                                                 RIGHT_JUST,
536                                                 font_size,
537                                                 0,
538                                                 TRUE );
539   HUD_deque.insert( HUD_deque.begin(), HIptr);
540
541 //      case 17:
542         HIptr = (instr_item *) new instr_label( 440,
543                                                  85,
544                                                  60,
545                                                  10,
546                                                 get_elevatorval,
547                                                 "%5.2f",
548                                                 "Elevator ",
549                                                 NULL,
550                                                  1.0,
551                                                 HUDS_TOP,
552                                                 RIGHT_JUST,
553                                                 font_size,
554                                                 0,
555                                                 TRUE );
556   HUD_deque.insert( HUD_deque.begin(), HIptr);
557
558 //      case 18:
559         HIptr = (instr_item *) new instr_label( 440,
560                                                  60,
561                                                  60,
562                                                  10,
563                                                 get_aileronval,
564                                                 "%5.2f",
565                                                 "Aileron  ",
566                                                 NULL,
567                                                  1.0,
568                                                 HUDS_TOP,
569                                                 RIGHT_JUST,
570                                                 font_size,
571                                                 0,
572                                                 TRUE );
573   HUD_deque.insert( HUD_deque.begin(), HIptr);
574
575 //      case 19:
576         HIptr = (instr_item *) new instr_label( 10,
577                                                 10,
578                                                 60,
579                                                 10,
580                                                  get_frame_rate,
581                                                 "%.1f",
582                                                 "Frame rate = ",
583                                                 NULL,
584                                                  1.0,
585                                                 HUDS_TOP,
586                                                 RIGHT_JUST,
587                                                 font_size,
588                                                 0,
589                                                 TRUE );
590   HUD_deque.insert( HUD_deque.begin(), HIptr);
591
592 //      case 20:
593       switch( current_options.get_tris_or_culled() ) {
594       case 0:
595           HIptr = (instr_item *) new instr_label( 10,
596                               25,
597                               120,
598                               10,
599                               get_vfc_tris_drawn,
600                               "%.0f",
601                               "Tris Rendered = ",
602                               NULL,
603                               1.0,
604                               HUDS_TOP,
605                               RIGHT_JUST,
606                               font_size,
607                               0,
608                               TRUE );
609           break;
610       case 1:
611           HIptr = (instr_item *) new instr_label( 10,
612                               25,
613                               90,
614                               10,
615                               get_vfc_ratio,
616                               "%.2f",
617                               "VFC Ratio = ",
618                               NULL,
619                               1.0,
620                               HUDS_TOP,
621                               RIGHT_JUST,
622                               font_size,
623                               0,
624                               TRUE );
625           break;
626       }
627       break;
628
629 //      case 21:
630         HIptr = (instr_item *) new instr_label( 10,
631                                                 40,
632                                                 90,
633                                                 10,
634                                                 get_fov,
635                                                 "%.1f",
636                                                 "FOV = ",
637                                                 NULL,
638                         1.0,
639                                                 HUDS_TOP,
640                                                 RIGHT_JUST,
641                                                 font_size,
642                                                 0,
643                                                 TRUE );
644   HUD_deque.insert( HUD_deque.begin(), HIptr);
645 */
646 //      default:
647 //        HIptr = 0;;
648 //      }
649 //    if( HIptr ) {                   // Anything to install?
650 //      HUD_deque.insert( HUD_deque.begin(), HIptr);
651 //      }
652 //    index++;
653 //    }
654 //  while( HIptr );
655
656   return 0;  // For now. Later we may use this for an error code.
657
658 }
659
660 int fgHUDInit2( fgAIRCRAFT * /* current_aircraft */ )
661 {
662 //    instr_item *HIptr;
663 //    int index;
664     int font_size;
665
666     int off = 50;
667 //  int min_x = off;
668 //  int max_x = 640-off;
669 //  int min_y = off;
670     int max_y = 480-off;
671     int cen_x = 640 / 2;
672     int cen_y = 480 / 2;
673     int text_h = 10;
674     int ladr_w2 = 60;
675     int ladr_h2 = 90;
676 //  int ladr_t = 35;
677     int compass_w = 200;
678 //  int gap = 10;
679
680     font_size = (current_options.get_xsize() > 1000) ? LARGE : SMALL;
681
682     HUD_style = 2;
683
684     FG_LOG( FG_COCKPIT, FG_INFO, "Initializing current aircraft HUD" );
685
686 //  deque < instr_item * > :: iterator first = HUD_deque.begin();
687 //  deque < instr_item * > :: iterator last = HUD_deque.end();
688 //  HUD_deque.erase( first, last);  // empty the HUD deque  
689     HUD_deque.erase( HUD_deque.begin(), HUD_deque.end());
690
691     //  hud->code = 1;
692     //  hud->status = 0;
693
694     // For now lets just hardcode the hud here.
695     // In the future, hud information has to come from the same place
696     // aircraft information came from.
697
698     //  fgHUDSetTimeMode( hud, NIGHT );
699     //  fgHUDSetBrightness( hud, BRT_LIGHT );
700
701     //  index = 0;
702 //    index = 19;  
703
704     instr_item* p;
705
706     p = new HudLadder( cen_x-ladr_w2, cen_y-ladr_h2, 2*ladr_w2, 2*ladr_h2, 1 );
707     HUD_deque.push_front( p );
708
709 //      case 4:    // GYRO COMPASS
710     p =new hud_card( cen_x-(compass_w/2),
711                      max_y,
712                      compass_w,
713                      28,
714                      get_view_direction,
715                      HUDS_TOP,
716                      360, 0,
717                      1.0,
718                      5,   1,
719                      360,
720                      0,
721                      25,
722                      true);
723     HUD_deque.push_front( p );
724
725     p = new lat_label( (cen_x - compass_w/2)/2,
726                        max_y,
727                        0, text_h,
728                        get_latitude,
729                        "%s%", //"%.0f",
730                        "", //"Lat ",
731                        "",
732                        1.0,
733                        HUDS_TOP,
734                        CENTER_JUST,
735                        font_size,
736                        0,
737                        TRUE );
738     HUD_deque.push_front( p );
739     
740 //    p = new instr_label( 140, 450, 60, 10,
741 //           get_lat_min,
742 //           "%05.2f",
743 //           "",
744 //           NULL,
745 //           1.0,
746 //           HUDS_TOP,
747 //           CENTER_JUST,
748 //           font_size,
749 //           0,
750 //           TRUE );
751 //    HUD_deque.push_front( p );
752     
753     p = new lon_label(((cen_x+compass_w/2)+(2*cen_x))/2,
754                        max_y,
755                        1, text_h,
756                        get_longitude,
757                        "%s%",//"%.0f",
758                        "", //"Lon ",
759                        "",
760                        1.0,
761                        HUDS_TOP,
762                        CENTER_JUST,
763                        font_size,
764                        0,
765                        TRUE );
766     HUD_deque.push_front( p );
767     
768     int x_pos = 40;
769     
770     p = new instr_label( x_pos, 25, 60, 10,
771                          get_frame_rate,
772                          "%7.1f",
773                          "Frame rate =",
774                          NULL,
775                          1.0,
776                          HUDS_TOP,
777                          LEFT_JUST,
778                          font_size,
779                          0, 
780                          TRUE );
781     HUD_deque.push_front( p );
782 #if 0
783     p = new instr_label( x_pos, 40, 120, 10,
784                          get_vfc_tris_culled,
785                          "%7.0f",
786                          "Culled       =",
787                          NULL,
788                          1.0,
789                          HUDS_TOP,
790                          LEFT_JUST,
791                          font_size,
792                          0,
793                          TRUE );
794     HUD_deque.push_front( p );
795
796     p = new instr_label( x_pos, 55, 120, 10,
797                          get_vfc_tris_drawn,
798                          "%7.0f",
799                          "Rendered   =",
800                          NULL,
801                          1.0,
802                          HUDS_TOP,
803                          LEFT_JUST,
804                          font_size,
805                          0,
806                          TRUE );
807     HUD_deque.push_front( p );
808 #endif // 0
809         
810 //    p = new instr_label( x_pos, 70, 90, 10,
811     p = new instr_label( x_pos, 40, 90, 10,
812                          get_fov,
813                          "%7.1f",
814                          "FOV          = ",
815                          NULL,
816                          1.0,
817                          HUDS_TOP,
818                          LEFT_JUST,
819                          font_size,
820                          0,
821                          TRUE );
822     HUD_deque.push_front( p );
823
824     x_pos = 480;
825     
826     p = new instr_label ( x_pos,
827                           70,
828                           60,
829                           10,
830                           get_aoa,
831                           "%7.2f",
832                           "AOA      ",
833                           " Deg",
834                           1.0,
835                           HUDS_TOP,
836                           LEFT_JUST,
837                           font_size,
838                           0,
839                           TRUE );
840     HUD_deque.push_front( p );
841
842     p = new instr_label( x_pos, 55, 40, 30,
843                          get_speed,
844                          "%5.0f",
845                          "Airspeed ",
846                          " Kts",
847                          1.0,
848                          HUDS_TOP,
849                          LEFT_JUST,
850                          font_size,
851                          0,
852                          TRUE );
853     HUD_deque.push_front( p );
854
855     if ( current_options.get_units() == fgOPTIONS::FG_UNITS_FEET ) {
856     strcpy(units, " ft");
857     } else {
858     strcpy(units, " m");
859     }
860     p = new instr_label( x_pos, 40, 40, 10,
861              get_altitude,
862              "%5.0f",
863              "Altitude ",
864              units,
865              1.0,
866              HUDS_TOP,
867              LEFT_JUST,
868              font_size,
869              0,
870              TRUE );
871     HUD_deque.push_front( p );
872
873     p = new instr_label( x_pos, 25, 40, 10,
874              get_agl,
875              "%5.0f",
876              "Elvation ",
877              units,
878              1.0,
879              HUDS_TOP,
880              LEFT_JUST,
881              font_size,
882              0,
883              TRUE );
884     HUD_deque.push_front( p );
885
886     p = new instr_label( x_pos, 10, 60, 10,
887              get_heading,
888              "%5.1f",
889              "Heading  ",
890              " Deg",
891              1.0,
892              HUDS_TOP,
893              LEFT_JUST,
894              font_size,
895              0,
896              TRUE );
897     HUD_deque.push_front( p );
898
899     p = new fgTBI_instr( 290, 55, 60, 10 ); // 270
900     HUD_deque.push_front( p );
901     
902     p = new  guage_instr( 270, //250,            // x
903                           390, //360, //400, //45, //420,            // y
904                           100,            // width
905                           20,            // height
906                           get_aileronval, // data source
907                           HUDS_BOTTOM | HUDS_NOTEXT,
908                           100.0,
909                           +1.0,
910                           -1.0);
911     HUD_deque.push_front( p );
912
913     p = new  guage_instr( 20,             // x
914                           240-50,             // y
915                           20,             // width
916                           100,             // height
917                           get_elevatorval, // data source
918                           HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT,
919                           -100.0,           // Scale data
920                           +1.0,           // Data Range
921                           -1.0);
922     HUD_deque.push_front( p );
923
924     p = new  guage_instr( 270, //250,             // x
925                           10+15,             // y
926                           100,             // width
927                           20,             // height
928                           get_rudderval,   // data source
929                           HUDS_TOP | HUDS_NOTEXT,
930                           100.0,
931                           +1.0,
932                           -1.0);
933     HUD_deque.push_front( p );
934
935     p = new  guage_instr( 600,             // x
936                           240-80,
937                           20,
938                           160,             // height
939                           get_throttleval, // data source
940                           HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT,
941                           100.0,
942                           1.0,
943                           0.0);
944     HUD_deque.push_front( p );
945     
946     return 0;  // For now. Later we may use this for an error code.
947 }
948
949 int global_day_night_switch = DAY;
950
951 void HUD_brightkey( bool incr_bright )
952 {
953 instr_item *pHUDInstr = HUD_deque[0];
954 int brightness        = pHUDInstr->get_brightness();
955
956   if( current_options.get_hud_status() ) {
957     if( incr_bright ) {
958       switch (brightness) {
959         case BRT_LIGHT:
960           current_options.set_hud_status(0);
961           break;
962
963         case BRT_MEDIUM:
964           brightness = BRT_LIGHT;
965           break;
966
967         case BRT_DARK:
968           brightness = BRT_MEDIUM;
969           break;
970
971         case BRT_BLACK:
972           brightness = BRT_DARK;
973           break;
974
975         default:
976           brightness = BRT_BLACK;
977         }
978       }
979     else {
980       switch (brightness) {
981         case BRT_LIGHT:
982           brightness = BRT_MEDIUM;
983           break;
984
985         case BRT_MEDIUM:
986           brightness = BRT_DARK;
987           break;
988
989         case BRT_DARK:
990           brightness = BRT_BLACK;
991           break;
992
993         case BRT_BLACK:
994         default:
995           current_options.set_hud_status(0);
996         }
997       }
998     }
999   else {
1000     current_options.set_hud_status(1);
1001     if( incr_bright ) {
1002       if( DAY == global_day_night_switch ) {
1003         brightness = BRT_BLACK;
1004         }
1005       else {
1006         brightness = BRT_DARK;
1007         global_day_night_switch = DAY;
1008         }
1009       }
1010     else {
1011       if( NIGHT == global_day_night_switch ) {
1012         brightness = BRT_DARK;
1013         }
1014       else {
1015         brightness = BRT_MEDIUM;
1016         global_day_night_switch = NIGHT;
1017         }
1018       }
1019     }
1020   pHUDInstr->SetBrightness( brightness );
1021 }
1022
1023 #if 0
1024 // fgUpdateHUD
1025 //
1026 // Performs a once around the list of calls to instruments installed in
1027 // the HUD object with requests for redraw. Kinda. It will when this is
1028 // all C++.
1029 //
1030 void fgUpdateHUD( void ) {
1031   int brightness;
1032 //  int day_night_sw = current_aircraft.controls->day_night_switch;
1033   int day_night_sw = global_day_night_switch;
1034   int hud_displays = HUD_deque.size();
1035   instr_item *pHUDInstr;
1036   float line_width;
1037
1038   if( !hud_displays ) {  // Trust everyone, but ALWAYS cut the cards!
1039     return;
1040     }
1041
1042   HUD_TextList.erase();
1043   HUD_LineList.erase();
1044 //  HUD_StippleLineList.erase();
1045   
1046   pHUDInstr = HUD_deque[0];
1047   brightness = pHUDInstr->get_brightness();
1048 //  brightness = HUD_deque.at(0)->get_brightness();
1049
1050   glMatrixMode(GL_PROJECTION);
1051   glPushMatrix();
1052
1053   glLoadIdentity();
1054   gluOrtho2D(0, 640, 0, 480);
1055   glMatrixMode(GL_MODELVIEW);
1056   glPushMatrix();
1057   glLoadIdentity();
1058
1059   glColor3f(1.0, 1.0, 1.0);
1060   glIndexi(7);
1061
1062   glDisable(GL_DEPTH_TEST);
1063   glDisable(GL_LIGHTING);
1064
1065   // We can do translucency, so why not. :-)
1066 //  glEnable    ( GL_BLEND ) ;
1067 //  glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
1068   
1069   if( day_night_sw == DAY) {
1070       switch (brightness) {
1071           case BRT_LIGHT:
1072 //            glColor4f (0.1, 0.9, 0.1, 0.75);
1073             glColor3f (0.1, 0.9, 0.1);
1074             break;
1075
1076           case BRT_MEDIUM:
1077 //            glColor4f (0.1, 0.7, 0.0, 0.75);
1078             glColor3f (0.1, 0.7, 0.0);
1079             break;
1080
1081           case BRT_DARK:
1082 //            glColor4f (0.0, 0.6, 0.0, 0.75);
1083             glColor3f(0.0, 0.6, 0.0);
1084             break;
1085
1086           case BRT_BLACK:
1087 //            glColor4f( 0.0, 0.0, 0.0, 0.75);
1088             glColor3f( 0.0, 0.0, 0.0);
1089             break;
1090
1091           default:;
1092       }
1093   }
1094   else {
1095       if( day_night_sw == NIGHT) {
1096           switch (brightness) {
1097               case BRT_LIGHT:
1098 //                glColor4f (0.9, 0.1, 0.1, 0.75);
1099                 glColor3f (0.9, 0.1, 0.1);
1100                 break;
1101
1102               case BRT_MEDIUM:
1103 //                glColor4f (0.7, 0.0, 0.1, 0.75);
1104                 glColor3f (0.7, 0.0, 0.1);
1105                 break;
1106
1107               case BRT_DARK:
1108               default:
1109 //                glColor4f (0.6, 0.0, 0.0, 0.75);
1110                   glColor3f (0.6, 0.0, 0.0);
1111           }
1112       }
1113           else {     // Just in case default
1114 //            glColor4f (0.1, 0.9, 0.1, 0.75);
1115               glColor3f (0.1, 0.9, 0.1);
1116           }
1117   }
1118
1119   deque < instr_item * > :: iterator current = HUD_deque.begin();
1120   deque < instr_item * > :: iterator last = HUD_deque.end();
1121
1122   for ( ; current != last; ++current ) {
1123       pHUDInstr = *current;
1124
1125       if( pHUDInstr->enabled()) {
1126           //  fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d  Status %d\n",
1127           //            hud->code, hud->status );
1128           pHUDInstr->draw();
1129 //        HUD_deque.at(i)->draw(); // Responsible for broken or fixed variants.
1130                               // No broken displays honored just now.
1131       }
1132   }
1133
1134   char *gmt_str = get_formated_gmt_time();
1135   HUD_TextList.add( fgText( 40, 10, gmt_str) );
1136
1137 #ifdef FG_NETWORK_OLK
1138   if ( net_hud_display ) {
1139       net_hud_update();
1140   }
1141 #endif
1142
1143   HUD_TextList.draw();
1144
1145   line_width = (current_options.get_xsize() > 1000) ? 1.0 : 0.5;
1146   glLineWidth(line_width);
1147   HUD_LineList.draw();
1148
1149 //  glEnable(GL_LINE_STIPPLE);
1150 //  glLineStipple( 1, 0x00FF );
1151 //  HUD_StippleLineList.draw();
1152 //  glDisable(GL_LINE_STIPPLE);
1153
1154 //  glDisable( GL_BLEND );
1155   
1156   glEnable(GL_DEPTH_TEST);
1157   glEnable(GL_LIGHTING);
1158   glMatrixMode(GL_PROJECTION);
1159   glPopMatrix();
1160   glMatrixMode(GL_MODELVIEW);
1161   glPopMatrix();
1162 }
1163 #endif
1164
1165
1166 // fgUpdateHUD
1167 //
1168 // Performs a once around the list of calls to instruments installed in
1169 // the HUD object with requests for redraw. Kinda. It will when this is
1170 // all C++.
1171 //
1172 void fgUpdateHUD( void ) {
1173   int brightness;
1174 //  int day_night_sw = current_aircraft.controls->day_night_switch;
1175   int day_night_sw = global_day_night_switch;
1176   int hud_displays = HUD_deque.size();
1177   instr_item *pHUDInstr;
1178   float line_width;
1179
1180   if( !hud_displays ) {  // Trust everyone, but ALWAYS cut the cards!
1181     return;
1182     }
1183
1184   HUD_TextList.erase();
1185   HUD_LineList.erase();
1186 //  HUD_StippleLineList.erase();
1187   
1188   pHUDInstr = HUD_deque[0];
1189   brightness = pHUDInstr->get_brightness();
1190 //  brightness = HUD_deque.at(0)->get_brightness();
1191
1192   glMatrixMode(GL_PROJECTION);
1193   glPushMatrix();
1194
1195   glLoadIdentity();
1196   gluOrtho2D(0, 640, 0, 480);
1197   glMatrixMode(GL_MODELVIEW);
1198   glPushMatrix();
1199   glLoadIdentity();
1200
1201   glColor3f(1.0, 1.0, 1.0);
1202   glIndexi(7);
1203
1204   glDisable(GL_DEPTH_TEST);
1205   glDisable(GL_LIGHTING);
1206
1207   // We can do translucency, so why not. :-)
1208 //  glEnable    ( GL_BLEND ) ;
1209 //  glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
1210   
1211   if( day_night_sw == DAY) {
1212           switch (brightness) {
1213                   case BRT_LIGHT:
1214 //            glColor4f (0.1, 0.9, 0.1, 0.75);
1215             glColor3f (0.1, 0.9, 0.1);
1216             break;
1217
1218           case BRT_MEDIUM:
1219 //            glColor4f (0.1, 0.7, 0.0, 0.75);
1220             glColor3f (0.1, 0.7, 0.0);
1221             break;
1222
1223           case BRT_DARK:
1224 //            glColor4f (0.0, 0.6, 0.0, 0.75);
1225             glColor3f(0.0, 0.6, 0.0);
1226             break;
1227
1228           case BRT_BLACK:
1229 //            glColor4f( 0.0, 0.0, 0.0, 0.75);
1230             glColor3f( 0.0, 0.0, 0.0);
1231             break;
1232
1233           default:;
1234           }
1235   }
1236   else {
1237           if( day_night_sw == NIGHT) {
1238                   switch (brightness) {
1239                           case BRT_LIGHT:
1240 //                glColor4f (0.9, 0.1, 0.1, 0.75);
1241                 glColor3f (0.9, 0.1, 0.1);
1242                 break;
1243
1244               case BRT_MEDIUM:
1245 //                glColor4f (0.7, 0.0, 0.1, 0.75);
1246                 glColor3f (0.7, 0.0, 0.1);
1247                 break;
1248
1249                           case BRT_DARK:
1250                           default:
1251 //                                glColor4f (0.6, 0.0, 0.0, 0.75);
1252                                   glColor3f (0.6, 0.0, 0.0);
1253                   }
1254           }
1255           else {     // Just in case default
1256 //                        glColor4f (0.1, 0.9, 0.1, 0.75);
1257                           glColor3f (0.1, 0.9, 0.1);
1258                   }
1259   }
1260
1261   deque < instr_item * > :: iterator current = HUD_deque.begin();
1262   deque < instr_item * > :: iterator last = HUD_deque.end();
1263
1264   for ( ; current != last; ++current ) {
1265           pHUDInstr = *current;
1266
1267           if( pHUDInstr->enabled()) {
1268                   //  fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d  Status %d\n",
1269                   //            hud->code, hud->status );
1270                   pHUDInstr->draw();
1271 //            HUD_deque.at(i)->draw(); // Responsible for broken or fixed variants.
1272                               // No broken displays honored just now.
1273           }
1274   }
1275
1276   char *gmt_str = get_formated_gmt_time();
1277   HUD_TextList.add( fgText(40, 10, gmt_str) );
1278
1279 #ifdef FG_NETWORK_OLK
1280   if ( net_hud_display ) {
1281       net_hud_update();
1282   }
1283 #endif
1284
1285
1286   // temporary
1287   extern bool fgAPAltitudeEnabled( void );
1288   extern bool fgAPHeadingEnabled( void );
1289   extern bool fgAPWayPointEnabled( void );
1290   extern char *fgAPget_TargetDistanceStr( void );
1291   extern char *fgAPget_TargetHeadingStr( void );
1292   extern char *fgAPget_TargetAltitudeStr( void );
1293   extern char *fgAPget_TargetLatLonStr( void );
1294
1295   int apY = 480 - 80;
1296 //  char scratch[128];
1297 //  HUD_TextList.add( fgText( "AUTOPILOT", 20, apY) );
1298 //  apY -= 15;
1299   if( fgAPHeadingEnabled() ) {
1300           HUD_TextList.add( fgText( 40, apY, fgAPget_TargetHeadingStr()) );       
1301           apY -= 15;
1302   }
1303   if( fgAPAltitudeEnabled() ) {
1304           HUD_TextList.add( fgText( 40, apY, fgAPget_TargetAltitudeStr()) );      
1305           apY -= 15;
1306   }
1307   if( fgAPWayPointEnabled() ) {
1308           HUD_TextList.add( fgText( 40, apY, fgAPget_TargetLatLonStr()) );
1309           apY -= 15;
1310           HUD_TextList.add( fgText( 40, apY, fgAPget_TargetDistanceStr() ) );     
1311           apY -= 15;
1312   }
1313   
1314   HUD_TextList.draw();
1315
1316   line_width = (current_options.get_xsize() > 1000) ? 1.0 : 0.5;
1317   glLineWidth(line_width);
1318   HUD_LineList.draw();
1319
1320 //  glEnable(GL_LINE_STIPPLE);
1321 //  glLineStipple( 1, 0x00FF );
1322 //  HUD_StippleLineList.draw();
1323 //  glDisable(GL_LINE_STIPPLE);
1324
1325 //  glDisable( GL_BLEND );
1326   
1327   glEnable(GL_DEPTH_TEST);
1328   glEnable(GL_LIGHTING);
1329   glMatrixMode(GL_PROJECTION);
1330   glPopMatrix();
1331   glMatrixMode(GL_MODELVIEW);
1332   glPopMatrix();
1333 }
1334