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
41 #include <Include/fg_constants.h>
42 #include <Aircraft/aircraft.h>
43 #include <Main/fg_debug.h>
44 #include <Math/fg_random.h>
45 #include <Math/mat3.h>
46 #include <Math/polar.h>
47 #include <Scenery/scenery.h>
48 #include <Time/fg_timer.h>
49 #include <Weather/weather.h>
53 #define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES); \
54 glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
57 // The following routines obtain information concerntin the aircraft's
58 // current state and return it to calling instrument display routines.
59 // They should eventually be member functions of the aircraft.
62 double get_speed( void )
66 f = current_aircraft.flight;
67 return( FG_V_equiv_kts ); // Make an explicit function call.
70 double get_aoa( void )
74 f = current_aircraft.flight;
75 return( FG_Gamma_vert_rad * RAD_TO_DEG );
78 double get_roll( void )
82 f = current_aircraft.flight;
86 double get_pitch( void )
90 f = current_aircraft.flight;
94 double get_heading( void )
98 f = current_aircraft.flight;
99 return( FG_Psi*RAD_TO_DEG );
102 double get_altitude( void )
105 // double rough_elev;
107 f = current_aircraft.flight;
108 // rough_elev = mesh_altitude(FG_Longitude * RAD_TO_ARCSEC,
109 // FG_Latitude * RAD_TO_ARCSEC);
111 return( FG_Altitude * FEET_TO_METER /* -rough_elev */ );
115 // The following code deals with painting the "instrument" on the display
117 /* textString - Bitmap font string */
119 static void textString(int x, int y, char *msg, void *font)
123 glutBitmapCharacter(font, *msg);
128 /* strokeString - Stroke font string */
130 static void strokeString(int x, int y, char *msg, void *font)
133 glTranslatef(x, y, 0);
134 glScalef(.04, .04, .04);
136 glutStrokeCharacter(font, *msg);
145 Draws a measuring scale anywhere on the HUD
148 Needs: HUD_scale struct
151 static void drawscale( HUD_scale * pscale )
161 double cur_value = (*(pscale->load_value))();
163 vmin = cur_value - pscale->width_units / 2;
164 vmax = cur_value + pscale->width_units / 2;
166 mid_scr = pscale->scr_min+(pscale->scr_max-pscale->scr_min)/2;
168 if( pscale->type == VERTICAL ) // Vertical scale
170 if( pscale->orientation == LEFT )
171 marker_x = pscale->scr_pos-6;
173 if( pscale->orientation == RIGHT )
174 marker_x = pscale->scr_pos;
175 drawOneLine( pscale->scr_pos,
179 if( pscale->orientation == LEFT )
181 drawOneLine( pscale->scr_pos-3,
186 drawOneLine( pscale->scr_pos-3,
191 drawOneLine( pscale->scr_pos,
198 if( pscale->orientation == RIGHT )
200 drawOneLine( pscale->scr_pos,
205 drawOneLine( pscale->scr_pos,
210 drawOneLine( pscale->scr_pos,
216 factor = (pscale->scr_max - pscale->scr_min)/pscale->width_units;
218 for( i = vmin; i <= vmax; i++ )
220 if( pscale->sub_type == LIMIT ) {
221 condition = (i >= pscale->minimum_value);
224 if( pscale->sub_type == NOLIMIT ) {
230 marker_y = pscale->scr_min + (i - vmin) * factor;
231 if( !(i%pscale->div_min)) {
232 if( pscale->orientation == LEFT )
234 drawOneLine( marker_x + 3, marker_y, marker_x + 6, marker_y );
237 if( pscale->orientation == RIGHT )
239 drawOneLine( marker_x, marker_y, marker_x + 3, marker_y );
241 if( i%pscale->div_max==0 )
243 drawOneLine( marker_x, marker_y, marker_x + 6, marker_y );
244 sprintf( TextScale, "%d", i );
245 if( pscale->orientation == LEFT )
247 textString( marker_x - 8 * strlen(TextScale) - 2, marker_y - 4,
248 TextScale, GLUT_BITMAP_8_BY_13 );
251 if( pscale->orientation == RIGHT )
253 textString( marker_x+10, marker_y-4,
254 TextScale, GLUT_BITMAP_8_BY_13 );
261 } // End for range of i from vmin to vmax
263 if( pscale->type == HORIZONTAL ) // Horizontal scale
265 if( pscale->orientation == TOP ) {
266 marker_y = pscale->scr_pos;
269 if( pscale->orientation == BOTTOM ) {
270 marker_y = pscale->scr_pos - 6;
273 drawOneLine( pscale->scr_min,
277 if( pscale->orientation == TOP )
279 drawOneLine( pscale->scr_min,
284 drawOneLine( pscale->scr_max,
289 drawOneLine( mid_scr,
296 if( pscale->orientation == BOTTOM )
298 drawOneLine( pscale->scr_min,
303 drawOneLine( pscale->scr_max,
308 drawOneLine( mid_scr,
314 factor = (pscale->scr_max - pscale->scr_min)/pscale->width_units;
316 for( i = vmin; i <= vmax; i++ ) // increment is faster than addition
318 if( pscale->sub_type == LIMIT ) {
319 condition = (i >= pscale->minimum_value);
322 if( pscale->sub_type == NOLIMIT ) {
328 marker_x = pscale->scr_min+(i-vmin)*factor;
329 if( i%pscale->div_min==0 ) {
330 if( pscale->orientation == TOP )
332 drawOneLine( marker_x, marker_y, marker_x, marker_y+3 );
335 if( pscale->orientation == BOTTOM )
337 drawOneLine( marker_x, marker_y+3, marker_x, marker_y+6 );
341 if( i%pscale->div_max==0 )
343 sprintf( TextScale, "%d", i );
344 if( pscale->orientation == TOP )
346 drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
347 textString ( marker_x-4*strlen(TextScale), marker_y+14,
348 TextScale, GLUT_BITMAP_8_BY_13 );
351 if( pscale->orientation == BOTTOM )
353 drawOneLine( marker_x, marker_y, marker_x, marker_y+6 );
354 textString ( marker_x+10, marker_y-4,
355 TextScale, GLUT_BITMAP_8_BY_13 );
366 // Draws a climb ladder in the center of the HUD
369 static void drawladder( HUD_ladder *ladder )
372 double roll_value, pitch_value;
373 int marker_x, marker_y;
377 int scr_min, scr_max;
380 int new_x_ini, new_x_end;
381 int new_y_ini, new_y_end;
387 roll_value = (*ladder->load_roll)();
388 pitch_value = (*ladder->load_pitch)()*RAD_TO_DEG;
390 vmin = pitch_value - ladder->width_units/2;
391 vmax = pitch_value + ladder->width_units/2;
393 scr_min = ladder->y_pos - (ladder->scr_height/2);
394 scr_max = scr_min + ladder->scr_height;
397 mid_scr = scr_min + (scr_max-scr_min)/2;
400 marker_x = ladder->x_pos - ladder->scr_width/2;
402 factor = (scr_max-scr_min)/ladder->width_units;
404 for( i=vmin; i<=vmax; i+=1 )
409 marker_y = scr_min+(i-vmin)*factor;
410 if( i%ladder->div_units==0 )
412 sprintf( TextLadder, "%d", i );
413 if( ladder->scr_hole == 0 )
416 x_ini = ladder->x_pos - ladder->scr_width/2;
419 x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
422 x_end = ladder->x_pos + ladder->scr_width/2;
424 new_x_ini = ladder->x_pos + \
425 (x_ini - ladder->x_pos) * cos(roll_value) - \
426 (y_ini - ladder->y_pos) * sin(roll_value);
427 new_y_ini = ladder->y_pos + \
428 (x_ini - ladder->x_pos) * sin(roll_value) + \
429 (y_ini - ladder->y_pos) * cos(roll_value);
430 new_x_end = ladder->x_pos + \
431 (x_end - ladder->x_pos) * cos(roll_value) - \
432 (y_end - ladder->y_pos) * sin(roll_value);
433 new_y_end = ladder->y_pos + \
434 (x_end - ladder->x_pos) * sin(roll_value) + \
435 (y_end - ladder->y_pos) * cos(roll_value);
439 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
443 glEnable(GL_LINE_STIPPLE);
444 glLineStipple( 1, 0x00FF );
445 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
446 glDisable(GL_LINE_STIPPLE);
448 textString( new_x_ini - 8 * strlen(TextLadder) - 8,
450 TextLadder, GLUT_BITMAP_8_BY_13 );
451 textString( new_x_end + 10,
453 TextLadder, GLUT_BITMAP_8_BY_13 );
458 x_ini = ladder->x_pos - ladder->scr_width/2;
461 x_ini = ladder->x_pos - ladder->scr_width/2 - 10;
464 x_end = ladder->x_pos - ladder->scr_width/2 + ladder->scr_hole/2;
466 new_x_ini = ladder->x_pos+ \
467 (x_ini - ladder->x_pos) * cos(roll_value) -\
468 (y_ini - ladder->y_pos) * sin(roll_value);
469 new_y_ini = ladder->y_pos+ \
470 (x_ini - ladder->x_pos) * sin(roll_value) +\
471 (y_ini - ladder->y_pos) * cos(roll_value);
472 new_x_end = ladder->x_pos+ \
473 (x_end - ladder->x_pos) * cos(roll_value) -\
474 (y_end - ladder->y_pos) * sin(roll_value);
475 new_y_end = ladder->y_pos+ \
476 (x_end - ladder->x_pos) * sin(roll_value) +\
477 (y_end - ladder->y_pos) * cos(roll_value);
481 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
485 glEnable(GL_LINE_STIPPLE);
486 glLineStipple( 1, 0x00FF );
487 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
488 glDisable(GL_LINE_STIPPLE);
490 textString( new_x_ini - 8 * strlen(TextLadder) - 8,
492 TextLadder, GLUT_BITMAP_8_BY_13 );
494 x_ini = ladder->x_pos + ladder->scr_width/2 - ladder->scr_hole/2;
497 x_end = ladder->x_pos + ladder->scr_width/2;
500 x_end = ladder->x_pos + ladder->scr_width/2 + 10;
503 new_x_ini = ladder->x_pos + \
504 (x_ini-ladder->x_pos)*cos(roll_value) -\
505 (y_ini-ladder->y_pos)*sin(roll_value);
506 new_y_ini = ladder->y_pos + \
507 (x_ini-ladder->x_pos)*sin(roll_value) +\
508 (y_ini-ladder->y_pos)*cos(roll_value);
509 new_x_end = ladder->x_pos + \
510 (x_end-ladder->x_pos)*cos(roll_value) -\
511 (y_end-ladder->y_pos)*sin(roll_value);
512 new_y_end = ladder->y_pos + \
513 (x_end-ladder->x_pos)*sin(roll_value) +\
514 (y_end-ladder->y_pos)*cos(roll_value);
518 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
522 glEnable(GL_LINE_STIPPLE);
523 glLineStipple( 1, 0x00FF );
524 drawOneLine( new_x_ini, new_y_ini, new_x_end, new_y_end );
525 glDisable(GL_LINE_STIPPLE);
527 textString( new_x_end+10, new_y_end-4,
528 TextLadder, GLUT_BITMAP_8_BY_13 );
531 /* if( i%pscale->div_max==0 )
533 drawOneLine( marker_x, marker_y, marker_x+6, marker_y );
534 sprintf( TextScale, "%d", i );
535 if( pscale->orientation == LEFT )
537 textString( marker_x-8*strlen(TextScale)-2, marker_y-4,
538 TextScale, GLUT_BITMAP_8_BY_13 );
540 else if( pscale->orientation == RIGHT )
542 textString( marker_x+10, marker_y-4,
543 TextScale, GLUT_BITMAP_8_BY_13 );
552 // Draws an artificial horizon line in the center of the HUD
553 // (with or without a center hole)
555 // Needs: x_center, y_center, length, hole
558 static void drawhorizon( HUD_horizon *horizon )
562 // struct fgFLIGHT *f = ¤t_aircraft.flight;
563 double sin_bank, cos_bank;
566 bank_angle = (*horizon->load_value)();
568 // sin_bank = sin( FG_2PI-FG_Phi );
569 // cos_bank = cos( FG_2PI-FG_Phi );
570 sin_bank = sin(FG_2PI-bank_angle);
571 cos_bank = cos(FG_2PI-bank_angle);
572 x_inc1 = (int)(horizon->scr_width * cos_bank);
573 y_inc1 = (int)(horizon->scr_width * sin_bank);
574 x_inc2 = (int)(horizon->scr_hole * cos_bank);
575 y_inc2 = (int)(horizon->scr_hole * sin_bank);
577 if( horizon->scr_hole == 0 )
579 drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
580 horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
584 drawOneLine( horizon->x_pos - x_inc1, horizon->y_pos - y_inc1, \
585 horizon->x_pos - x_inc2, horizon->y_pos - y_inc2 );
586 drawOneLine( horizon->x_pos + x_inc2, horizon->y_pos + y_inc2, \
587 horizon->x_pos + x_inc1, horizon->y_pos + y_inc1 );
591 // drawControlSurfaces()
592 // Draws a representation of the control surfaces in their current state
593 // anywhere in the HUD
596 static void drawControlSurfaces( HUD_control_surfaces *ctrl_surf )
604 x_ini = ctrl_surf->x_pos;
605 y_ini = ctrl_surf->y_pos;
609 drawOneLine( x_ini, y_ini, x_end, y_ini );
610 drawOneLine( x_ini, y_ini, x_ini, y_end );
611 drawOneLine( x_ini, y_end, x_end, y_end );
612 drawOneLine( x_end, y_end, x_end, y_ini );
613 drawOneLine( x_ini + 30, y_ini, x_ini + 30, y_end );
614 drawOneLine( x_ini + 30, y_ini + 30, x_ini + 90, y_ini + 30 );
615 drawOneLine( x_ini + 90, y_ini, x_ini + 90, y_end );
616 drawOneLine( x_ini + 120, y_ini, x_ini + 120, y_end );
618 c = current_aircraft.controls;
620 /* Draw elevator diagram */
621 textString( x_ini + 1, y_end-11, "E", GLUT_BITMAP_8_BY_13 );
622 drawOneLine( x_ini + 15, y_ini + 5, x_ini + 15, y_ini + 55 );
623 drawOneLine( x_ini + 14, y_ini + 30, x_ini + 16, y_ini + 30 );
624 if( FG_Elevator <= -0.01 || FG_Elevator >= 0.01 )
626 drawOneLine( x_ini + 10, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0), \
627 x_ini + 20, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0) );
631 drawOneLine( x_ini + 7, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0), \
632 x_ini + 23, y_ini + 5 + (int)(((FG_Elevator + 1.0)/2)*50.0) );
635 /* Draw aileron diagram */
636 textString( x_ini + 30 + 1, y_end-11, "A", GLUT_BITMAP_8_BY_13 );
637 drawOneLine( x_ini + 35, y_end-15, x_ini + 85, y_end-15 );
638 drawOneLine( x_ini + 60, y_end-14, x_ini + 60, y_end-16 );
639 if( FG_Aileron <= -0.01 || FG_Aileron >= 0.01 )
641 drawOneLine( x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-20, \
642 x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-10 );
646 drawOneLine( x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-25, \
647 x_ini + 35 + (int)(((FG_Aileron + 1.0)/2)*50.0), y_end-5 );
650 /* Draw rudder diagram */
651 textString( x_ini + 30 + 1, y_ini + 21, "R", GLUT_BITMAP_8_BY_13 );
652 drawOneLine( x_ini + 35, y_ini + 15, x_ini + 85, y_ini + 15 );
653 drawOneLine( x_ini + 60, y_ini + 14, x_ini + 60, y_ini + 16 );
654 if( FG_Rudder <= -0.01 || FG_Rudder >= 0.01 )
656 drawOneLine( x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 20, \
657 x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 10 );
661 drawOneLine( x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 25, \
662 x_ini + 35 + (int)(((FG_Rudder + 1.0)/2)*50.0), y_ini + 5 );
666 /* Draw throttle diagram */
667 textString( x_ini + 90 + 1, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
668 textString( x_ini + 90 + 1, y_end-21, "r", GLUT_BITMAP_8_BY_13 );
669 drawOneLine( x_ini + 105, y_ini + 5, x_ini + 105, y_ini + 55 );
670 drawOneLine( x_ini + 100, y_ini + 5 + (int)(FG_Throttle[0]*50.0), \
671 x_ini + 110, y_ini + 5 + (int)(FG_Throttle[0]*50.0) );
674 /* Draw elevator trim diagram */
675 textString( x_ini + 121, y_end-11, "T", GLUT_BITMAP_8_BY_13 );
676 textString( x_ini + 121, y_end-22, "m", GLUT_BITMAP_8_BY_13 );
677 drawOneLine( x_ini + 135, y_ini + 5, x_ini + 135, y_ini + 55 );
678 drawOneLine( x_ini + 134, y_ini + 30, x_ini + 136, y_ini + 30 );
679 if( FG_Elev_Trim <= -0.01 || FG_Elev_Trim >= 0.01 )
681 drawOneLine( x_ini + 130, y_ini + 5 + (int)(((FG_Elev_Trim + 1)/2)*50.0), \
682 x_ini + 140, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0) );
686 drawOneLine( x_ini + 127, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0), \
687 x_ini + 143, y_ini + 5 + (int)(((FG_Elev_Trim + 1.0)/2)*50.0) );
693 // Draws a label anywhere in the HUD
697 static void drawlabel( HUD_label *label )
704 if( !label ) { // Eliminate the possible, but absurd case.
708 if( label->pre_str != NULL) {
709 if( label->post_str != NULL ) {
710 sprintf( buffer, "%s%s%s", label->pre_str, \
715 sprintf( buffer, "%s%s", label->pre_str, \
720 if( label->post_str != NULL ) {
721 sprintf( buffer, "%s%s", label->format, \
724 } // else do nothing if both pre and post strings are nulls. Interesting.
727 sprintf( string, buffer, (*label->load_value)() );
729 fgPrintf( FG_COCKPIT, FG_DEBUG, buffer );
730 fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
731 fgPrintf( FG_COCKPIT, FG_DEBUG, string );
732 fgPrintf( FG_COCKPIT, FG_DEBUG, "\n" );
734 lenstr = strlen( string );
735 if( label->justify == LEFT_JUST ) {
739 if( label->justify == CENTER_JUST ) {
743 if( label->justify == RIGHT_JUST ) {
749 if( label->size == SMALL ) {
750 textString( label->x_pos + posincr, label->y_pos,
751 string, GLUT_BITMAP_8_BY_13);
754 if( label->size == LARGE ) {
755 textString( label->x_pos + posincr, label->y_pos,
756 string, GLUT_BITMAP_9_BY_15);
760 // The following routines concern HUD object/component object construction
765 // Constructs a HUD object and then adds in instruments. At the present
766 // the instruments are hard coded into the routine. Ultimately these need
767 // to be defined by the aircraft's instrumentation records so that the
768 // display for a Piper Cub doesn't show the speed range of a North American
769 // mustange and the engine readouts of a B36!
771 Hptr fgHUDInit( fgAIRCRAFT *current_aircraft )
775 fgPrintf( FG_COCKPIT, FG_INFO, "Initializing HUD\n" );
777 hud = (Hptr)calloc(sizeof( HUD),1);
784 // For now lets just hardcode the hud here.
785 // In the future, hud information has to come from the same place
786 // aircraft information came from.
788 fgHUDAddHorizon( hud, 590, 50, 40, 20, get_roll );
789 fgHUDAddScale ( hud, VERTICAL, LIMIT, 220, 100, 280, 5, 10,
790 LEFT, LEFT, 0, 100, 50, get_speed );
791 fgHUDAddScale ( hud, VERTICAL, NOLIMIT, 440, 100, 280, 1, 5,
792 RIGHT, RIGHT, -400, 50, 25, get_aoa );
793 fgHUDAddScale ( hud, HORIZONTAL, NOLIMIT, 280, 220, 440, 5, 10,
794 TOP, TOP, 0, 50, 50, get_heading );
795 fgHUDAddLabel ( hud, 180, 85, SMALL, NOBLINK,
796 RIGHT_JUST, NULL, " Kts", "%5.0f", get_speed );
797 fgHUDAddLabel ( hud, 180, 73, SMALL, NOBLINK,
798 RIGHT_JUST, NULL, " m", "%5.0f", get_altitude );
799 fgHUDAddLadder ( hud, 330, 190, 90, 180, 70, 10,
800 NONE, 45, get_roll, get_pitch );
801 fgHUDAddControlSurfaces( hud, 10, 10, get_heading );
809 // This is a stand in for linked list code that will get replaced later
810 // by some more elegant list handling code.
812 void add_instrument( Hptr hud, HIptr pinstrument )
814 if( !hud || !pinstrument ) {
818 pinstrument->next = hud->instruments;
819 hud->instruments = pinstrument;
825 // Constructs a HUD_horizon "object" and installs it into the hud instrument
828 Hptr fgHUDAddHorizon( Hptr hud, \
833 double (*load_value)() )
835 HUD_horizon *phorizon;
836 HUD_instr *pinstrument;
841 // construct the parent object
842 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
843 if( pinstrument == NULL ) {
846 pinstrument->type = HUDhorizon; // ARTIFICIAL_HORIZON;
848 // Construct the horizon
849 phorizon = (HUD_horizon *) calloc( sizeof(HUD_horizon),1);
850 if( phorizon == NULL ) {
854 phorizon->x_pos = x_pos;
855 phorizon->y_pos = y_pos;
856 phorizon->scr_width = length;
857 phorizon->scr_hole = hole_len;
858 phorizon->load_value = load_value;
859 // Install the horizon in the parent.
860 pinstrument->instr = phorizon;
861 // Install the instrument into hud.
862 add_instrument( hud, pinstrument);
869 // Constructs a HUD_scale "object" and installs it into the hud instrument
872 Hptr fgHUDAddScale( Hptr hud, \
885 double (*load_value)() )
888 HUD_instr *pinstrument;
894 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
895 if( pinstrument == NULL ) {
899 pinstrument->type = HUDscale;
901 pscale = ( HUD_scale *)calloc(sizeof(HUD_scale),1);
902 if( pscale == NULL ) {
906 pscale->sub_type = sub_type;
907 pscale->scr_pos = scr_pos;
908 pscale->scr_min = scr_min;
909 pscale->scr_max = scr_max;
910 pscale->div_min = div_min;
911 pscale->div_max = div_max;
912 pscale->orientation = orientation;
913 pscale->with_minimum = with_min;
914 pscale->minimum_value = min_value;
915 pscale->maximum_value = max_value;
916 pscale->width_units = width_units;
917 pscale->load_value = load_value;
919 pinstrument->instr = pscale;
920 // Install the instrument into hud.
921 add_instrument( hud, pinstrument);
928 // Constructs a HUD_Label object and installs it into the hud instrument
930 Hptr fgHUDAddLabel( Hptr hud, \
939 double (*load_value)() )
942 HUD_instr *pinstrument;
948 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
949 if( pinstrument == NULL ) {
952 pinstrument->type = HUDlabel;
954 plabel = (HUD_label *)calloc(sizeof(HUD_label),1);
955 if( plabel == NULL ){
959 plabel->x_pos = x_pos;
960 plabel->y_pos = y_pos;
962 plabel->blink = blink;
963 plabel->justify = justify;
964 plabel->pre_str = pre_str;
965 plabel->post_str = post_str;
966 plabel->format = format;
967 plabel->load_value = load_value;
969 pinstrument->instr = plabel;
970 // Install the instrument into hud.
971 add_instrument( hud, pinstrument);
978 // Contains code that constructs a ladder "object" and installs it as
979 // a hud instrument in the hud instrument list.
981 Hptr fgHUDAddLadder( Hptr hud, \
990 double (*load_roll)(),
991 double (*load_pitch)() )
994 HUD_instr *pinstrument;
1000 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1001 if( pinstrument == NULL )
1004 pinstrument->type = HUDladder;
1006 pladder = (HUD_ladder *)calloc(sizeof(HUD_ladder),1);
1007 if( pladder == NULL )
1010 pladder->type = 0; // Not used.
1011 pladder->x_pos = x_pos;
1012 pladder->y_pos = y_pos;
1013 pladder->scr_width = scr_width;
1014 pladder->scr_height = scr_height;
1015 pladder->scr_hole = hole_len;
1016 pladder->div_units = div_units;
1017 pladder->label_position = label_pos;
1018 pladder->width_units = width_units;
1019 pladder->load_roll = load_roll;
1020 pladder->load_pitch = load_pitch;
1022 pinstrument->instr = pladder;
1023 // Install the instrument into hud.
1024 add_instrument( hud, pinstrument);
1028 // fgHUDAddControlSurfaces()
1030 // Adds the control surface indicators which make up for the lack of seat
1031 // of the pants feel. Should be unnecessary with joystick and pedals
1032 // enabled. But that is another improvement. Also, what of flaps? Spoilers?
1033 // This may need to be expanded or flattened into multiple indicators,
1034 // vertical and horizontal.
1036 Hptr fgHUDAddControlSurfaces( Hptr hud,
1039 double (*load_value)() )
1041 HUD_control_surfaces *pctrl_surf;
1042 HUD_instr *pinstrument;
1049 pinstrument = (HIptr)calloc(sizeof(HUD_instr),1);
1053 pinstrument->type = HUDcontrols;
1056 pctrl_surf = (HUD_control_surfaces *)calloc(sizeof(HUD_control_surfaces),1);
1057 if( !(pctrl_surf == NULL) )
1060 pctrl_surf->x_pos = x_pos;
1061 pctrl_surf->y_pos = y_pos;
1062 pctrl_surf->load_value = load_value;
1064 pinstrument->instr = pctrl_surf;
1066 add_instrument( hud, pinstrument);
1073 Hptr fgHUDAddMovingHorizon( Hptr hud, \
1083 Hptr fgHUDAddCircularLadder( Hptr hud, \
1093 Hptr fgHUDAddNumDisp( Hptr hud, \
1108 // Performs a once around the list of calls to instruments installed in
1109 // the HUD object with requests for redraw. Kinda. It will when this is
1113 void fgUpdateHUD( Hptr hud ) {
1116 glMatrixMode(GL_PROJECTION);
1120 gluOrtho2D(0, 640, 0, 480);
1121 glMatrixMode(GL_MODELVIEW);
1125 glColor3f(1.0, 1.0, 1.0);
1128 glDisable(GL_DEPTH_TEST);
1129 glDisable(GL_LIGHTING);
1132 glColor3f (0.1, 0.9, 0.1);
1134 fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d Status %d\n",
1135 hud->code, hud->status );
1137 phud_instr = hud->instruments;
1138 while( phud_instr ) {
1139 /* printf("Drawing Instrument %d\n", phud_instr->type); */
1141 switch (phud_instr->type) {
1142 case HUDhorizon: // ARTIFICIAL HORIZON
1143 drawhorizon( (pHUDhorizon)phud_instr->instr );
1146 case HUDscale: // Need to simplify this call.
1147 drawscale ( (pHUDscale) phud_instr->instr );
1151 drawlabel ( (pHUDlabel) phud_instr->instr );
1155 drawladder( (pHUDladder) phud_instr->instr );
1159 drawControlSurfaces( (pHUDControlSurface) phud_instr->instr );
1162 default:; // Ignore anything you don't know about.
1165 phud_instr = phud_instr->next;
1168 glEnable(GL_DEPTH_TEST);
1169 glEnable(GL_LIGHTING);
1170 glMatrixMode(GL_PROJECTION);
1172 glMatrixMode(GL_MODELVIEW);
1178 /* Revision 1.14 1998/02/12 21:59:41 curt
1179 /* Incorporated code changes contributed by Charlie Hotchkiss
1180 /* <chotchkiss@namg.us.anritsu.com>
1182 * Revision 1.12 1998/02/09 15:07:48 curt
1185 * Revision 1.11 1998/02/07 15:29:34 curt
1186 * Incorporated HUD changes and struct/typedef changes from Charlie Hotchkiss
1187 * <chotchkiss@namg.us.anritsu.com>
1189 * Revision 1.10 1998/02/03 23:20:14 curt
1190 * Lots of little tweaks to fix various consistency problems discovered by
1191 * Solaris' CC. Fixed a bug in fg_debug.c with how the fgPrintf() wrapper
1192 * passed arguments along to the real printf(). Also incorporated HUD changes
1193 * by Michele America.
1195 * Revision 1.9 1998/01/31 00:43:04 curt
1196 * Added MetroWorks patches from Carmen Volpe.
1198 * Revision 1.8 1998/01/27 00:47:51 curt
1199 * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
1200 * system and commandline/config file processing code.
1202 * Revision 1.7 1998/01/19 18:40:20 curt
1203 * Tons of little changes to clean up the code and to remove fatal errors
1204 * when building with the c++ compiler.
1206 * Revision 1.6 1997/12/15 23:54:34 curt
1207 * Add xgl wrappers for debugging.
1208 * Generate terrain normals on the fly.
1210 * Revision 1.5 1997/12/10 22:37:39 curt
1211 * Prepended "fg" on the name of all global structures that didn't have it yet.
1212 * i.e. "struct WEATHER {}" became "struct fgWEATHER {}"
1214 * Revision 1.4 1997/09/23 00:29:32 curt
1215 * Tweaks to get things to compile with gcc-win32.
1217 * Revision 1.3 1997/09/05 14:17:26 curt
1218 * More tweaking with stars.
1220 * Revision 1.2 1997/09/04 02:17:30 curt
1223 * Revision 1.1 1997/08/29 18:03:22 curt