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