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