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