]> git.mxchange.org Git - flightgear.git/blob - Main/GLmain.c
A tiny bit more view tweaking.
[flightgear.git] / Main / GLmain.c
1 /**************************************************************************
2  * GLmain.c -- top level sim routines
3  *
4  * Written by Curtis Olson for OpenGL, started May 1997.
5  *
6  * Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * $Id$
23  * (Log is kept at end of this file)
24  **************************************************************************/
25
26
27 #include <math.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <signal.h>    /* for timer routines */
31
32 #if defined(__WATCOMC__) || defined(__MSC__)
33 #  include <time.h>
34 #else
35 #  include <sys/time.h>
36 #endif
37
38 #ifdef GLUT
39     #include <GL/glut.h>
40     #include "GLUTkey.h"
41 #elif MESA_TK
42     /* assumes -I/usr/include/mesa in compile command */
43     #include "gltk.h"
44     #include "GLTKkey.h"
45 #endif
46
47 #include "../aircraft/aircraft.h"
48 #include "../scenery/scenery.h"
49 #include "../mat3/mat3.h"
50
51
52 #define DEG_TO_RAD       0.017453292
53 #define RAD_TO_DEG       57.29577951
54
55 /* This is a record containing all the info for the aircraft currently
56    being operated */
57 struct aircraft_params current_aircraft;
58
59 /* view parameters */
60 static GLfloat win_ratio = 1.0;
61
62 /* sun direction */
63 static GLfloat sun_vec[4] = {-3.0, 1.0, 2.0, 0.0 };
64
65 /* temporary hack */
66 extern struct mesh *mesh_ptr;
67 /* Function prototypes */
68 GLint fgSceneryCompile();
69 static void fgSceneryDraw();
70 /* pointer to terrain mesh structure */
71 static GLint mesh;
72
73 /* Another hack */
74 double fogDensity = 2000.0;
75 double view_offset = 0.0;
76 double goal_view_offset = 0.0;
77
78 /* Another hack */
79 #define DEFAULT_MODEL_HZ 20
80 #define DEFAULT_MULTILOOP 6
81 double Simtime;
82
83
84 /**************************************************************************
85  * fgInitVisuals() -- Initialize various GL/view parameters
86  **************************************************************************/
87
88 static void fgInitVisuals() {
89     /* if the 4th field is 0.0, this specifies a direction ... */
90     static GLfloat color[4] = { 0.3, 0.7, 0.2, 1.0 };
91     static GLfloat fogColor[4] = {0.65, 0.65, 0.85, 1.0};
92     
93     glEnable( GL_DEPTH_TEST );
94     glFrontFace(GL_CW);
95     glEnable( GL_CULL_FACE );
96
97     /* If enabled, normal vectors specified with glNormal are scaled
98        to unit length after transformation.  See glNormal. */
99     glEnable( GL_NORMALIZE );
100
101     glLightfv( GL_LIGHT0, GL_POSITION, sun_vec );
102     glEnable( GL_LIGHTING );
103     glEnable( GL_LIGHT0 );
104
105     glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color );
106     glShadeModel( GL_FLAT ); /* glShadeModel( GL_SMOOTH ); */
107
108     glEnable( GL_FOG );
109     glFogi (GL_FOG_MODE, GL_LINEAR);
110     /* glFogf (GL_FOG_START, 1.0); */
111     glFogf (GL_FOG_END, fogDensity);
112     glFogfv (GL_FOG_COLOR, fogColor);
113     /* glFogf (GL_FOG_DENSITY, fogDensity); */
114     /* glHint (GL_FOG_HINT, GL_FASTEST); */
115
116     glClearColor(0.6, 0.6, 0.9, 1.0);
117 }
118
119
120 /**************************************************************************
121  * Update the view volume, position, and orientation
122  **************************************************************************/
123
124 static void fgUpdateViewParams() {
125     double pos_x, pos_y, pos_z;
126     struct flight_params *f;
127     MAT3mat R, TMP;
128     MAT3vec vec, up, forward, fwrd_view;
129
130     f = &current_aircraft.flight;
131
132     /* Tell GL we are about to modify the projection parameters */
133     glMatrixMode(GL_PROJECTION);
134     glLoadIdentity();
135     gluPerspective(45.0, 1.0/win_ratio, 1.0, 6000.0);
136
137     glMatrixMode(GL_MODELVIEW);
138     glLoadIdentity();
139     
140     /* calculate position in arc seconds */
141     pos_x = (FG_Longitude * RAD_TO_DEG) * 3600.0;
142     pos_y = (FG_Latitude   * RAD_TO_DEG) * 3600.0;
143     pos_z = FG_Altitude * 0.01; /* (Convert feet to aproximate arcsecs) */
144
145     /* build current rotation matrix */
146     MAT3_SET_VEC(vec, 1.0, 0.0, 0.0);
147     MAT3rotate(R, vec, FG_Phi);
148     /* printf("Roll matrix\n"); */
149     /* MAT3print(R, stdout); */
150
151     MAT3_SET_VEC(vec, 0.0, 1.0, 0.0);
152     /* MAT3mult_vec(vec, vec, R); */
153     MAT3rotate(TMP, vec, -FG_Theta);
154     /* printf("Pitch matrix\n"); */
155     /* MAT3print(TMP, stdout); */
156     MAT3mult(R, R, TMP);
157
158     MAT3_SET_VEC(vec, 0.0, 0.0, -1.0);
159     /* MAT3mult_vec(vec, vec, R); */
160     /* MAT3rotate(TMP, vec, M_PI + M_PI_2 + FG_Psi + view_offset); */
161     MAT3rotate(TMP, vec, FG_Psi - M_PI_2);
162     /* printf("Yaw matrix\n");
163     MAT3print(TMP, stdout); */
164     MAT3mult(R, R, TMP);
165
166     /* MAT3print(R, stdout); */
167
168     /* generate the current up, forward, and fwrd-view vectors */
169     MAT3_SET_VEC(vec, 0.0, 0.0, 1.0);
170     MAT3mult_vec(up, vec, R);
171
172     MAT3_SET_VEC(vec, 1.0, 0.0, 0.0);
173     MAT3mult_vec(forward, vec, R);
174     printf("Forward vector is (%.2f,%.2f,%.2f)\n", forward[0], forward[1], 
175            forward[2]);
176
177     MAT3rotate(TMP, up, view_offset);
178     MAT3mult_vec(fwrd_view, forward, TMP);
179
180     gluLookAt(pos_x, pos_y, pos_z,
181               pos_x + fwrd_view[0], pos_y + fwrd_view[1], pos_z + fwrd_view[2],
182               up[0], up[1], up[2]);
183
184     glLightfv( GL_LIGHT0, GL_POSITION, sun_vec );
185 }
186
187
188 /**************************************************************************
189  * Update all Visuals (redraws anything graphics related)
190  **************************************************************************/
191
192 static void fgUpdateVisuals( void ) {
193     /* update view volume parameters */
194     fgUpdateViewParams();
195
196     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
197
198     /* Tell GL we are switching to model view parameters */
199     glMatrixMode(GL_MODELVIEW);
200     /* glLoadIdentity(); */
201
202     /* draw terrain mesh */
203     fgSceneryDraw();
204
205     #ifdef GLUT
206       glutSwapBuffers();
207     #elif MESA_TK
208       tkSwapBuffers();
209     #endif
210 }
211
212
213 /**************************************************************************
214  * Timer management routines
215  **************************************************************************/
216
217 static struct itimerval t, ot;
218
219 /* This routine catches the SIGALRM */
220 void fgTimerCatch() {
221     struct flight_params *f;
222     static double lastSimtime = -99.9;
223     int Overrun;
224
225     /* ignore any SIGALRM's until we come back from our EOM iteration */
226     signal(SIGALRM, SIG_IGN);
227
228     f = &current_aircraft.flight;
229
230     /* printf("In fgTimerCatch()\n"); */
231
232     Overrun = (lastSimtime == Simtime);
233
234     /* add this back in when you get simtime working */
235     /* if ( Overrun ) {
236         printf("OVERRUN!!!\n");
237     } */
238
239     /* update the flight model */
240     fgFlightModelUpdate(FG_LARCSIM, f, DEFAULT_MULTILOOP);
241
242     if ( fabs(goal_view_offset - view_offset) < 0.09 ) {
243         view_offset = goal_view_offset;
244     } else {
245         /* move view_offset towards goal_view_offset */
246         if ( goal_view_offset > view_offset ) {
247             if ( goal_view_offset - view_offset < M_PI ) {
248                 view_offset += 0.05;
249             } else {
250                 view_offset -= 0.05;
251             }
252         } else {
253             if ( view_offset - goal_view_offset < M_PI ) {
254                 view_offset -= 0.05;
255             } else {
256                 view_offset += 0.05;
257             }
258         }
259         if ( view_offset > PI2 ) {
260             view_offset -= PI2;
261         } else if ( view_offset < 0 ) {
262             view_offset += PI2;
263         }
264     }
265
266     lastSimtime = Simtime;
267     signal(SIGALRM, fgTimerCatch);
268 }
269
270 /* this routine initializes the interval timer to generate a SIGALRM after
271  * the specified interval (dt) */
272 void fgTimerInit(float dt) {
273     int terr;
274     int isec;
275     float usec;
276
277     isec = (int) dt;
278     usec = 1000000* (dt - (float) isec);
279
280     t.it_interval.tv_sec = isec;
281     t.it_interval.tv_usec = usec;
282     t.it_value.tv_sec = isec;
283     t.it_value.tv_usec = usec;
284     /* printf("fgTimerInit() called\n"); */
285     fgTimerCatch();   /* set up for SIGALRM signal catch */
286     terr = setitimer( ITIMER_REAL, &t, &ot );
287     if (terr) perror("Error returned from setitimer");
288 }
289
290
291 /**************************************************************************
292  * Scenery management routines
293  **************************************************************************/
294
295 static void fgSceneryInit() {
296     /* make terrain mesh */
297     mesh = fgSceneryCompile();
298 }
299
300
301 /* create the terrain mesh */
302 GLint fgSceneryCompile() {
303     GLint mesh;
304
305     mesh = mesh2GL(mesh_ptr);
306
307     return(mesh);
308 }
309
310
311 /* draw the terrain mesh */
312 static void fgSceneryDraw() {
313     glCallList(mesh);
314 }
315
316
317 /* What should we do when we have nothing else to do?  How about get
318  * ready for the next move?*/
319 static void fgMainLoop( void )
320 {
321     fgSlewUpdate();
322     aircraft_debug(1);
323
324     fgUpdateVisuals();
325 }
326
327
328 /**************************************************************************
329  * Handle new window size or exposure
330  **************************************************************************/
331
332 static void fgReshape( int width, int height ) {
333     /* Do this so we can call fgReshape(0,0) ourselves without having to know
334      * what the values of width & height are. */
335     if ( (height > 0) && (width > 0) ) {
336         win_ratio = (GLfloat) height / (GLfloat) width;
337     }
338
339     /* Inform gl of our view window size */
340     glViewport(0, 0, (GLint)width, (GLint)height);
341
342     fgUpdateViewParams();
343     
344     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
345 }
346
347
348 /**************************************************************************
349  * Main ...
350  **************************************************************************/
351
352 int main( int argc, char *argv[] ) {
353     struct flight_params *f;
354
355     f = &current_aircraft.flight;
356
357     /* parse the scenery file */
358     parse_scenery(argv[1]);
359
360     #ifdef GLUT
361       /* initialize GLUT */
362       glutInit(&argc, argv);
363
364       /* Define Display Parameters */
365       glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
366
367       /* Define initial window size */
368       glutInitWindowSize(640, 480);
369
370       /* Initialize the main window */
371       glutCreateWindow("Terrain Demo");
372     #elif MESA_TK
373       /* Define initial window size */
374       tkInitPosition(0, 0, 640, 480);
375
376       /* Define Display Parameters */
377       tkInitDisplayMode( TK_RGB | TK_DEPTH | TK_DOUBLE | TK_DIRECT );
378
379       /* Initialize the main window */
380       if (tkInitWindow("Terrain Demo") == GL_FALSE) {
381           tkQuit();
382       }
383     #endif
384
385     /* setup view parameters, only makes GL calls */
386     fgInitVisuals();
387
388     /* Globe Aiport, AZ */
389     FG_Runway_altitude = 3234.5;
390     FG_Runway_latitude = 120070.41;
391     FG_Runway_longitude = -398391.28;
392     FG_Runway_heading = 102.0 * DEG_TO_RAD;
393
394     /* Initial Position */
395     FG_Latitude  = (  120070.41 / 3600.0 ) * DEG_TO_RAD;
396     FG_Longitude = ( -398391.28 / 3600.0 ) * DEG_TO_RAD;
397     FG_Altitude  = FG_Runway_altitude + 3.758099;
398
399     printf("Initial position is: (%.4f, %.4f, %.2f)\n", FG_Latitude, 
400            FG_Longitude, FG_Altitude);
401
402   
403     /* Initial Velocity */
404     FG_V_north = 0.0 /*  7.287719E+00 */;
405     FG_V_east  = 0.0 /*  1.521770E+03 */;
406     FG_V_down  = 0.0 /* -1.265722E-05 */;
407
408     /* Initial Orientation */
409     FG_Phi   = -2.658474E-06;
410     FG_Theta =  7.401790E-03;
411     FG_Psi   =  282.0 * DEG_TO_RAD;
412
413     /* Initial Angular B rates */
414     FG_P_body = 7.206685E-05;
415     FG_Q_body = 0.000000E+00;
416     FG_R_body = 9.492658E-05;
417
418     FG_Earth_position_angle = 0.000000E+00;
419
420     /* Mass properties and geometry values */
421     FG_Mass = 8.547270E+01;
422     FG_I_xx = 1.048000E+03;
423     FG_I_yy = 3.000000E+03;
424     FG_I_zz = 3.530000E+03;
425     FG_I_xz = 0.000000E+00;
426
427     /* CG position w.r.t. ref. point */
428     FG_Dx_cg = 0.000000E+00;
429     FG_Dy_cg = 0.000000E+00;
430     FG_Dz_cg = 0.000000E+00;
431
432     /* Set initial position and slew parameters */
433     /* fgSlewInit(-398391.3, 120070.41, 244, 3.1415); */ /* GLOBE Airport */
434     /* fgSlewInit(-335340,162540, 15, 4.38); */
435     /* fgSlewInit(-398673.28,120625.64, 53, 4.38); */
436
437     fgFlightModelInit(FG_LARCSIM, f, 1.0/(DEFAULT_MODEL_HZ*DEFAULT_MULTILOOP));
438
439     /* build all objects */
440     fgSceneryInit();
441
442     /* initialize timer */
443     fgTimerInit( 1.0 / DEFAULT_MODEL_HZ );
444
445     #ifdef GLUT
446       /* call fgReshape() on window resizes */
447       glutReshapeFunc( fgReshape );
448
449       /* call key() on keyboard event */
450       glutKeyboardFunc( GLUTkey );
451       glutSpecialFunc( GLUTspecialkey );
452
453       /* call fgMainLoop() whenever there is nothing else to do */
454       glutIdleFunc( fgMainLoop );
455
456       /* draw the scene */
457       glutDisplayFunc( fgUpdateVisuals );
458
459       /* pass control off to the GLUT event handler */
460       glutMainLoop();
461     #elif MESA_TK
462       /* call fgReshape() on expose events */
463       tkExposeFunc( fgReshape );
464
465       /* call fgReshape() on window resizes */
466       tkReshapeFunc( fgReshape );
467
468       /* call key() on keyboard event */
469       tkKeyDownFunc( GLTKkey );
470
471       /* call fgMainLoop() whenever there is nothing else to do */
472       tkIdleFunc( fgMainLoop );
473
474       /* draw the scene */
475       tkDisplayFunc( fgUpdateVisuals );
476
477       /* pass control off to the tk event handler */
478       tkExec();
479     #endif
480
481     return(0);
482 }
483
484
485 /* $Log$
486 /* Revision 1.13  1997/06/02 03:40:06  curt
487 /* A tiny bit more view tweaking.
488 /*
489  * Revision 1.12  1997/06/02 03:01:38  curt
490  * Working on views (side, front, back, transitions, etc.)
491  *
492  * Revision 1.11  1997/05/31 19:16:25  curt
493  * Elevator trim added.
494  *
495  * Revision 1.10  1997/05/31 04:13:52  curt
496  * WE CAN NOW FLY!!!
497  *
498  * Continuing work on the LaRCsim flight model integration.
499  * Added some MSFS-like keyboard input handling.
500  *
501  * Revision 1.9  1997/05/30 19:27:01  curt
502  * The LaRCsim flight model is starting to look like it is working.
503  *
504  * Revision 1.8  1997/05/30 03:54:10  curt
505  * Made a bit more progress towards integrating the LaRCsim flight model.
506  *
507  * Revision 1.7  1997/05/29 22:39:49  curt
508  * Working on incorporating the LaRCsim flight model.
509  *
510  * Revision 1.6  1997/05/29 12:31:39  curt
511  * Minor tweaks, moving towards general flight model integration.
512  *
513  * Revision 1.5  1997/05/29 02:33:23  curt
514  * Updated to reflect changing interfaces in other "modules."
515  *
516  * Revision 1.4  1997/05/27 17:44:31  curt
517  * Renamed & rearranged variables and routines.   Added some initial simple
518  * timer/alarm routines so the flight model can be updated on a regular 
519  * interval.
520  *
521  * Revision 1.3  1997/05/23 15:40:25  curt
522  * Added GNU copyright headers.
523  * Fog now works!
524  *
525  * Revision 1.2  1997/05/23 00:35:12  curt
526  * Trying to get fog to work ...
527  *
528  * Revision 1.1  1997/05/21 15:57:51  curt
529  * Renamed due to added GLUT support.
530  *
531  * Revision 1.3  1997/05/19 18:22:42  curt
532  * Parameter tweaking ... starting to stub in fog support.
533  *
534  * Revision 1.2  1997/05/17 00:17:34  curt
535  * Trying to stub in support for standard OpenGL.
536  *
537  * Revision 1.1  1997/05/16 16:05:52  curt
538  * Initial revision.
539  *
540  */