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