]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/cockpit.cxx
f8e822b3f0303188fa3a9482af211b0a80663159
[flightgear.git] / src / Cockpit / cockpit.cxx
1 // cockpit.cxx -- routines to draw a cockpit (initial draft)
2 //
3 // Written by Michele America, started September 1997.
4 //
5 // Copyright (C) 1997  Michele F. America  - nomimarketing@mail.telepac.pt
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 #include <GL/glut.h>
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <simgear/constants.h>
39 #include <simgear/debug/logstream.hxx>
40 #include <simgear/math/polar3d.hxx>
41 #include <simgear/misc/props.hxx>
42
43 #include <Aircraft/aircraft.hxx>
44 #include <Include/general.hxx>
45 #include <FDM/ADA.hxx>
46 #include <Main/globals.hxx>
47 #include <Main/fg_props.hxx>
48 #include <Main/viewmgr.hxx>
49 #include <Scenery/scenery.hxx>
50 #include <Time/fg_timer.hxx>
51 #include <GUI/gui.h>
52
53 #include "cockpit.hxx"
54
55
56 // This is a structure that contains all data related to
57 // cockpit/panel/hud system
58
59 static pCockpit ac_cockpit;
60 // The following routines obtain information concerntin the aircraft's
61 // current state and return it to calling instrument display routines.
62 // They should eventually be member functions of the aircraft.
63 //
64
65 float get_latitude( void )
66 {
67     double lat;
68
69     lat = current_aircraft.fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES;
70
71     float flat = lat;
72     return(flat);
73
74 }
75
76 float get_lat_min( void )
77 {
78     double      a, d;
79
80     a = current_aircraft.fdm_state->get_Latitude() * SGD_RADIANS_TO_DEGREES;    
81     if (a < 0.0) {
82         a = -a;
83     }
84     d = (double) ( (int) a);
85     float lat_min = (a - d) * 60.0;
86     return(lat_min );
87 }
88
89
90 float get_longitude( void )
91 {
92     double lon;
93
94     lon = current_aircraft.fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES;
95
96     float flon = lon;
97     return(flon);
98 }
99
100
101 char*
102 get_formated_gmt_time( void )
103 {
104     static char buf[32];
105     const struct tm *p = globals->get_time_params()->getGmt();
106     sprintf( buf, "%d/%d/%4d %d:%02d:%02d", 
107          p->tm_mon+1, p->tm_mday, 1900 + p->tm_year,
108          p->tm_hour, p->tm_min, p->tm_sec);
109     return buf;
110 }
111
112
113 float get_long_min( void )
114 {
115     double  a, d;
116     a = current_aircraft.fdm_state->get_Longitude() * SGD_RADIANS_TO_DEGREES;   
117     if (a < 0.0) {
118         a = -a;
119     }
120     d = (double) ( (int) a);
121     float lon_min = (a - d) * 60.0; 
122     return(lon_min);
123 }
124
125 float get_throttleval( void )
126 {
127     float throttle = globals->get_controls()->get_throttle( 0 );
128     return (throttle);     // Hack limiting to one engine
129 }
130
131 float get_aileronval( void )
132 {
133     float aileronval = globals->get_controls()->get_aileron();
134     return (aileronval);
135 }
136
137 float get_elevatorval( void )
138 {
139     float elevator_val = (float)globals->get_controls()->get_elevator();
140     return elevator_val;
141 }
142
143 float get_elev_trimval( void )
144 {
145     float elevatorval = globals->get_controls()->get_elevator_trim();
146     return (elevatorval);
147 }
148
149 float get_rudderval( void )
150 {
151     float rudderval = globals->get_controls()->get_rudder();
152     return (rudderval);
153 }
154
155 float get_speed( void )
156 {
157     static const SGPropertyNode * speedup_node = fgGetNode("/sim/speed-up");
158
159     float speed = current_aircraft.fdm_state->get_V_calibrated_kts()
160         * speedup_node->getIntValue();
161
162     return speed;
163 }
164
165 float get_mach(void)
166 {
167         float mach=current_aircraft.fdm_state->get_Mach_number();
168         return mach;
169 }       
170
171 float get_aoa( void )
172 {
173     float aoa = current_aircraft.fdm_state->get_Alpha() * SGD_RADIANS_TO_DEGREES;
174     return( aoa );
175 }
176
177 float get_roll( void )
178 {
179     float roll = current_aircraft.fdm_state->get_Phi();
180     return( roll );
181 }
182
183 float get_pitch( void )
184 {
185     float pitch = current_aircraft.fdm_state->get_Theta();
186     return( pitch );
187 }
188
189 float get_heading( void )
190 {
191     float heading = (current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES);
192     return( heading );
193 }
194
195 float get_altitude( void )
196 {
197     static const SGPropertyNode *startup_units_node
198         = fgGetNode("/sim/startup/units");
199
200     float altitude;
201
202     if ( startup_units_node->getStringValue() == "feet" ) {
203         altitude = current_aircraft.fdm_state->get_Altitude();
204     } else {
205         altitude = (current_aircraft.fdm_state->get_Altitude()
206                     * SG_FEET_TO_METER);
207     }
208
209     return altitude;
210 }
211
212 float get_agl( void )
213 {
214     float agl;
215
216     if ( fgGetString("/sim/startup/units") == "feet" ) {
217         agl = (current_aircraft.fdm_state->get_Altitude()
218                - scenery.cur_elev * SG_METER_TO_FEET);
219     } else {
220         agl = (current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
221                - scenery.cur_elev);
222     }
223     return agl;
224 }
225
226 float get_sideslip( void )
227 {
228     float sideslip = current_aircraft.fdm_state->get_Beta();
229     return( sideslip );
230 }
231
232 float get_frame_rate( void )
233 {
234     float frame_rate = general.get_frame_rate();
235     return (frame_rate); 
236 }
237
238 float get_fov( void )
239 {
240     float fov = globals->get_current_view()->get_fov(); 
241     return (fov);
242 }
243
244 float get_vfc_ratio( void )
245 {
246     // float vfc = current_view.get_vfc_ratio();
247     // return (vfc);
248     return 0.0;
249 }
250
251 float get_vfc_tris_drawn   ( void )
252 {
253     // float rendered = current_view.get_tris_rendered();
254     // return (rendered);
255     return 0.0;
256 }
257
258 float get_vfc_tris_culled   ( void )
259 {
260     // float culled = current_view.get_tris_culled();
261     // return (culled);
262     return 0.0;
263 }
264
265 float get_climb_rate( void )
266 {
267     float climb_rate;
268     if ( fgGetString("/sim/startup/units") == "feet" ) {
269         climb_rate = current_aircraft.fdm_state->get_Climb_Rate() * 60.0;
270     } else {
271         climb_rate = current_aircraft.fdm_state->get_Climb_Rate() * SG_FEET_TO_METER * 60.0;
272     }
273     return (climb_rate);
274 }
275
276
277 float get_view_direction( void )
278 {
279     double view_off = SGD_2PI - globals->get_current_view()->get_view_offset();
280     double view = ( current_aircraft.fdm_state->get_Psi() + view_off)
281         * SGD_RADIANS_TO_DEGREES;
282     
283     if(view > 360.)
284         view -= 360.;
285     else if(view<0.)
286         view += 360.;
287     
288     return view;
289 }
290
291 // $$$ begin - added, VS Renganathan 13 Oct 2K
292 // #ifdef FIGHTER_HUD
293 float get_Vx   ( void )
294 {
295     // CLO - 5 Jan 2000 - something needs to get addressed here
296     // float Vxx = current_aircraft.fdm_state->get_V_north_rel_ground();
297     float Vxx = 0;
298     return (Vxx);
299 }
300
301 float get_Vy   ( void )
302 {
303     // CLO - 5 Jan 2000 - something needs to get addressed here
304     // float Vyy = current_aircraft.fdm_state->get_V_east_rel_ground();
305     float Vyy = 0;
306     return (Vyy);
307 }
308
309 float get_Vz   ( void )
310 {
311     // CLO - 5 Jan 2000 - something needs to get addressed here
312     // float Vzz = current_aircraft.fdm_state->get_V_down_rel_ground();
313     float Vzz = 0;
314     return (Vzz);
315 }
316
317 float get_Ax   ( void )
318 {
319     float Ax = current_aircraft.fdm_state->get_V_dot_north();
320     return (Ax);
321 }
322
323 float get_Ay   ( void )
324 {
325     float Ay = current_aircraft.fdm_state->get_V_dot_east();
326     return (Ay);
327 }
328
329 float get_Az   ( void )
330 {
331     float Az = current_aircraft.fdm_state->get_V_dot_down();
332     return (Az);
333 }
334
335 float get_anzg   ( void )
336 {
337     float anzg = current_aircraft.fdm_state->get_N_Z_cg();
338     return (anzg);
339 }
340
341 int get_iaux1 (void)
342 {
343     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
344     return fdm->get_iaux1();
345 }
346
347 int get_iaux2 (void)
348 {
349     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
350     return fdm->get_iaux2();
351 }
352
353 int get_iaux3 (void)
354 {
355     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
356     return fdm->get_iaux3();
357 }
358
359 int get_iaux4 (void)
360 {
361     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
362     return fdm->get_iaux4();
363 }
364
365 int get_iaux5 (void)
366 {
367     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
368     return fdm->get_iaux5();
369 }
370
371 int get_iaux6 (void)
372 {
373     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
374     return fdm->get_iaux6();
375 }
376
377 int get_iaux7 (void)
378 {
379     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
380     return fdm->get_iaux7();
381 }
382
383 int get_iaux8 (void)
384 {
385     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
386     return fdm->get_iaux8();
387 }
388
389 int get_iaux9 (void)
390 {
391     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
392     return fdm->get_iaux9();
393 }
394
395 int get_iaux10 (void)
396 {
397     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
398     return fdm->get_iaux10();
399 }
400
401 int get_iaux11 (void)
402 {
403     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
404     return fdm->get_iaux11();
405 }
406
407 int get_iaux12 (void)
408 {
409      FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
410      return fdm->get_iaux12();
411 }
412
413 float get_aux1 (void)
414 {
415     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
416     return fdm->get_aux1();
417 }
418
419 float get_aux2 (void)
420 {
421     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
422     return fdm->get_aux2();
423 }
424
425 float get_aux3 (void)
426 {
427     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
428     return fdm->get_aux3();
429 }
430
431 float get_aux4 (void)
432 {
433     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
434     return fdm->get_aux4();
435 }
436
437 float get_aux5 (void)
438 {
439     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
440     return fdm->get_aux5();
441 }
442
443 float get_aux6 (void)
444 {
445     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
446     return fdm->get_aux6();
447 }
448
449 float get_aux7 (void)
450 {
451     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
452     return fdm->get_aux7();
453 }
454
455 float get_aux8 (void)
456 {
457     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
458     return fdm->get_aux8();
459 }
460
461 float get_aux9 (void)
462 {
463     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
464     return fdm->get_aux9();
465 }
466
467 float get_aux10 (void)
468 {
469     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
470     return fdm->get_aux10();
471 }
472
473 float get_aux11 (void)
474 {
475     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
476     return fdm->get_aux11();
477 }
478
479 float get_aux12 (void)
480 {
481     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
482     return fdm->get_aux12();
483 }
484
485 float get_aux13 (void)
486 {
487     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
488     return fdm->get_aux13();
489 }
490
491 float get_aux14 (void)
492 {
493     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
494     return fdm->get_aux14();
495 }
496
497 float get_aux15 (void)
498 {
499     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
500     return fdm->get_aux15();
501 }
502
503 float get_aux16 (void)
504 {
505     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
506     return fdm->get_aux16();
507 }
508
509 float get_aux17 (void)
510 {
511     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
512     return fdm->get_aux17();
513 }
514
515 float get_aux18 (void)
516 {
517     FGADA *fdm = (FGADA *)current_aircraft.fdm_state;
518     return fdm->get_aux18();
519 }
520 // #endif
521 // $$$ end - added, VS Renganathan 13 Oct 2K
522
523
524 #ifdef NOT_USED
525 /****************************************************************************/
526 /* Convert degrees to dd mm'ss.s" (DMS-Format)                              */
527 /****************************************************************************/
528 char *dmshh_format(double degrees)
529 {
530     static char buf[16];    
531     int deg_part;
532     int min_part;
533     double sec_part;
534     
535     if (degrees < 0)
536       degrees = -degrees;
537
538     deg_part = degrees;
539     min_part = 60.0 * (degrees - deg_part);
540     sec_part = 3600.0 * (degrees - deg_part - min_part / 60.0);
541
542     /* Round off hundredths */
543     if (sec_part + 0.005 >= 60.0)
544       sec_part -= 60.0, min_part += 1;
545     if (min_part >= 60)
546       min_part -= 60, deg_part += 1;
547
548     sprintf(buf,"%02d*%02d %05.2f",deg_part,min_part,sec_part);
549
550     return buf;
551 }
552 #endif // 0
553
554
555 /************************************************************************
556  Convert degrees to dd mm.mmm' (DMM-Format)
557  Description: Converts using a round-off factor tailored to the required
558  precision of the minutes field (three decimal places).  Round-off
559  prevents function from returning a minutes value of 60.
560
561  Input arguments: Coordinate value in decimal degrees
562
563 ************************************************************************/
564 static char *toDM(float dd)
565 {
566     static char  dm[16];
567     double tempdd;
568     double mn;
569     double sign = 1;
570     int deg;
571
572     if (dd < 0) {
573         sign = -1;
574     }
575     /* round for minutes expressed to three decimal places */
576     tempdd = fabs(dd) + (5.0E-4 / 60.0);
577     deg = (int)tempdd;
578     mn = fabs( (tempdd - (double)(deg)) * 60.0 - 4.999E-4 );
579     deg *= (int)sign;
580     sprintf(dm, "%d*%06.3f", deg, mn);
581     return dm;
582 }
583
584
585 /************************************************************************
586  Convert degrees to dd mm'ss.s'' (DMS-Format)
587  Description: Converts using a round-off factor tailored to the required
588  precision of the seconds field (one decimal place).  Round-off
589  prevents function from returning a seconds value of 60.
590
591  Input arguments: Coordinate value in decimal degrees
592
593 ************************************************************************/
594 static char *toDMS(float dd)
595 {
596     static char  dms[16];
597     double tempdd, tempmin;
598     int deg;
599     int mn;
600     double sec;
601     double sign = 1;
602
603     if(dd < 0) {
604         sign = -1;
605     }
606     /* round up for seconds expressed to one decimal place */
607     tempdd = fabs(dd) + (0.05 / 3600.0);
608     deg = (int)tempdd;
609     tempmin =  (tempdd - (double)(deg)) * 60.0;
610     mn = (int)tempmin;
611     sec = fabs( (tempmin - (double)(mn)) * 60.0 - 0.049 );
612     deg *= (int)sign;
613     sprintf(dms, "%d*%02d %04.1f", deg, mn, sec);
614     return dms;
615 }
616
617
618 // Have to set the LatLon display type
619 //static char *(*fgLatLonFormat)(float) = toDM;
620 static char *(*fgLatLonFormat)(float);
621
622 char *coord_format_lat(float latitude)
623 {
624     static char buf[16];
625
626     sprintf(buf,"%s%c",
627 //      dmshh_format(latitude),
628 //      toDMS(latitude),
629 //      toDM(latitude),
630         fgLatLonFormat(latitude),           
631         latitude > 0 ? 'N' : 'S');
632     return buf;
633 }
634
635 char *coord_format_lon(float longitude)
636 {
637     static char buf[80];
638
639     sprintf(buf,"%s%c",
640 //      dmshh_format(longitude),
641 //      toDMS(longitude),
642 //      toDM(longitude),
643         fgLatLonFormat(longitude),
644         longitude > 0 ? 'E' : 'W');
645     return buf;
646 }
647
648 void fgLatLonFormatToggle( puObject *)
649 {
650     static int toggle = 0;
651
652     if ( toggle ) 
653         fgLatLonFormat = toDM;
654     else
655         fgLatLonFormat = toDMS;
656     
657     toggle = ~toggle;
658 }
659
660 #ifdef NOT_USED
661 char *coord_format_latlon(double latitude, double longitude)
662 {
663     static char buf[1024];
664
665     sprintf(buf,"%s%c %s%c",
666         dmshh_format(latitude),
667         latitude > 0 ? 'N' : 'S',
668         dmshh_format(longitude),
669         longitude > 0 ? 'E' : 'W');
670     return buf;
671 }
672 #endif
673
674
675 bool fgCockpitInit( fgAIRCRAFT *cur_aircraft )
676 {
677     SG_LOG( SG_COCKPIT, SG_INFO, "Initializing cockpit subsystem" );
678
679     //  cockpit->code = 1;  /* It will be aircraft dependent */
680     //  cockpit->status = 0;
681
682     // If aircraft has HUD specified we will get the specs from its def
683     // file. For now we will depend upon hard coding in hud?
684     
685     // We must insure that the existing instrument link is purged.
686     // This is done by deleting the links in the list.
687     
688     // HI_Head is now a null pointer so we can generate a new list from the
689     // current aircraft.
690
691     fgHUDInit( cur_aircraft );
692     ac_cockpit = new fg_Cockpit();
693     
694     // Have to set the LatLon display type
695     fgLatLonFormat = toDM;
696     
697     SG_LOG( SG_COCKPIT, SG_INFO,
698         "  Code " << ac_cockpit->code() << " Status " 
699         << ac_cockpit->status() );
700
701         return true;
702 }
703
704 void fgCockpitUpdate( void ) {
705
706     SG_LOG( SG_COCKPIT, SG_DEBUG,
707             "Cockpit: code " << ac_cockpit->code() << " status " 
708             << ac_cockpit->status() );
709
710     static const SGPropertyNode * xsize_node = fgGetNode("/sim/startup/xsize");
711     static const SGPropertyNode * ysize_node = fgGetNode("/sim/startup/ysize");
712     static const SGPropertyNode * hud_visibility_node
713         = fgGetNode("/sim/hud/visibility");
714
715     int iwidth   = xsize_node->getIntValue();
716     int iheight  = ysize_node->getIntValue();
717     float width  = iwidth;
718     // float height = iheight;
719
720                                 // FIXME: inefficient
721     if ( hud_visibility_node->getBoolValue() ) {
722         // This will check the global hud linked list pointer.
723         // If these is anything to draw it will.
724         fgUpdateHUD();
725     }
726
727 #define DISPLAY_COUNTER
728 #ifdef DISPLAY_COUNTER
729     else
730     {
731         char buf[64];
732         float fps    =       get_frame_rate();
733 //      float tris   = fps * get_vfc_tris_drawn();
734 //      float culled = fps * get_vfc_tris_culled();
735 //      sprintf(buf,"%-4.1f  %7.0f  %7.0f", fps, tris, culled);
736         sprintf(buf,"%-5.1f", fps);
737
738         glMatrixMode( GL_PROJECTION );
739         glPushMatrix();
740         glLoadIdentity();
741         gluOrtho2D( 0, iwidth, 0, iheight );
742         glMatrixMode( GL_MODELVIEW );
743         glPushMatrix();
744         glLoadIdentity();
745
746         glDisable( GL_DEPTH_TEST );
747         glDisable( GL_LIGHTING );
748         
749         glColor3f( 0.9, 0.4, 0.2 );
750
751         guiFnt.drawString( buf,
752                            int(width - guiFnt.getStringWidth(buf) - 10),
753                            10 );
754         glEnable( GL_DEPTH_TEST );
755         glEnable( GL_LIGHTING );
756         glMatrixMode( GL_PROJECTION );
757         glPopMatrix();
758         glMatrixMode( GL_MODELVIEW );
759         glPopMatrix();
760     }
761 #endif // #ifdef DISPLAY_COUNTER
762     
763     glViewport( 0, 0, iwidth, iheight );
764 }