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