1 // hud.cxx -- hud defines and prototypes
3 // Written by Michele America, started September 1997.
5 // Copyright (C) 1997 Michele F. America - micheleamerica@geocities.com
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.
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.
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.
33 # define exception c_exception
42 # include <values.h> // for MAXINT
45 #include <Aircraft/aircraft.hxx>
46 #include <Debug/logstream.hxx>
48 #include <Include/fg_constants.h>
49 #include <Main/options.hxx>
50 #include <Math/fg_random.h>
51 #include <Math/mat3.h>
52 #include <Math/polar3d.hxx>
53 #include <Scenery/scenery.hxx>
54 #include <Time/fg_timer.hxx>
56 #if defined ( __sun__ ) || defined ( __sgi )
58 extern void *memmove(void *, const void *, size_t);
66 // The following routines obtain information concerning the aircraft's
67 // current state and return it to calling instrument display routines.
68 // They should eventually be member functions of the aircraft.
71 deque< instr_item * > HUD_deque;
73 fgTextList HUD_TextList;
74 fgLineList HUD_LineList;
75 fgLineList HUD_StippleLineList;
81 locRECT( UINT left, UINT top, UINT right, UINT bottom);
82 RECT get_rect(void) { return rect;}
85 locRECT :: locRECT( UINT left, UINT top, UINT right, UINT bottom)
95 void drawOneLine( UINT x1, UINT y1, UINT x2, UINT y2)
103 void drawOneLine( RECT &rect)
106 glVertex2f(rect.left, rect.top);
107 glVertex2f(rect.right, rect.bottom);
112 // The following code deals with painting the "instrument" on the display
114 /* textString - Bitmap font string */
116 void textString( int x, int y, char *msg, void *font ){
120 // puDrawString ( NULL, msg, x, y );
124 glutBitmapCharacter(font, *msg);
131 /* strokeString - Stroke font string */
132 void strokeString(int x, int y, char *msg, void *font, float theta)
137 float sintheta,costheta;
143 glRotatef(theta * RAD_TO_DEG, 0.0, 0.0, 1.0);
144 sintheta = sin(theta);
145 costheta = cos(theta);
146 xx = (int)(x * costheta + y * sintheta);
147 yy = (int)(y * costheta - x * sintheta);
148 glTranslatef( xx, yy, 0);
149 glScalef(.1, .1, 0.0);
150 while( (c=*msg++) ) {
151 glutStrokeCharacter(font, c);
157 int getStringWidth ( char *str )
159 if ( HUDtext && str )
162 guiFntHandle->getBBox ( str, HUD_TextSize, 0, &l, &r, NULL, NULL ) ;
163 return FloatToInt( r - l );
168 //========================= End of Class Implementations===================
171 // Constructs a HUD object and then adds in instruments. At the present
172 // the instruments are hard coded into the routine. Ultimately these need
173 // to be defined by the aircraft's instrumentation records so that the
174 // display for a Piper Cub doesn't show the speed range of a North American
175 // mustange and the engine readouts of a B36!
180 int fgHUDInit( fgAIRCRAFT * /* current_aircraft */ )
187 int min_x = 25; //off/2;
188 int max_x = 615; //640-(off/2);
190 int max_y = 430; //480-off;
193 unsigned int text_h = 10;
194 unsigned int ladr_w2 = 60;
200 font_size = (current_options.get_xsize() > 1000) ? LARGE : SMALL;
204 FG_LOG( FG_COCKPIT, FG_INFO, "Initializing current aircraft HUD" );
206 // deque < instr_item * > :: iterator first = HUD_deque.begin();
207 // deque < instr_item * > :: iterator last = HUD_deque.end();
208 // HUD_deque.erase( first, last); // empty the HUD deque
210 HUD_deque.erase( HUD_deque.begin(), HUD_deque.end()); // empty the HUD deque
215 // For now lets just hardcode the hud here.
216 // In the future, hud information has to come from the same place
217 // aircraft information came from.
219 // fgHUDSetTimeMode( hud, NIGHT );
220 // fgHUDSetBrightness( hud, BRT_LIGHT );
223 int x = 290; /*cen_x-30*/
224 int y = 45; /*off-5*/
225 // HIptr = (instr_item *) new fgTBI_instr( x, y, ladr_w2, text_h );
226 HIptr = (instr_item *) new fgTBI_instr( 290, 45, 60, 10 );
227 HUD_deque.insert( HUD_deque.begin(), HIptr);
229 // case 1: // Artificial Horizon
230 HIptr = (instr_item *) new HudLadder( cen_x-ladr_w2, cen_y-ladr_h2,
231 2*ladr_w2, 2*ladr_h2 );
232 HUD_deque.insert( HUD_deque.begin(), HIptr);
234 // case 4: // GYRO COMPASS
235 HIptr = (instr_item *) new hud_card( cen_x-(compass_w/2),
248 HUD_deque.insert( HUD_deque.begin(), HIptr);
251 HIptr = (instr_item *) new hud_card( max_x - 35 -15, // 15 to balance speed card
256 // HUDS_RIGHT | HUDS_VERT,
257 HUDS_LEFT | HUDS_VERT,
265 HUD_deque.insert( HUD_deque.begin(), HIptr);
268 HIptr = (instr_item *) new guage_instr( cen_x-50, // x
269 cen_y + ladr_h2 -20, // y
272 get_aileronval, // data source
273 HUDS_BOTTOM | HUDS_NOTEXT,
277 HUD_deque.insert( HUD_deque.begin(), HIptr);
279 // case 3: // Radio Altimeter
280 HIptr = (instr_item *) new hud_card( cen_x + ladr_w2 + gap + 13 + ladr_t,
285 HUDS_LEFT | HUDS_VERT,
293 HUD_deque.insert( HUD_deque.begin(), HIptr);
296 HIptr = (instr_item *) new guage_instr( cen_x -ladr_w2 -gap -13 -20 -ladr_t,
300 get_elevatorval, // data source
301 HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT,
302 -100.0, // Scale data
305 HUD_deque.insert( HUD_deque.begin(), HIptr);
308 HIptr = (instr_item *) new guage_instr( cen_x-50, // x
309 cen_y -gap -ladr_w2 -20, //-85 // y
312 get_rudderval, // data source
313 HUDS_TOP | HUDS_NOTEXT,
317 HUD_deque.insert( HUD_deque.begin(), HIptr);
320 HIptr = (instr_item *) new hud_card( min_x +10 +5, //min_x +18,
325 // HUDS_LEFT | HUDS_VERT,
326 HUDS_RIGHT | HUDS_VERT,
335 HUD_deque.insert( HUD_deque.begin(), HIptr);
338 HIptr = (instr_item *) new guage_instr( min_x-10, // x
342 get_throttleval, // data source
343 // HUDS_VERT | HUDS_RIGHT | HUDS_NOTEXT,
344 HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT, 100.0,
348 HUD_deque.insert( HUD_deque.begin(), HIptr);
349 // Remove this when below uncommented
351 HIptr = (instr_item *) new instr_label( 10,
365 HUD_deque.insert( HUD_deque.begin(), HIptr);
367 HIptr = (instr_item *) new lat_label( (cen_x - (compass_w/2))/2,
381 HUD_deque.insert( HUD_deque.begin(), HIptr);
383 HIptr = (instr_item *) new lon_label(((cen_x+compass_w/2)+(2*cen_x))/2,
396 HUD_deque.insert( HUD_deque.begin(), HIptr);
399 // case 10: // Digital KIAS
400 HIptr = (instr_item *) new instr_label ( 110,
414 HUD_deque.insert( HUD_deque.begin(), HIptr);
416 // case 11: // Digital Rate of Climb
417 HIptr = (instr_item *) new instr_label ( 110,
431 HUD_deque.insert( HUD_deque.begin(), HIptr);
433 // case 12: // Roll indication diagnostic
434 HIptr = (instr_item *) new instr_label ( 110,
448 HUD_deque.insert( HUD_deque.begin(), HIptr);
450 // case 13: // Angle of attack diagnostic
451 HIptr = (instr_item *) new instr_label ( 440,
465 HUD_deque.insert( HUD_deque.begin(), HIptr);
468 HIptr = (instr_item *) new instr_label ( 440,
482 HUD_deque.insert( HUD_deque.begin(), HIptr);
485 HIptr = (instr_item *) new instr_label ( 440,
499 HUD_deque.insert( HUD_deque.begin(), HIptr);
502 HIptr = (instr_item *) new instr_label( 440,
516 HUD_deque.insert( HUD_deque.begin(), HIptr);
519 HIptr = (instr_item *) new instr_label( 440,
533 HUD_deque.insert( HUD_deque.begin(), HIptr);
536 HIptr = (instr_item *) new instr_label( 440,
550 HUD_deque.insert( HUD_deque.begin(), HIptr);
553 HIptr = (instr_item *) new instr_label( 10,
567 HUD_deque.insert( HUD_deque.begin(), HIptr);
570 switch( current_options.get_tris_or_culled() ) {
572 HIptr = (instr_item *) new instr_label( 10,
588 HIptr = (instr_item *) new instr_label( 10,
607 HIptr = (instr_item *) new instr_label( 10,
621 HUD_deque.insert( HUD_deque.begin(), HIptr);
626 // if( HIptr ) { // Anything to install?
627 // HUD_deque.insert( HUD_deque.begin(), HIptr);
633 return 0; // For now. Later we may use this for an error code.
637 int fgHUDInit2( fgAIRCRAFT * /* current_aircraft */ )
639 // instr_item *HIptr;
645 // int max_x = 640-off;
649 // int cen_y = 480 / 2;
657 font_size = (current_options.get_xsize() > 1000) ? LARGE : SMALL;
661 FG_LOG( FG_COCKPIT, FG_INFO, "Initializing current aircraft HUD" );
663 // deque < instr_item * > :: iterator first = HUD_deque.begin();
664 // deque < instr_item * > :: iterator last = HUD_deque.end();
665 // HUD_deque.erase( first, last); // empty the HUD deque
666 HUD_deque.erase( HUD_deque.begin(), HUD_deque.end());
671 // For now lets just hardcode the hud here.
672 // In the future, hud information has to come from the same place
673 // aircraft information came from.
675 // fgHUDSetTimeMode( hud, NIGHT );
676 // fgHUDSetBrightness( hud, BRT_LIGHT );
683 // case 4: // GYRO COMPASS
684 p =new hud_card( cen_x-(compass_w/2),
697 HUD_deque.push_front( p );
699 p = new lat_label( (cen_x - compass_w/2)/2,
712 HUD_deque.push_front( p );
714 // p = new instr_label( 140, 450, 60, 10,
725 // HUD_deque.push_front( p );
727 p = new lon_label(((cen_x+compass_w/2)+(2*cen_x))/2,
740 HUD_deque.push_front( p );
744 p = new instr_label( x_pos, 25, 60, 10,
755 HUD_deque.push_front( p );
757 p = new instr_label( x_pos, 40, 120, 10,
768 HUD_deque.push_front( p );
770 p = new instr_label( x_pos, 55, 120, 10,
781 HUD_deque.push_front( p );
783 p = new instr_label( x_pos, 70, 90, 10,
794 HUD_deque.push_front( p );
798 p = new instr_label ( x_pos,
812 HUD_deque.push_front( p );
814 p = new instr_label( x_pos, 55, 40, 30,
825 HUD_deque.push_front( p );
827 if ( current_options.get_units() == fgOPTIONS::FG_UNITS_FEET ) {
828 strcpy(units, " ft");
832 p = new instr_label( x_pos, 40, 40, 10,
843 HUD_deque.push_front( p );
845 p = new instr_label( x_pos, 25, 40, 10,
856 HUD_deque.push_front( p );
858 p = new instr_label( x_pos, 10, 60, 10,
869 HUD_deque.push_front( p );
871 p = new fgTBI_instr( 290, 55, 60, 10 ); // 270
872 HUD_deque.push_front( p );
874 p = new guage_instr( 270, //250, // x
875 390, //360, //400, //45, //420, // y
878 get_aileronval, // data source
879 HUDS_BOTTOM | HUDS_NOTEXT,
883 HUD_deque.push_front( p );
885 p = new guage_instr( 20, // x
889 get_elevatorval, // data source
890 HUDS_RIGHT | HUDS_VERT | HUDS_NOTEXT,
891 -100.0, // Scale data
894 HUD_deque.push_front( p );
896 p = new guage_instr( 270, //250, // x
900 get_rudderval, // data source
901 HUDS_TOP | HUDS_NOTEXT,
905 HUD_deque.push_front( p );
907 p = new guage_instr( 600, // x
911 get_throttleval, // data source
912 HUDS_VERT | HUDS_LEFT | HUDS_NOTEXT,
916 HUD_deque.push_front( p );
918 return 0; // For now. Later we may use this for an error code.
921 int global_day_night_switch = DAY;
923 void HUD_brightkey( bool incr_bright )
925 instr_item *pHUDInstr = HUD_deque[0];
926 int brightness = pHUDInstr->get_brightness();
928 if( current_options.get_hud_status() ) {
930 switch (brightness) {
932 current_options.set_hud_status(0);
936 brightness = BRT_LIGHT;
940 brightness = BRT_MEDIUM;
944 brightness = BRT_DARK;
948 brightness = BRT_BLACK;
952 switch (brightness) {
954 brightness = BRT_MEDIUM;
958 brightness = BRT_DARK;
962 brightness = BRT_BLACK;
967 current_options.set_hud_status(0);
972 current_options.set_hud_status(1);
974 if( DAY == global_day_night_switch ) {
975 brightness = BRT_BLACK;
978 brightness = BRT_DARK;
979 global_day_night_switch = DAY;
983 if( NIGHT == global_day_night_switch ) {
984 brightness = BRT_DARK;
987 brightness = BRT_MEDIUM;
988 global_day_night_switch = NIGHT;
992 pHUDInstr->SetBrightness( brightness );
997 // Performs a once around the list of calls to instruments installed in
998 // the HUD object with requests for redraw. Kinda. It will when this is
1001 void fgUpdateHUD( void ) {
1003 // int day_night_sw = current_aircraft.controls->day_night_switch;
1004 int day_night_sw = global_day_night_switch;
1005 int hud_displays = HUD_deque.size();
1006 instr_item *pHUDInstr;
1009 if( !hud_displays ) { // Trust everyone, but ALWAYS cut the cards!
1013 HUD_TextList.erase();
1014 HUD_LineList.erase();
1015 // HUD_StippleLineList.erase();
1017 pHUDInstr = HUD_deque[0];
1018 brightness = pHUDInstr->get_brightness();
1019 // brightness = HUD_deque.at(0)->get_brightness();
1021 glMatrixMode(GL_PROJECTION);
1025 gluOrtho2D(0, 640, 0, 480);
1026 glMatrixMode(GL_MODELVIEW);
1030 glColor3f(1.0, 1.0, 1.0);
1033 glDisable(GL_DEPTH_TEST);
1034 glDisable(GL_LIGHTING);
1036 // We can do translucency, so why not. :-)
1037 // glEnable ( GL_BLEND ) ;
1038 // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
1040 if( day_night_sw == DAY) {
1041 switch (brightness) {
1043 // glColor4f (0.1, 0.9, 0.1, 0.75);
1044 glColor3f (0.1, 0.9, 0.1);
1048 // glColor4f (0.1, 0.7, 0.0, 0.75);
1049 glColor3f (0.1, 0.7, 0.0);
1053 // glColor4f (0.0, 0.6, 0.0, 0.75);
1054 glColor3f(0.0, 0.6, 0.0);
1058 // glColor4f( 0.0, 0.0, 0.0, 0.75);
1059 glColor3f( 0.0, 0.0, 0.0);
1066 if( day_night_sw == NIGHT) {
1067 switch (brightness) {
1069 // glColor4f (0.9, 0.1, 0.1, 0.75);
1070 glColor3f (0.9, 0.1, 0.1);
1074 // glColor4f (0.7, 0.0, 0.1, 0.75);
1075 glColor3f (0.7, 0.0, 0.1);
1080 // glColor4f (0.6, 0.0, 0.0, 0.75);
1081 glColor3f (0.6, 0.0, 0.0);
1084 else { // Just in case default
1085 // glColor4f (0.1, 0.9, 0.1, 0.75);
1086 glColor3f (0.1, 0.9, 0.1);
1090 deque < instr_item * > :: iterator current = HUD_deque.begin();
1091 deque < instr_item * > :: iterator last = HUD_deque.end();
1093 for ( ; current != last; ++current ) {
1094 pHUDInstr = *current;
1096 if( pHUDInstr->enabled()) {
1097 // fgPrintf( FG_COCKPIT, FG_DEBUG, "HUD Code %d Status %d\n",
1098 // hud->code, hud->status );
1100 // HUD_deque.at(i)->draw(); // Responsible for broken or fixed variants.
1101 // No broken displays honored just now.
1105 char *gmt_str = get_formated_gmt_time();
1106 HUD_TextList.add( fgText( 40, 10, gmt_str) );
1108 HUD_TextList.draw();
1110 line_width = (current_options.get_xsize() > 1000) ? 1.0 : 0.5;
1111 glLineWidth(line_width);
1112 HUD_LineList.draw();
1114 // glEnable(GL_LINE_STIPPLE);
1115 // glLineStipple( 1, 0x00FF );
1116 // HUD_StippleLineList.draw();
1117 // glDisable(GL_LINE_STIPPLE);
1119 // glDisable( GL_BLEND );
1121 glEnable(GL_DEPTH_TEST);
1122 glEnable(GL_LIGHTING);
1123 glMatrixMode(GL_PROJECTION);
1125 glMatrixMode(GL_MODELVIEW);