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