1 /**************************************************************************
2 * hud.c -- hud defines and prototypes
4 * Written by Michele America, started September 1997.
6 * Copyright (C) 1997 Michele F. America - nomimarketing@mail.telepac.pt
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.
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.
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.
23 * (Log is kept at end of this file)
24 **************************************************************************/
36 # include <values.h> /* for MAXINT */
37 #endif /* not WIN32 */
41 #include <Include/fg_constants.h>
42 #include <Aircraft/aircraft.h>
43 #include <Main/fg_debug.h>
44 #include <Math/fg_random.h>
45 #include <Math/mat3.h>
46 #include <Math/polar.h>
47 #include <Scenery/scenery.h>
48 // #include <Scenery/mesh.h> /* not used any more :-) */
49 #include <Time/fg_timer.h>
50 #include <Weather/weather.h>
54 #define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES); \
55 glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
58 // The following routines obtain information concerntin the aircraft's
59 // current state and return it to calling instrument display routines.
60 // They should eventually be member functions of the aircraft.
63 double get_speed( void )
67 f = current_aircraft.flight;
68 return( FG_V_equiv_kts ); // Make an explicit function call.
71 double get_aoa( void )
75 f = current_aircraft.flight;
76 return( FG_Gamma_vert_rad * RAD_TO_DEG );
79 double get_roll( void )
83 f = current_aircraft.flight;
87 double get_pitch( void )
91 f = current_aircraft.flight;
95 double get_heading( void )
99 f = current_aircraft.flight;
100 return( FG_Psi*RAD_TO_DEG );
103 double get_altitude( void )
106 // double rough_elev;
108 f = current_aircraft.flight;
109 // rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
110 // FG_Latitude * RAD_TO_ARCSEC);
112 return( FG_Altitude * FEET_TO_METER /* -rough_elev */ );
116 // The following code deals with painting the "instrument" on the display
118 /* textString - Bitmap font string */
120 static void textString(int x, int y, char *msg, void *font)
124 glutBitmapCharacter(font, *msg);
129 /* strokeString - Stroke font string */
131 static void strokeString(int x, int y, char *msg, void *font)
134 glTranslatef(x, y, 0);
135 glScalef(.04, .04, .04);
137 glutStrokeCharacter(font, *msg);
146 Draws a measuring scale anywhere on the HUD
149 Needs: HUD_scale struct
152 static void drawscale( HUD_scale * pscale )
162 double cur_value = (*(pscale->load_value))();
164 vmin = cur_value - pscale->maximum_value / 2;
165 vmax = cur_value + pscale->maximum_value / 2;
167 mid_scr = pscale->scr_min+(pscale->scr_max-pscale->scr_min)/2;
169 if( pscale->type == VERTICAL ) // Vertical scale
171 if( pscale->orientation == LEFT )
172 marker_x = pscale->scr_pos-6;
174 if( pscale->orientation == RIGHT )
175 marker_x = pscale->scr_pos;
176 drawOneLine( pscale->scr_pos,
180 if( pscale->orientation == LEFT )
182 drawOneLine( pscale->scr_pos-3,
187 drawOneLine( pscale->scr_pos-3,
192 drawOneLine( pscale->scr_pos,
199 if( pscale->orientation == RIGHT )
201 drawOneLine( pscale->scr_pos,
206 drawOneLine( pscale->scr_pos,
211 drawOneLine( pscale->scr_pos,
217 factor = (pscale->scr_max - pscale->scr_min)/pscale->maximum_value;
219 for( i=vmin; i<=vmax; i+=1 )
221 if( pscale->sub_type == LIMIT )
222 condition = i>= pscale->minimum_value;
224 if( pscale->sub_type == NOLIMIT )
229 marker_y = pscale->scr_min+(i-vmin)*factor;
230 if( i%pscale->div_min==0 )
231 if( pscale->orientation == LEFT )
233 drawOneLine( marker_x+3, marker_y, marker_x+6, marker_y );
236 if( pscale->orientation == RIGHT )
238 drawOneLine( marker_x, marker_y, marker_x+3, marker_y );
240 if( i%pscale->div_max==0 )
242 drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
243 sprintf( TextScale, "%d", i );
244 if( pscale->orientation == LEFT )
246 textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
247 TextScale, GLUT_BITMAP_8_BY_13 );
250 if( pscale->orientation == RIGHT )
252 textString( marker_x+10, marker_y-4,
253 TextScale, GLUT_BITMAP_8_BY_13 );
257 } // End for range of i from vmin to vmax
259 if( pscale->type == HORIZONTAL ) // Horizontal scale
261 if( pscale->orientation == TOP )
262 marker_y = pscale->scr_pos;
264 if( pscale->orientation == BOTTOM )
265 marker_y = pscale->scr_pos-6;
266 drawOneLine( pscale->scr_min,
270 if( pscale->orientation == TOP )
272 drawOneLine( pscale->scr_min,
277 drawOneLine( pscale->scr_max,
282 drawOneLine( mid_scr,
289 if( pscale->orientation == BOTTOM )
291 drawOneLine( pscale->scr_min,
296 drawOneLine( pscale->scr_max,
301 drawOneLine( mid_scr,
307 factor = (pscale->scr_max - pscale->scr_min)/pscale->maximum_value;
309 for( i=vmin; i<=vmax; i+=1 )
311 if( pscale->sub_type == LIMIT )
312 condition = i>= pscale->minimum_value;
314 if( pscale->sub_type == NOLIMIT )
319 marker_x = pscale->scr_min+(i-vmin)*factor;
320 if( i%pscale->div_min==0 )
321 if( pscale->orientation == TOP )
323 drawOneLine( marker_x, marker_y, marker_x, marker_y+3 );
326 if( pscale->orientation == BOTTOM )
328 drawOneLine( marker_x, marker_y+3, marker_x, marker_y+6 );
330 if( i%pscale->div_max==0 )
332 sprintf( TextScale, "%d", i );
333 if( pscale->orientation == TOP )
335 drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
336 textString ( marker_x-4*strlen(TextScale), marker_y+14,
337 TextScale, GLUT_BITMAP_8_BY_13 );
340 if( pscale->orientation == BOTTOM )
342 drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
343 textString ( marker_x+10, marker_y-4,
344 TextScale, GLUT_BITMAP_8_BY_13 );
355 Draws a climb ladder in the center of the HUD
359 static void drawladder( HUD_ladder *ladder )
362 double roll_value, pitch_value;
363 int marker_x, marker_y;
367 int scr_min, scr_max;
370 int new_x_ini, new_x_end;
371 int new_y_ini, new_y_end;
377 roll_value = (*ladder->load_roll)();
378 pitch_value = (*ladder->load_pitch)()*RAD_TO_DEG;
380 vmin = pitch_value - ladder->width_units/2;
381 vmax = pitch_value + ladder->width_units/2;
383 scr_min = ladder->y_pos - (ladder->scr_height/2);
384 scr_max = scr_min + ladder->scr_height;
387 mid_scr = scr_min + (scr_max-scr_min)/2;
390 marker_x = ladder->x_pos - ladder->scr_width/2;
392 factor = (scr_max-scr_min)/ladder->width_units;
394 for( i=vmin; i<=vmax; i+=1 )
399 marker_y = scr_min+(i-vmin)*factor;
400 if( i%ladder->div_units==0 )
402 sprintf( TextLadder, "%d", i );
403 if( ladder->scr_hole == 0 )
406 x_ini = ladder->x_pos - ladder->scr_width/2;
408 x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
410 x_end = ladder->x_pos + ladder->scr_width/2;
412 new_x_ini = ladder->x_pos + \
413 (x_ini - ladder->x_pos) * cos(roll_value) - \
414 (y_ini - ladder->y_pos) * sin(roll_value);
415 new_y_ini = ladder->y_pos + \
416 (x_ini - ladder->x_pos) * sin(roll_value) + \
417 (y_ini - ladder->y_pos) * cos(roll_value);
418 new_x_end = ladder->x_pos + \
419 (x_end - ladder->x_pos) * cos(roll_value) - \
420 (y_end - ladder->y_pos) * sin(roll_value);
421 new_y_end = ladder->y_pos + \
422 (x_end - ladder->x_pos) * sin(roll_value) + \
423 (y_end - ladder->y_pos) * cos(roll_value);
427 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
431 glEnable(GL_LINE_STIPPLE);
432 glLineStipple( 1, 0x00FF );
433 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
434 glDisable(GL_LINE_STIPPLE);
436 textString( new_x_ini - 8 * strlen(TextLadder) - 8,
438 TextLadder, GLUT_BITMAP_8_BY_13 );
439 textString( new_x_end + 10,
441 TextLadder, GLUT_BITMAP_8_BY_13 );
446 x_ini = ladder->x_pos - ladder->scr_width/2;
448 x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
450 x_end = ladder->x_pos - ladder->scr_width/2 + ladder->scr_hole/2;
452 new_x_ini = ladder->x_pos+ \
453 (x_ini - ladder->x_pos) * cos(roll_value) -\
454 (y_ini - ladder->y_pos) * sin(roll_value);
455 new_y_ini = ladder->y_pos+ \
456 (x_ini - ladder->x_pos) * sin(roll_value) +\
457 (y_ini - ladder->y_pos) * cos(roll_value);
458 new_x_end = ladder->x_pos+ \
459 (x_end - ladder->x_pos) * cos(roll_value) -\
460 (y_end - ladder->y_pos) * sin(roll_value);
461 new_y_end = ladder->y_pos+ \
462 (x_end - ladder->x_pos) * sin(roll_value) +\
463 (y_end - ladder->y_pos) * cos(roll_value);
467 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
471 glEnable(GL_LINE_STIPPLE);
472 glLineStipple( 1, 0x00FF );
473 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
474 glDisable(GL_LINE_STIPPLE);
476 textString( new_x_ini - 8 * strlen(TextLadder) - 8,
478 TextLadder, GLUT_BITMAP_8_BY_13 );
480 x_ini = ladder->x_pos + ladder->scr_width/2 - ladder->scr_hole/2;
483 x_end = ladder->x_pos + ladder->scr_width/2;
485 x_end = ladder->x_pos + ladder->scr_width/2 + 10;
487 new_x_ini = ladder->x_pos + \
488 (x_ini-ladder->x_pos)*cos(roll_value) -\
489 (y_ini-ladder->y_pos)*sin(roll_value);
490 new_y_ini = ladder->y_pos + \
491 (x_ini-ladder->x_pos)*sin(roll_value) +\
492 (y_ini-ladder->y_pos)*cos(roll_value);
493 new_x_end = ladder->x_pos + \
494 (x_end-ladder->x_pos)*cos(roll_value) -\
495 (y_end-ladder->y_pos)*sin(roll_value);
496 new_y_end = ladder->y_pos + \
497 (x_end-ladder->x_pos)*sin(roll_value) +\
498 (y_end-ladder->y_pos)*cos(roll_value);
502 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
506 glEnable(GL_LINE_STIPPLE);
507 glLineStipple( 1, 0x00FF );
508 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
509 glDisable(GL_LINE_STIPPLE);
511 textString( new_x_end+10, new_y_end-4,
512 TextLadder, GLUT_BITMAP_8_BY_13 );
515 /* if( i%pscale->div_max==0 )
517 drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
518 sprintf( TextScale, "%d", i );
519 if( pscale->orientation == LEFT )
521 textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
522 TextScale, GLUT_BITMAP_8_BY_13 );
524 else if( pscale->orientation == RIGHT )
526 textString( marker_x+10, marker_y-4,
527 TextScale, GLUT_BITMAP_8_BY_13 );
536 // Draws an artificial horizon line in the center of the HUD
537 // (with or without a center hole)
539 // Needs: x_center, y_center, length, hole
542 static void drawhorizon( HUD_horizon *horizon )
546 // struct fgFLIGHT *f = ¤t_aircraft.flight;
547 double sin_bank, cos_bank;
550 bank_angle = (*horizon->load_value)();
552 // sin_bank = sin( FG_2PI-FG_Phi );
553 // cos_bank = cos( FG_2PI-FG_Phi );
554 sin_bank = sin(FG_2PI-bank_angle);
555 cos_bank = cos(FG_2PI-bank_angle);
556 x_inc1 = (int)(horizon->scr_width * cos_bank);
557 y_inc1 = (int)(horizon->scr_width * sin_bank);
558 x_inc2 = (int)(horizon->scr_hole * cos_bank);
559 y_inc2 = (int)(horizon->scr_hole * sin_bank);
561 if( horizon->scr_hole == 0 )
563 drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
564 horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
568 drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
569 horizon->x_pos - x_inc2, horizon->y_pos - y_inc2 );
570 drawOneLine( horizon->x_pos + x_inc2, horizon->y_pos + y_inc2, \
571 horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
576 Draws a representation of the control surfaces in their current state
579 Needs: struct HUD_control_surfaces
582 static void drawControlSurfaces( HUD_control_surfaces *ctrl_surf )
590 x_ini = ctrl_surf->x_pos;
591 y_ini = ctrl_surf->y_pos;
595 drawOneLine( x_ini, y_ini, x_end, y_ini );
596 drawOneLine( x_ini, y_ini, x_ini, y_end );
597 drawOneLine( x_ini, y_end, x_end, y_end );
598 drawOneLine( x_end, y_end, x_end, y_ini );
599 drawOneLine( x_ini + 30, y_ini, x_ini + 30, y_end );
600 drawOneLine( x_ini + 30, y_ini + 30, x_ini + 90, y_ini + 30 );
601 drawOneLine( x_ini + 90, y_ini, x_ini + 90, y_end );
602 drawOneLine( x_ini + 120, y_ini, x_ini + 120, y_end );
604 c = current_aircraft.controls;
606 /* Draw elevator diagram */
607 textString( x_ini + 1, y_end-11, "E", GLUT_BITMAP_8_BY_13 );
608 drawOneLine( x_ini + 15, y_ini + 5, x_ini + 15, y_ini + 55 );
609 drawOneLine( x_ini + 14, y_ini + 30, x_ini + 16, y_ini + 30 );
610 if( FG_Elevator <= -0.01 || FG_Elevator >= 0.01 )
612 drawOneLine( x_ini + 10, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0), \
613 x_ini + 20, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0) );
617 drawOneLine( x_ini + 7, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0), \
618 x_ini + 23, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0) );
621 /* Draw aileron diagram */
622 textString( x_ini + 30 + 1, y_end-11, "A", GLUT_BITMAP_8_BY_13 );
623 drawOneLine( x_ini + 35, y_end-15, x_ini + 85, y_end-15 );
624 drawOneLine( x_ini + 60, y_end-14, x_ini + 60, y_end-16 );
625 if( FG_Aileron <= -0.01 || FG_Aileron >= 0.01 )
627 drawOneLine( x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-20, \
628 x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-10 );
632 drawOneLine( x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-25, \
633 x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-5 );
636 /* Draw rudder diagram */
637 textString( x_ini + 30 + 1, y_ini + 21, "R", GLUT_BITMAP_8_BY_13 );
638 drawOneLine( x_ini + 35, y_ini + 15, x_ini + 85, y_ini + 15 );
639 drawOneLine( x_ini + 60, y_ini + 14, x_ini + 60, y_ini + 16 );
640 if( FG_Rudder <= -0.01 || FG_Rudder >= 0.01 )
642 drawOneLine( x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 20, \
643 x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 10 );
647 drawOneLine( x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 25, \
648 x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 5 );
652 /* Draw throttle diagram */
653 textString( x_ini + 90 + 1, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
654 textString( x_ini + 90 + 1, y_end-21, "r", GLUT_BITMAP_8_BY_13 );
655 drawOneLine( x_ini + 105, y_ini + 5, x_ini + 105, y_ini + 55 );
656 drawOneLine( x_ini + 100, y_ini + 5 + (int)(FG_Throttle[0]*50.0), \
657 x_ini + 110, y_ini + 5 + (int)(FG_Throttle[0]*50.0) );
660 /* Draw elevator trim diagram */
661 textString( x_ini + 121, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
662 textString( x_ini + 121, y_end-22, "m", GLUT_BITMAP_8_BY_13 );
663 drawOneLine( x_ini + 135, y_ini + 5, x_ini + 135, y_ini + 55 );
664 drawOneLine( x_ini + 134, y_ini + 30, x_ini + 136, y_ini + 30 );
665 if( FG_Elev_Trim <= -0.01 || FG_Elev_Trim >= 0.01 )
667 drawOneLine( x_ini + 130, y_ini + 5 + (int)(((FG_Elev_Trim + 1)/2)*50.0), \
668 x_ini + 140, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0) );
672 drawOneLine( x_ini + 127, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0), \
673 x_ini + 143, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0) );
679 // Draws a label anywhere in the HUD
683 static void drawlabel( HUD_label *label )
690 if( !label ) { // Eliminate the possible, but absurd case.
694 if( label->pre_str != NULL) {
695 if( label->post_str != NULL ) {
696 sprintf( buffer, "%s%s%s", label->pre_str, \
701 sprintf( buffer, "%s%s", label->pre_str, \
706 if( label->post_str != NULL ) {
707 sprintf( buffer, "%s%s", label->format, \
710 } // else do nothing if both pre and post strings are nulls. Interesting.
713 sprintf( string, buffer, (*label->load_value)() );
715 fgPrintf( FG_COCKPIT, FG_DEBUG, buffer );
716 fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
717 fgPrintf( FG_COCKPIT, FG_DEBUG, string );
718 fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
720 lenstr = strlen( string );
721 if( label->justify == LEFT_JUST ) {
725 if( label->justify == CENTER_JUST ) {
729 if( label->justify == RIGHT_JUST ) {
735 if( label->size == SMALL ) {
736 textString( label->x_pos + posincr, label->y_pos,
737 string, GLUT_BITMAP_8_BY_13);
740 if( label->size == LARGE ) {
741 textString( label->x_pos + posincr, label->y_pos,
742 string, GLUT_BITMAP_9_BY_15);
746 // The following routines concern HUD object/component object construction
751 // Constructs a HUD object and then adds in instruments. At the present
752 // the instruments are hard coded into the routine. Ultimately these need
753 // to be defined by the aircraft's instrumentation records so that the
754 // display for a Piper Cub doesn't show the speed range of a North American
755 // mustange and the engine readouts of a B36!
757 Hptr fgHUDInit( fgAIRCRAFT *current_aircraft )
761 hud = (Hptr)calloc(sizeof( HUD),1);
768 // For now lets just hardcode the hud here .
769 // In the future, hud information has to come from the same place
770 // aircraft information came from.
772 fgHUDAddHorizon( hud, 590, 50, 40, 20, get_roll );
773 fgHUDAddScale ( hud, VERTICAL, NOLIMIT, 220, 100, 280, 5, 10,
774 LEFT, LEFT, 0, 100, get_speed );
775 fgHUDAddScale ( hud, VERTICAL, NOLIMIT, 440, 100, 280, 1, 5,
776 RIGHT, RIGHT, -400, 25, get_aoa );
777 fgHUDAddScale ( hud, HORIZONTAL, NOLIMIT, 280, 220, 440, 5, 10,
778 TOP, TOP, 0, 50, get_heading );
779 fgHUDAddLabel ( hud, 180, 85, SMALL, NOBLINK,
780 RIGHT_JUST, NULL, " Kts", "%5.0f", get_speed );
781 fgHUDAddLabel ( hud, 180, 73, SMALL, NOBLINK,
782 RIGHT_JUST, NULL, " m", "%5.0f", get_altitude );
783 fgHUDAddLadder ( hud, 330, 190, 90, 180, 70, 10,
784 NONE, 45, get_roll, get_pitch );
785 // fgHUDAddControlSurfaces( hud, 10, 10, get_heading );
792 // This is a stand in for linked list code that will get replaced later
793 // by some more elegant list handling code.
795 void add_instrument( Hptr hud, HIptr pinstrument )
797 if( !hud || !pinstrument ) {
800 pinstrument->next = hud->instruments;
801 hud->instruments = pinstrument;
806 // Constructs a HUD_horizon "object" and installs it into the hud instrument
809 Hptr fgHUDAddHorizon( Hptr hud, \
814 double (*load_value)() )
816 HUD_horizon *phorizon;
817 HUD_instr *pinstrument;
822 // construct the parent object
823 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
824 if( pinstrument == NULL ) {
827 pinstrument->type = HUDhorizon; // ARTIFICIAL_HORIZON;
829 // Construct the horizon
830 phorizon = (HUD_horizon *) calloc( sizeof(HUD_horizon),1);
831 if( phorizon == NULL ) {
835 phorizon->x_pos = x_pos;
836 phorizon->y_pos = y_pos;
837 phorizon->scr_width = length;
838 phorizon->scr_hole = hole_len;
839 phorizon->load_value = load_value;
840 // Install the horizon in the parent.
841 pinstrument->instr = phorizon;
842 // Install the instrument into hud.
843 add_instrument( hud, pinstrument);
850 // Constructs a HUD_scale "object" and installs it into the hud instrument
853 Hptr fgHUDAddScale( Hptr hud, \
865 double (*load_value)() )
868 HUD_instr *pinstrument;
874 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
875 if( pinstrument == NULL ) {
879 pinstrument->type = SCALE;
881 pscale = ( HUD_scale *)calloc(sizeof(HUD_scale),1);
882 if( pscale == NULL ) {
886 pscale->type = sub_type;
887 pscale->scr_pos = scr_pos;
888 pscale->scr_min = scr_min;
889 pscale->scr_max = scr_max;
890 pscale->div_min = div_min;
891 pscale->div_max = div_max;
892 pscale->orientation = orientation;
893 pscale->with_minimum = with_min;
894 pscale->minimum_value = min_value;
895 pscale->width_units = width_units;
896 pscale->load_value = load_value;
898 pinstrument->instr = pscale;
899 // Install the instrument into hud.
900 add_instrument( hud, pinstrument);
907 // Constructs a HUD_Label object and installs it into the hud instrument
909 Hptr fgHUDAddLabel( Hptr hud, \
918 double (*load_value)() )
921 HUD_instr *pinstrument;
927 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
928 if( pinstrument == NULL ) {
931 pinstrument->type = LABEL;
933 plabel = (HUD_label *)calloc(sizeof(HUD_label),1);
934 if( plabel == NULL ){
938 plabel->x_pos = x_pos;
939 plabel->y_pos = y_pos;
941 plabel->blink = blink;
942 plabel->justify = justify;
943 plabel->pre_str = pre_str;
944 plabel->post_str = post_str;
945 plabel->format = format;
946 plabel->load_value = load_value;
948 pinstrument->instr = plabel;
949 // Install the instrument into hud.
950 add_instrument( hud, pinstrument);
957 // Contains code that constructs a ladder "object" and installs it as
958 // a hud instrument in the hud instrument list.
960 Hptr fgHUDAddLadder( Hptr hud, \
969 double (*load_roll)(),
970 double (*load_pitch)() )
973 HUD_instr *pinstrument;
979 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
980 if( pinstrument == NULL )
983 pinstrument->type = LADDER;
985 pladder = (HUD_ladder *)calloc(sizeof(HUD_ladder),1);
986 if( pladder == NULL )
989 pladder->type = 0; // Not used.
990 pladder->x_pos = x_pos;
991 pladder->y_pos = y_pos;
992 pladder->scr_width = scr_width;
993 pladder->scr_height = scr_height;
994 pladder->scr_hole = hole_len;
995 pladder->div_units = div_units;
996 pladder->label_position = label_pos;
997 pladder->width_units = width_units;
998 pladder->load_roll = load_roll;
999 pladder->load_pitch = load_pitch;
1001 pinstrument->instr = pladder;
1002 // Install the instrument into hud.
1003 add_instrument( hud, pinstrument);
1008 Hptr fgHUDAddMovingHorizon( Hptr hud, \
1018 Hptr fgHUDAddCircularLadder( Hptr hud, \
1028 Hptr fgHUDAddNumDisp( Hptr hud, \
1043 // Performs a once around the list of calls to instruments installed in
1044 // the HUD object with requests for redraw. Kinda. It will when this is
1048 void fgUpdateHUD( Hptr hud )
1052 glMatrixMode(GL_PROJECTION);
1056 gluOrtho2D(0, 640, 0, 480);
1057 glMatrixMode(GL_MODELVIEW);
1061 glColor3f(1.0, 1.0, 1.0);
1064 glDisable(GL_DEPTH_TEST);
1065 glDisable(GL_LIGHTING);
1068 glColor3f (0.1, 0.9, 0.1);
1070 fgPrintf( FG_COCKPIT, FG_DEBUG,
1071 "HUD Code %d Status %d\n",
1072 hud->code, hud->status );
1074 phud_instr = hud->instruments;
1075 while( phud_instr ) {
1076 switch (phud_instr->type){
1077 case HUDhorizon: // ARTIFICIAL HORIZON
1078 drawhorizon( (pHUDhorizon)phud_instr );
1081 case HUDscale: // Need to simplify this call.
1082 drawscale ( (pHUDscale) phud_instr );
1086 drawlabel ( (pHUDlabel) phud_instr );
1090 drawladder( (pHUDladder) phud_instr );
1094 drawControlSurfaces( (pHUDControlSurface) phud_instr );
1095 default:; // Ignore anything you don't know about.
1097 phud_instr = phud_instr->next;
1100 glEnable(GL_DEPTH_TEST);
1101 glEnable(GL_LIGHTING);
1102 glMatrixMode(GL_PROJECTION);
1104 glMatrixMode(GL_MODELVIEW);
1111 /* Revision 1.11 1998/02/07 15:29:34 curt
1112 /* Incorporated HUD changes and struct/typedef changes from Charlie Hotchkiss
1113 /* <chotchkiss@namg.us.anritsu.com>
1115 * Revision 1.10 1998/02/03 23:20:14 curt
1116 * Lots of little tweaks to fix various consistency problems discovered by
1117 * Solaris' CC. Fixed a bug in fg_debug.c with how the fgPrintf() wrapper
1118 * passed arguments along to the real printf(). Also incorporated HUD changes
1119 * by Michele America.
1121 * Revision 1.9 1998/01/31 00:43:04 curt
1122 * Added MetroWorks patches from Carmen Volpe.
1124 * Revision 1.8 1998/01/27 00:47:51 curt
1125 * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
1126 * system and commandline/config file processing code.
1128 * Revision 1.7 1998/01/19 18:40:20 curt
1129 * Tons of little changes to clean up the code and to remove fatal errors
1130 * when building with the c++ compiler.
1132 * Revision 1.6 1997/12/15 23:54:34 curt
1133 * Add xgl wrappers for debugging.
1134 * Generate terrain normals on the fly.
1136 * Revision 1.5 1997/12/10 22:37:39 curt
1137 * Prepended "fg" on the name of all global structures that didn't have it yet.
1138 * i.e. "struct WEATHER {}" became "struct fgWEATHER {}"
1140 * Revision 1.4 1997/09/23 00:29:32 curt
1141 * Tweaks to get things to compile with gcc-win32.
1143 * Revision 1.3 1997/09/05 14:17:26 curt
1144 * More tweaking with stars.
1146 * Revision 1.2 1997/09/04 02:17:30 curt
1149 * Revision 1.1 1997/08/29 18:03:22 curt