]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel.cxx
Allow aircraft model file to be specified from the command line.
[flightgear.git] / src / Cockpit / panel.cxx
1 // panel.cxx -- routines to draw an instrument panel
2 //
3 // Written by Friedemann Reinhard, started June 1998.
4 //
5 // Copyright(C)1998 Friedemann Reinhard-reinhard@theorie2.physik.uni-erlangen.de
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 #define FILLED true
33
34 #include <GL/glut.h>
35 #include <XGL/xgl.h>
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <string>
41 #include <math.h>
42
43 #include <Debug/logstream.hxx>
44 #include <Aircraft/aircraft.hxx>
45 #include <Main/options.hxx>
46 #include <Main/views.hxx>
47 #include <Misc/fgpath.hxx>
48 #include <Objects/texload.h>
49
50 #include "panel.hxx"
51 #include "cockpit.hxx"
52 #include "hud.hxx"
53
54 GLubyte *imag;
55 int imag_width, imag_height;
56
57 GLubyte *img;
58 int img_width, img_height;
59
60 static float value[4];
61 static GLuint panel_tex_id[2];
62 static GLubyte tex[32][128][3];
63 static float alphahist;
64 static float Xzoom, Yzoom;
65 static Pointer pointer[20];
66 static int NumPoint = 4;
67 static int i = 0;
68 static GLdouble mvmatrix[16];
69 static GLdouble matrix[16];
70 static double var[20];
71 static double offset;
72 static float alpha;
73 static int n1;
74 static int n2;
75
76 static GLfloat Wings[] = {
77     -1.25, -28.125, 1.255, -28.125, 1.255, 28.125, -1.25, 28.125};
78     
79 static GLfloat Elevator[] = {
80     3.0, -10.9375, 4.5, -10.9375, 4.5, 10.9375, 3.0, 10.9375};
81     
82 static GLfloat Rudder[] = {
83     2.0, -0.45, 10.625, -0.45, 10.625, 0.55, 2.0, 0.55};
84
85 FGPanel* FGPanel::OurPanel = 0;
86
87 // FGPanel::FGPanel() - constructor to initialize the panel.                 
88 FGPanel::FGPanel(void){
89     int x, y;
90     FILE *f;
91     char line[256];
92     GLint test;
93     GLubyte *tex = new GLubyte[262144];
94     
95     if(OurPanel) {
96         FG_LOG( FG_GENERAL, FG_ALERT, "Error: only one Panel allowed" );
97         exit(-1);
98     }
99     
100     OurPanel = this;   
101     
102     Xzoom = (float)((float)(current_view.get_winWidth())/1024);
103     Yzoom = (float)((float)(current_view.get_winHeight())/768);
104     
105     test_instr[3] = new FGTexInstrument(144.375, 166.875, 4, 32, 3, 30, 15.0,
106                                         260.0, -20.0, 360, 65, 193, 0);
107     test_instr[4] = new FGTexInstrument(358, 52, 4, 30, 3, 30, -3.0, 3.0, 100,
108                                         440, 66.15, 66, 2);
109     test_instr[5] = new FGTexInstrument(357.5, 167, 5, 25, 4, 30, 0, 10000, 0,
110                                         360, 194, 191, 1);
111     test_instr[6] = new FGTexInstrument(357.5, 167, 5, 32, 3, 30, 0, 3000, 0,
112                                         1080, 194, 191, 1);
113     test_instr[0] = new FGHorizon(251, 166.75);
114     test_instr[1] = new FGTurnCoordinator(143.75, 51.75);
115     //test_instr[2] = new FGRpmGauge(462.5, 133);
116     test_instr[2] = new FGTexInstrument(462.5, 133, 10, 20, 5.5, 60, 0.0, 1.0,
117                                         -67, 180, 174, 83, 3); 
118     
119     // FontList = glGenLists (256);
120     // glListBase(FontList);
121     // InitLists();
122     
123 #ifdef GL_VERSION_1_1
124     xglGenTextures(2, panel_tex_id);
125     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[1]);
126 #elif GL_EXT_texture_object
127     xglGenTexturesEXT(2, panel_tex_id);
128     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[1]);
129 #else
130 #  error port me
131 #endif
132     
133     xglMatrixMode(GL_PROJECTION);
134     xglPushMatrix();
135     xglLoadIdentity();
136     xglViewport(0, 0, 640, 480);
137     xglOrtho(0, 640, 0, 480, 1, -1);
138     xglMatrixMode(GL_MODELVIEW);
139     xglPushMatrix();
140     xglLoadIdentity();
141     xglPixelStorei(GL_UNPACK_ALIGNMENT, 4);
142     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
143     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   
144     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
145     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
146     
147     // load in the texture data 
148     
149     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
150     FGPath tpath( current_options.get_fg_root() );
151     tpath.append( "Textures/gauges.rgb" );
152     if((img = read_rgb_texture( (char *)tpath.c_str(), &img_width,                      &img_height ))==NULL){
153     }
154     
155     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
156     tpath.set( current_options.get_fg_root() );
157     tpath.append( "Textures/gauges2.rgb" );
158     if((imag = read_rgb_texture( (char *)tpath.c_str(), &imag_width,                     &imag_height ))==NULL){
159     }
160     
161     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 1024);
162     
163     tpath.set( current_options.get_fg_root() );
164     tpath.append( "Textures/Fullone.rgb" );
165     if ((background = read_rgb_texture( (char *)tpath.c_str(), &width,                         &height ))==NULL ){
166     }
167     
168     //    for(y=0;y<256;y++){
169     //      for(x=0;x<256;x++){
170     //      tex[(y+x*256)*3] = imag[(y+x*256)*3];
171     //      tex[(y+x*256)*3 + 1] = imag[(y+x*256)*3 + 1];
172     //      tex[(y+x*256)*3 + 2] = imag[(y+x*256)*3 + 2];
173     //      tex[(y+x*256)*3 + 3] = (imag[(y+x*256)*3 + 1] + imag[(y+x*256)*3 + 2]   //                               + imag[(y+x*256)*3 + 0])/3;
174     //      
175     //  if((imag[(y+x*256)*3] < 150) && (imag[(y+x*256)*3 +1] < 150) &&         //             (imag[(y+x*256)*3 + 2] < 150) ){
176     //              tex[(y+x*256)*3 + 3] = 0x0;
177     //               }
178     //           else{
179     //             tex[(y+x*256)*3 + 3] = 0xff;
180     //             }
181     //       }
182     // }
183     
184     xglPixelZoom(Xzoom, Yzoom);
185     xglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
186     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 1024);
187     xglRasterPos2i(0,0);
188     xglPixelZoom(Xzoom, Yzoom);
189     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
190     xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB,                                   GL_UNSIGNED_BYTE, imag);
191     
192 #ifdef GL_VERSION_1_1
193     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[0]);
194 #elif GL_EXT_texture_object
195     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[0]);
196 #else
197 #  error port me
198 #endif
199     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
200     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   
201     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
202     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
203     xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB,                                  GL_UNSIGNED_BYTE, (GLvoid *)(img)); 
204     
205     xglMatrixMode(GL_MODELVIEW);
206     xglPopMatrix();
207 }
208
209 void FGPanel::ReInit( int x, int y, int finx, int finy){
210     fgOPTIONS *o;
211     FGView *v = &current_view;
212     int i;
213     GLint buffer;
214     
215     o = &current_options;
216     
217     xglDisable(GL_DEPTH_TEST);
218     
219     Xzoom = (float)((float)(current_view.get_winWidth())/1024);
220     Yzoom = (float)((float)(current_view.get_winHeight())/768);
221     
222     // save the current buffer state
223     xglGetIntegerv(GL_DRAW_BUFFER, &buffer);
224     
225     // and enable both buffers for writing
226     xglDrawBuffer(GL_FRONT_AND_BACK);
227     
228     xglMatrixMode(GL_PROJECTION);
229     xglPushMatrix();
230     xglLoadIdentity();
231     xglViewport(0, 0, 640, 480);
232     xglOrtho(0, 640, 0, 480, 1, -1);
233     xglMatrixMode(GL_MODELVIEW);
234     xglPushMatrix();
235     xglLoadIdentity();
236     xglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
237     xglPixelZoom(Xzoom, Yzoom);
238     xglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
239     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 1024);
240     xglPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
241     xglPixelStorei(GL_UNPACK_SKIP_ROWS, y);
242     xglRasterPos2i(x, y);
243     xglPixelZoom(Xzoom, Yzoom);
244     xglDrawPixels(finx - x, finy - y, GL_RGB, GL_UNSIGNED_BYTE,
245                   (GLvoid *)(background));
246     
247     // restore original buffer state
248     xglDrawBuffer( (GLenum)buffer );
249     xglEnable(GL_DEPTH_TEST);
250 }
251
252 void FGPanel::Update ( void ) {
253     
254     float alpha;
255     double pitch;
256     double roll;
257     float alpharad;
258     double speed;
259     int i;
260     
261     //    static bool beech_drawn = false;
262     //    char *test = "ALM 100";
263     
264     var[0] = get_speed() /* * 1.4 */; // We have to multiply the airspeed by a 
265     // factor, to simulate flying a Bonanza 
266     var[1] = get_altitude();
267     var[2] = get_climb_rate() / 1000.0; 
268     var[3] = get_throttleval();
269     
270     xglMatrixMode(GL_PROJECTION);
271     xglPushMatrix();
272     xglLoadIdentity();
273     xglOrtho(0, 640, 0, 480, 10, -10);
274     xglMatrixMode(GL_MODELVIEW);
275     xglPushMatrix();
276     xglLoadIdentity();
277     xglDisable(GL_DEPTH_TEST);
278     xglEnable(GL_LIGHTING);
279     xglEnable(GL_TEXTURE_2D);
280     xglDisable(GL_BLEND);
281     
282     xglMatrixMode(GL_MODELVIEW);
283     xglPopMatrix();
284     xglPushMatrix();
285     
286     xglDisable(GL_LIGHTING);
287     test_instr[3]->Render();
288     test_instr[4]->Render();
289     test_instr[5]->Render();
290     test_instr[6]->Render();
291     xglPopMatrix();
292     xglPushMatrix();
293     
294     test_instr[1]->Render();
295     test_instr[2]->Render();
296     
297     //   DrawBeechcraftLogo(230, 235, 30, 10);
298     //   DrawScale(144.375, 166.875, 38, 41.0, 18, 340, 44, 2.0, 1.0, 1.0, 1.0);
299     
300     xglEnable(GL_LIGHTING);
301     
302     test_instr[0]->Render();
303     
304     
305     xglDisable(GL_TEXTURE_2D);
306     xglPopMatrix();   
307     xglEnable(GL_DEPTH_TEST);
308     xglEnable(GL_LIGHTING);
309     xglDisable(GL_TEXTURE_2D);
310     xglDisable(GL_BLEND);
311     xglMatrixMode(GL_PROJECTION);
312     xglPopMatrix();
313     xglMatrixMode(GL_MODELVIEW);
314     xglPopMatrix();
315 }
316
317 // horizon - Let's draw an artificial horizon using both texture mapping and 
318 //           primitive drawing
319
320 void FGHorizon::Render(void){ 
321     double pitch;
322     double roll;
323     float shifted, alpha, theta;
324     float epsi = 360 / 180;
325     GLboolean Light;
326     GLfloat normal[2];
327     
328     static int n, dn, rot, tmp1, tmp2;
329     float a;
330     
331     GLfloat material[] = { 0.714844, 0.265625, 0.056875 ,1.0};
332     GLfloat material2[] = {0.6640625, 0.921875, 0.984375, 1.0};
333     GLfloat material3[] = {0.2, 0.2, 0.2, 1.0};
334     GLfloat material4[] = {0.8, 0.8, 0.8, 1.0};
335     GLfloat material5[] = {0.0, 0.0, 0.0, 1.0};
336     GLfloat direction[] = {0.0, 0.0, 0.0};
337     GLfloat light_position[4];
338     GLfloat light_ambient[] = {0.7, 0.7, 0.7, 1.0};
339     GLfloat light_ambient2[] = {0.7, 0.7, 0.7, 1.0};
340     GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
341     GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
342     
343     pitch = get_pitch() * RAD_TO_DEG;
344     if(pitch > 45)
345         pitch = 45;
346     
347     if(pitch < -45)
348         pitch = -45;
349     
350     roll = get_roll() * RAD_TO_DEG;
351     
352     xglEnable(GL_NORMALIZE);
353     xglEnable(GL_LIGHTING);
354     xglEnable(GL_TEXTURE_2D);
355     xglEnable(GL_LIGHT1);
356     xglDisable(GL_LIGHT2);
357     xglDisable(GL_LIGHT0);
358     xglMatrixMode(GL_MODELVIEW);
359     xglLoadIdentity();
360     xglTranslatef(XPos, YPos, 0);
361     xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
362     xglMatrixMode(GL_TEXTURE);
363     xglPushMatrix();
364     
365     // computations for the non-textured parts of the AH
366     
367     shifted = -((pitch / 10) * 7.0588235);
368     
369     if(shifted > (bottom - radius)){
370         theta = (180 - (acos((bottom - shifted) / radius)*RAD_TO_DEG));
371         n = (int)(theta / epsi) - 1;
372         n1 = n;
373         n2 = (180 - n1) + 2;
374         dn = n2 - n1;
375         rot = (int)(roll / epsi);
376         n1 += rot + 45;
377         n2 += rot + 45;
378     }
379     
380     if(shifted < (-top + radius)){
381         theta = ((acos((-top - shifted) / radius)*RAD_TO_DEG));
382         n = (int)(theta / epsi) + 1;
383         n1 = n;
384         n2 = (180 - n1) + 2;
385         dn = n2 - n1;
386         rot = (int)(roll / epsi);
387         n1 += rot - 45;
388         n2 += rot - 45;
389         if(n1 < 0){ n1 += 180; n2 +=180;}
390     }
391     
392     // end of computations  
393     
394     light_position[0] = 0.0;
395     light_position[1] = 0.0; 
396     light_position[2] = 1.5;
397     light_position[3] = 0.0;
398     xglLightfv(GL_LIGHT1, GL_POSITION, light_position);
399     xglLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);  
400     xglLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
401     xglLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
402     xglLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, direction);
403     
404 #ifdef GL_VERSION_1_1
405     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[1]);
406 #elif GL_EXT_texture_object
407     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[1]);
408 #else
409 #  error port me
410 #endif
411     
412     xglLoadIdentity();
413     xglTranslatef(0.0, ((pitch / 10) * 0.046875), 0.0);
414     xglTranslatef((texXPos/256), (texYPos/256), 0.0);
415     xglRotatef(-roll, 0.0, 0.0, 1.0);
416     xglScalef(1.7, 1.7, 0.0);
417     
418     // the following loop draws the textured part of the AH
419     
420     xglMaterialf(GL_FRONT, GL_SHININESS, 85.0);
421     
422     xglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material4);
423     xglMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material5);
424     xglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material3);
425     
426     xglMatrixMode(GL_MODELVIEW);
427     xglBegin(GL_TRIANGLES);
428     for(i=45;i<225;i++){
429         xglTexCoord2f(0.0, 0.0);
430         xglNormal3f(0.0, 0.0, 0.6);
431         xglVertex3f(0.0, 0.0, 0.0);
432         xglTexCoord2f(texCoord[i % 180][0], texCoord[i % 180][1]);
433         xglNormal3f(normals[i % 180][0], normals[i % 180][1], 0.6);
434         xglVertex3f(vertices[i % 180][0], vertices[i % 180][1], 0.0);
435         n = (i + 1) % 180;
436         xglTexCoord2f(texCoord[n][0], texCoord[n][1]);
437         xglNormal3f(normals[n][0], normals[n][1], 0.6);
438         xglVertex3f(vertices[n][0], vertices[n][1], 0.0);
439     }
440     xglEnd();
441     
442     
443     if((shifted > (bottom - radius)) && (n1 < 1000) && (n1 > 0)){
444         
445         a = sin(theta * DEG_TO_RAD) * sin(theta * DEG_TO_RAD);
446         light_ambient2[0] = a;
447         light_ambient2[1] = a;
448         light_ambient2[2] = a;
449         
450         xglLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient2);
451         xglLightfv(GL_LIGHT1, GL_DIFFUSE, light_ambient2); 
452         xglLightfv(GL_LIGHT1, GL_SPECULAR, light_ambient2);
453         
454         xglBegin(GL_TRIANGLES);
455         
456         tmp1 = n1; tmp2 = n2;
457         
458         for(i = tmp1; i < tmp2 + 1; i++){
459             n = i % 180;
460             xglNormal3f(0.0, 0.0, 1.5);
461             xglTexCoord2f((56 / 256), (140 / 256));
462             xglVertex3f(((vertices[n1 % 180][0] + vertices[n2 % 180][0]) / 2),                            ((vertices[n1 % 180][1] + vertices[n2 % 180][1]) / 2),                             0.0);
463             
464             xglTexCoord2f((57 / 256), (139 / 256));        
465             xglNormal3f(normals[n][0], normals[n][1], normals[n][3]);
466             xglVertex3f(vertices[n][0], vertices[n][1], 0.0);
467             
468             n = (i + 1) % 180;
469             xglTexCoord2f((57 / 256), (139 / 256));      
470             xglNormal3f(normals[n][0], normals[n][1], normals[n][3]);
471             xglVertex3f(vertices[n][0], vertices[n][1], 0.0);        
472         }
473         xglEnd();
474     }
475     
476     if((shifted < (-top + radius)) && (n1 < 1000) && (n1 > 0)){
477         a = sin(theta * DEG_TO_RAD) * sin(theta * DEG_TO_RAD);
478         light_ambient2[0] = a;
479         light_ambient2[1] = a;
480         light_ambient2[2] = a;
481         
482         xglLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient2);
483         xglLightfv(GL_LIGHT1, GL_DIFFUSE, light_ambient2); 
484         xglLightfv(GL_LIGHT1, GL_SPECULAR, light_ambient2);
485         xglMaterialf(GL_FRONT, GL_SHININESS, a * 85);
486         xglBegin(GL_TRIANGLES);
487         tmp1 = n1; tmp2 = n2;
488         for(i = tmp1; i <= tmp2; i++){
489             n = i % 180;
490             xglNormal3f(0.0, 0.0, 1.5);
491             xglTexCoord2f((73 / 256), (237 / 256));
492             xglVertex3f(((vertices[n1 % 180][0] + vertices[n2 % 180][0]) / 2),                            ((vertices[n1 % 180][1] + vertices[n2 % 180][1]) / 2), 0.0); 
493             
494             xglTexCoord2f((73 / 256), (236 / 256));
495             xglNormal3f(normals[n][0], normals[n][1], normals[n][2]);
496             xglVertex3f(vertices[n][0], vertices[n][1], 0.0);
497             
498             n = (i + 1) % 180;
499             xglTexCoord2f((73 / 256), (236 / 256)); 
500             xglNormal3f(normals[n][0], normals[n][1], normals[n][2]);
501             xglVertex3f(vertices[n][0], vertices[n][1], 0.0); 
502         }
503         xglEnd();
504     }
505     
506     // Now we will have to draw the small triangle indicating the roll value
507     
508     xglDisable(GL_LIGHTING);
509     xglDisable(GL_TEXTURE_2D);
510     
511     xglRotatef(roll, 0.0, 0.0, 1.0);
512     
513     xglBegin(GL_TRIANGLES);
514     xglColor3f(1.0, 1.0, 1.0);
515     xglVertex3f(0.0, radius, 0.0);
516     xglVertex3f(-3.0, (radius - 7.0), 0.0);
517     xglVertex3f(3.0, (radius - 7.0), 0.0);    
518     xglEnd();
519     
520     xglLoadIdentity();
521     
522     xglBegin(GL_POLYGON);
523     xglColor3f(0.2109375, 0.23046875, 0.203125);
524     xglVertex2f(275.625, 138.0);
525     xglVertex2f(275.625, 148.125);
526     xglVertex2f(258.125, 151.25);
527     xglVertex2f(246.875, 151.25);
528     xglVertex2f(226.875, 147.5);
529     xglVertex2f(226.875, 138.0);
530     xglVertex2f(275.625, 138.0);
531     xglEnd();
532     
533     xglLoadIdentity();
534     
535     xglMatrixMode(GL_TEXTURE);
536     xglPopMatrix();
537     xglMatrixMode(GL_PROJECTION);
538     xglPopMatrix();
539     xglDisable(GL_TEXTURE_2D);
540     xglDisable(GL_NORMALIZE);
541     xglDisable(GL_LIGHTING);
542     xglDisable(GL_LIGHT1);
543     xglEnable(GL_LIGHT0);
544 }
545
546 // fgHorizonInit - initialize values for the AH
547
548 void FGHorizon::Init(void){
549     radius = 28.9;
550     texXPos = 56;
551     texYPos = 174;
552     bottom = 36.5;
553     top = 36.5;
554     int n;
555     
556     float step = (360*DEG_TO_RAD)/180;
557     
558     for(n=0;n<180;n++){
559         vertices[n][0] = cos(n * step) * radius;
560         vertices[n][1] = sin(n * step) * radius;
561         texCoord[n][0] = (cos(n * step) * radius)/256;
562         texCoord[n][1] = (sin(n * step) * radius)/256;
563         normals[n][0] = cos(n * step) * radius + sin(n * step);
564         normals[n][1] = sin(n * step) * radius + cos(n * step);
565         normals[n][2] = 0.0;
566     }
567 }
568
569 void FGTexInstrument::UpdatePointer(void){
570     double pitch;
571     double roll;
572     float alpharad;
573     double speed;    
574     glEnableClientState(GL_VERTEX_ARRAY);
575     glVertexPointer(2, GL_FLOAT, 0, vertices);
576     
577     alpha=((((float)((var[variable]) - (value1))) /
578             (value2 - value1))* (alpha2 - alpha1) + alpha1);
579     
580     if (alpha < alpha1)
581         alpha = alpha1;
582     if (alpha > alpha2)
583         alpha -= alpha2;
584     xglMatrixMode(GL_MODELVIEW);  
585     xglPushMatrix();
586     xglLoadIdentity();
587     xglDisable(GL_TEXTURE_2D);
588     xglTranslatef(XPos, YPos, 0);
589     xglRotatef(-alpha, 0.0, 0.0, 1.0);
590     xglColor4f(1.0, 1.0, 1.0, 1.0);
591     glDrawArrays(GL_POLYGON, 0, 10);
592     tape[0] = tape[1];
593     tape[1] = alpha;
594     xglEnable(GL_TEXTURE_2D);
595     glDisableClientState(GL_VERTEX_ARRAY);
596 }
597
598 // fgEraseArea - 'Erases' a drawn Polygon by overlaying it with a textured 
599 //                 area. Shall be a method of a panel class once.
600
601 void fgEraseArea(GLfloat *array, int NumVerti, GLfloat texXPos,                                  GLfloat texYPos, GLfloat XPos, GLfloat YPos,                                    int Texid, float ScaleFactor){
602     int i, j;
603     int n;
604     float a;
605     float ififth;
606     
607     xglEnable(GL_TEXTURE_2D);
608     xglEnable(GL_TEXTURE_GEN_S);
609     xglEnable(GL_TEXTURE_GEN_T);
610     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
611     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
612     xglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
613     xglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
614     xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
615     xglMatrixMode(GL_TEXTURE);
616     xglLoadIdentity();
617     
618 #ifdef GL_VERSION_1_1
619     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[Texid]);
620 #elif GL_EXT_texture_object
621     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[Texid]);
622 #else
623 #  error port me
624 #endif
625     
626     xglMatrixMode(GL_TEXTURE);
627     xglLoadIdentity();
628     xglTranslatef(-((float)((XPos/0.625)/256)),                                                   -((float)((YPos/0.625)/256)), 0.0);
629     xglTranslatef(texXPos/256 , texYPos/256, 0.0);
630     xglScalef(0.00625, 0.00625, 1.0);
631     
632     xglBegin(GL_POLYGON);
633     for(n=0;n<NumVerti;n += 2){ 
634         xglVertex2f(array[n] * ScaleFactor, array[n + 1] * ScaleFactor);
635     } 
636     xglEnd();
637     
638     xglLoadIdentity();
639     xglMatrixMode(GL_MODELVIEW);
640     xglPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
641     xglPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
642     xglDisable(GL_TEXTURE_2D);
643     xglDisable(GL_TEXTURE_GEN_S);
644     xglDisable(GL_TEXTURE_GEN_T);
645     
646 }
647
648 // CreatePointer - calculate the vertices of a pointer 
649
650 void FGTexInstrument::CreatePointer(void){
651     int i;
652     float alpha;
653     float alphastep;
654     float r = radius;
655     
656     vertices[0] = 0;
657     vertices[1] = length;
658     vertices[2] = -(width/2);
659     vertices[3] = length - ((width/2)/(tan(angle*DEG_TO_RAD/2)));
660     vertices[4] = -(width/2);
661     vertices[5] = cos(asin((width/2)/r))*r;
662     
663     alphastep = (asin((width/2)/r)+asin((width/2)/r))/5;
664     alpha = asin(-(width/2)/r);
665     
666     for(i=0;i<5;i++){
667         alpha += alphastep;
668         vertices[(i*2)+6] = sin(alpha)*r;
669     }
670     
671     alpha = asin(-(width/2)/r);
672     
673     for(i=0;i<5;i++){
674         alpha +=alphastep;
675         vertices[(i*2)+7]= cos(alpha)*r;
676     }
677     
678     vertices[16] = - vertices[4];
679     vertices[17] = vertices[5];
680     vertices[18] = - vertices[2];
681     vertices[19] = vertices[3];
682     
683 }
684
685 // fgUpdateTurnCoordinator - draws turn coordinator related stuff
686
687 void FGTurnCoordinator::Render(void){
688     int n;
689     
690     xglDisable(GL_LIGHTING);
691     xglDisable(GL_BLEND);
692     xglEnable(GL_TEXTURE_2D);
693     
694     alpha = (get_sideslip() / 1.5) * 560;
695     if(alpha > 56){
696         alpha = 56;
697     }
698     if(alpha < -56){
699         alpha = -56;
700     }
701     
702     PlaneAlpha = get_roll();
703     
704     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
705     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
706     xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
707     
708     xglMatrixMode(GL_MODELVIEW);
709     xglLoadIdentity();
710     xglTranslatef(BallXPos, BallYPos, 0.0);
711     xglTranslatef(0.75 * sin(alphahist[0] * DEG_TO_RAD) * 31,                                     0.3 * (39 - (cos(alphahist[0] * DEG_TO_RAD) * 39)),                             0.0);
712     fgEraseArea(vertices, 72, BallTexXPos +                                                     ((0.75 * sin(alphahist[0] * DEG_TO_RAD) * 31) / 0.625),                         BallTexYPos + ((0.3 * (39 - (cos(alphahist[0] * DEG_TO_RAD)                                  * 39))) / 0.625),                                                   BallXPos + (0.75 * sin(alphahist[0] * DEG_TO_RAD) * 31),                       BallYPos + (0.3 * (39 - (cos(alphahist[0] * DEG_TO_RAD)                         * 39))), 1, 1);
713     xglDisable(GL_TEXTURE_2D);
714     xglEnable(GL_BLEND);
715     xglBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE);
716     xglMatrixMode(GL_MODELVIEW);
717     xglLoadIdentity();
718     xglTranslatef(BallXPos, BallYPos, 0.0);
719     xglTranslatef(0.75 * sin(alpha * DEG_TO_RAD) * 31,                                            0.3 * (39 - (cos(alpha * DEG_TO_RAD) * 39)), 0.0);
720     xglBegin(GL_POLYGON);
721     xglColor3f(0.8, 0.8, 0.8);
722     for(i=0;i<36;i++){
723         xglVertex2f(vertices[2 * i],                                                                vertices[(2 * i) + 1]);
724     }
725     xglEnd(); 
726     
727     xglDisable(GL_TEXTURE_2D);
728     xglDisable(GL_BLEND);
729     
730     xglMatrixMode(GL_MODELVIEW);
731     xglLoadIdentity();
732     xglTranslatef(XPos, YPos, 0.0);
733     xglRotatef(rollhist[0] * RAD_TO_DEG + 90, 0.0, 0.0, 1.0);
734     
735     fgEraseArea(Wings, 8, PlaneTexXPos, PlaneTexYPos,                                                     XPos, YPos, 1, 1); 
736     fgEraseArea(Elevator, 8, PlaneTexXPos, PlaneTexYPos,                                                     XPos, YPos, 1, 1); 
737     fgEraseArea(Rudder, 8, PlaneTexXPos, PlaneTexYPos,                                                     XPos, YPos, 1, 1); 
738     
739     xglLoadIdentity();
740     xglTranslatef(XPos, YPos, 0.0);
741     xglRotatef(-get_roll() * RAD_TO_DEG + 90, 0.0, 0.0, 1.0);
742     
743     xglBegin(GL_POLYGON);
744     xglColor3f(1.0, 1.0, 1.0);
745     for(i=0;i<90;i++){
746         xglVertex2f(cos(i * 4 * DEG_TO_RAD) * 5, sin(i * 4 * DEG_TO_RAD) * 5);
747     }
748     xglEnd();
749     
750     xglBegin(GL_POLYGON);
751     xglVertex2f(Wings[0], Wings[1]);
752     xglVertex2f(Wings[2], Wings[3]);
753     xglVertex2f(Wings[4], Wings[5]);
754     xglVertex2f(Wings[6], Wings[7]);
755     xglVertex2f(Wings[0], Wings[1]);
756     xglEnd();
757     
758     xglBegin(GL_POLYGON);
759     xglVertex2f(Elevator[0], Elevator[1]);
760     xglVertex2f(Elevator[2], Elevator[3]);
761     xglVertex2f(Elevator[4], Elevator[5]);
762     xglVertex2f(Elevator[6], Elevator[7]);
763     xglVertex2f(Elevator[0], Elevator[1]);
764     xglEnd();
765     
766     xglBegin(GL_POLYGON);
767     xglVertex2f(Rudder[0], Rudder[1]);
768     xglVertex2f(Rudder[2], Rudder[3]);
769     xglVertex2f(Rudder[4], Rudder[5]);
770     xglVertex2f(Rudder[6], Rudder[7]);
771     xglVertex2f(Rudder[0], Rudder[1]);
772     xglEnd();
773     
774     
775     alphahist[0] = alphahist[1];
776     alphahist[1] = alpha;
777     rollhist[0] = rollhist[1];
778     rollhist[1] = -get_roll();
779     
780     xglDisable(GL_BLEND);
781 }
782
783 void FGTurnCoordinator::Init(void){
784     int n;
785     PlaneTexXPos = 49;
786     PlaneTexYPos = 59.75;
787     BallXPos = 145;
788     BallYPos = 24;
789     BallTexXPos = 49;
790     BallTexYPos = 16;
791     BallRadius = 3.5;
792     
793     for(n=0;n<36;n++){
794         vertices[2 * n] = cos(10 * n * DEG_TO_RAD) * BallRadius;
795         vertices[(2 * n) + 1] = sin(10 * n * DEG_TO_RAD) * BallRadius;
796     }   
797 }
798
799 void DrawScale(float XPos, float YPos, float InnerRadius, float OuterRadius,                   float alpha1, float alpha2, int steps, float LineWidth,
800                float red, float green, float blue, bool filled){
801     int i;
802     float diff = (alpha2 - alpha1) / (float)(steps - 1);
803     
804 #define ANTIALIASED_INSTRUMENTS
805     
806 #ifdef ANTIALIASED_INSTRUMENTS
807     xglEnable(GL_LINE_SMOOTH);
808     xglEnable(GL_BLEND);
809     xglHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
810 #endif
811     
812     xglMatrixMode(GL_MODELVIEW);
813     xglLoadIdentity();
814     
815     xglTranslatef(XPos, YPos, 0.0);
816     xglRotatef(-alpha1, 0.0, 0.0, 1.0);
817     
818     xglLineWidth(LineWidth);
819     xglColor3f(red, green, blue);
820     
821     if(!filled){
822         xglBegin(GL_LINES);
823     }
824     else{
825         xglBegin(GL_QUAD_STRIP);
826     }
827     
828     for(i=0;i < steps; i++){
829         xglVertex3f(sin(i * diff * DEG_TO_RAD) * OuterRadius,
830                     cos(i * diff * DEG_TO_RAD) * OuterRadius,
831                     0.0);
832         xglVertex3f(sin(i * diff * DEG_TO_RAD) * InnerRadius,
833                     cos(i * diff * DEG_TO_RAD) * InnerRadius,
834                     0.0);
835     }
836     xglEnd();
837     
838     xglLoadIdentity();
839     xglDisable(GL_LINE_SMOOTH);
840     xglDisable(GL_BLEND);
841 }
842
843 void DrawBeechcraftLogo(float XPos, float YPos, float width, float height){
844     xglMatrixMode(GL_MODELVIEW);
845     xglLoadIdentity();
846     xglTranslatef(XPos, YPos, 0.0);
847     xglEnable(GL_BLEND);
848     xglEnable(GL_TEXTURE_2D);
849     //   xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
850     //   xglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
851     
852 #ifdef GL_VERSION_1_1
853     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[1]);
854 #elif GL_EXT_texture_object
855     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[1]);
856 #else
857 #  error port me
858 #endif
859     
860     xglBegin(GL_POLYGON);
861     
862     xglTexCoord2f(.39844, .01953);
863     xglVertex2f(0.0, 0.0);
864     xglTexCoord2f(.58594, .01953);
865     xglVertex2f(width, 0.0);
866     xglTexCoord2f(.58594, .074219);
867     xglVertex2f(width, height);
868     xglTexCoord2f(.39844, .074219);
869     xglVertex2f(0.0, height);
870     
871     xglEnd();
872     
873     xglDisable(GL_BLEND);
874     xglDisable(GL_TEXTURE_2D);
875 }
876
877
878 // PrintMatrix - routine to print the current modelview matrix.                 
879
880 void PrintMatrix( void){
881     xglGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
882     printf("matrix2 = %f %f %f %f \n",
883            mvmatrix[0], mvmatrix[1], mvmatrix[2], mvmatrix[3]);
884     printf("         %f %f %f %f \n",
885            mvmatrix[4], mvmatrix[5], mvmatrix[6], mvmatrix[7]);
886     printf("         %f %f %f %f \n",
887            mvmatrix[8], mvmatrix[9], mvmatrix[10], mvmatrix[11]);
888     printf("         %f %f %f %f \n",
889            mvmatrix[12], mvmatrix[13], mvmatrix[14], mvmatrix[15]);
890 }
891
892 void FGRpmGauge::Init(void){
893     list = xglGenLists (1);
894     int n;
895     
896     xglNewList(list, GL_COMPILE);
897     
898     xglColor3f(.26, .289, .3281);
899     xglBegin(GL_POLYGON);
900     for(n = 0; n < 180; n++){
901         xglVertex2f(cos(n * 0.0349066) * 24.5, sin(n * 0.0349066) * 24.5);
902     }
903     xglEnd();
904     
905     DrawScale(XPos, YPos, 22.5, 25.625, 50, 135, 10, 1.0, 0.0, 0.7, 0.0,FILLED);
906     DrawScale(XPos, YPos, 21.0, 25.625, -70, 180, 8, 1.8, 0.88, 0.88, 0.88, false);
907     DrawScale(XPos, YPos, 22.5, 25.0, -70, 180, 40, 0.6, 0.5, 0.5, 0.5, false);
908     
909     xglEndList();
910 }
911
912 void FGRpmGauge::Render(void){
913     xglMatrixMode(GL_MODELVIEW);
914     xglLoadIdentity();
915     xglTranslatef(XPos, YPos, 0.0);
916     
917     xglCallList(list);
918     
919 }
920
921 void FGPanel::DrawTestLetter(float X, float Y){
922     xglEnable(GL_TEXTURE_2D);
923     xglEnable(GL_BLEND);
924     
925     xglMatrixMode(GL_TEXTURE);
926     xglLoadIdentity();
927     xglTranslatef(X, Y, 0.0);
928     
929     DrawLetter();
930     
931     xglMatrixMode(GL_MODELVIEW); 
932     xglTranslatef(6.0, 0.0, 0.0);
933     xglDisable(GL_TEXTURE_2D);
934     xglDisable(GL_BLEND);
935 }
936
937 void FGPanel::InitLists(void){
938     xglNewList(FontList + 'A', GL_COMPILE);
939     DrawTestLetter(0.391625, 0.29296875);
940     xglEndList();
941     
942     xglNewList(FontList + 'B', GL_COMPILE);
943     DrawTestLetter(0.391625 + 1 * LETTER_OFFSET, 0.29296875);
944     xglEndList();
945     
946     xglNewList(FontList + 'C', GL_COMPILE);
947     DrawTestLetter(0.391625 + 2 * LETTER_OFFSET, 0.29296875);
948     xglEndList();
949     
950     xglNewList(FontList + 'D', GL_COMPILE);
951     DrawTestLetter(0.391625 + 3 * LETTER_OFFSET, 0.29296875);
952     xglEndList();
953     
954     xglNewList(FontList + 'E', GL_COMPILE);
955     DrawTestLetter(0.391625 + 4 * LETTER_OFFSET, 0.29296875);
956     xglEndList();
957     
958     xglNewList(FontList + 'F', GL_COMPILE);
959     DrawTestLetter(0.391625 + 5 * LETTER_OFFSET, 0.29296875);
960     xglEndList();
961     
962     xglNewList(FontList + 'G', GL_COMPILE);
963     DrawTestLetter(0.391625 + 6 * LETTER_OFFSET, 0.29296875);
964     xglEndList();
965     
966     xglNewList(FontList + 'H', GL_COMPILE);
967     DrawTestLetter(0.391625 + 7 * LETTER_OFFSET, 0.29296875);
968     xglEndList();
969     
970     xglNewList(FontList + 'I', GL_COMPILE);
971     DrawTestLetter(0.391625 + 8 * LETTER_OFFSET, 0.29296875);
972     xglEndList();
973     
974     xglNewList(FontList + 'J', GL_COMPILE);
975     DrawTestLetter(0.391625 + 9 * LETTER_OFFSET, 0.29296875);
976     xglEndList();
977     
978     xglNewList(FontList + 'K', GL_COMPILE);
979     DrawTestLetter(0.391625 + 9.7 * LETTER_OFFSET, 0.29296875);
980     xglEndList();
981     
982     xglNewList(FontList + 'L', GL_COMPILE);
983     DrawTestLetter(0.399625 + 10.6 * LETTER_OFFSET, 0.29296875);
984     xglEndList();
985     
986     xglNewList(FontList + 'M', GL_COMPILE);
987     DrawTestLetter(0.80459375, 0.29296875);
988     xglEndList();
989     
990     xglNewList(FontList + 'N', GL_COMPILE);
991     DrawTestLetter(0.83975, 0.29296875);
992     xglEndList();
993     
994     xglNewList(FontList + 'O', GL_COMPILE);
995     DrawTestLetter(0.871, 0.29296875);
996     xglEndList();
997     
998     xglNewList(FontList + 'P', GL_COMPILE);
999     DrawTestLetter(0.90715625, 0.29296875);
1000     xglEndList();
1001     
1002     xglNewList(FontList + 'Q', GL_COMPILE);
1003     DrawTestLetter(0.9413125, 0.29296875);
1004     xglEndList();
1005     
1006     xglNewList(FontList + '1', GL_COMPILE);
1007     DrawTestLetter(0.390625, 0.35546875);
1008     xglEndList();
1009     
1010     xglNewList(FontList + '2', GL_COMPILE);
1011     DrawTestLetter(0.390625 + 1*LETTER_OFFSET, 0.3515625); 
1012     xglEndList();
1013     
1014     xglNewList(FontList + '3', GL_COMPILE);
1015     DrawTestLetter(0.390625 + 2*LETTER_OFFSET, 0.3515625); 
1016     xglEndList();
1017     
1018     xglNewList(FontList + '4', GL_COMPILE);
1019     DrawTestLetter(0.390625 + 3*LETTER_OFFSET, 0.3515625); 
1020     xglEndList();
1021     
1022     xglNewList(FontList + '5', GL_COMPILE);
1023     DrawTestLetter(0.390625 + 4*LETTER_OFFSET, 0.3515625); 
1024     xglEndList();
1025     
1026     xglNewList(FontList + '6', GL_COMPILE);
1027     DrawTestLetter(0.390625 + 5*LETTER_OFFSET, 0.3515625); 
1028     xglEndList();
1029     
1030     xglNewList(FontList + '7', GL_COMPILE);
1031     DrawTestLetter(0.390625 + 6*LETTER_OFFSET, 0.3515625); 
1032     xglEndList();
1033     
1034     xglNewList(FontList + '8', GL_COMPILE);
1035     DrawTestLetter(0.390625 + 7*LETTER_OFFSET, 0.3515625); 
1036     xglEndList();
1037     
1038     xglNewList(FontList + '9', GL_COMPILE);
1039     DrawTestLetter(0.390625 + 8*LETTER_OFFSET, 0.3515625); 
1040     xglEndList();
1041     
1042     xglNewList(FontList + '0', GL_COMPILE);
1043     DrawTestLetter(0.383625 + 9*LETTER_OFFSET, 0.3515625); 
1044     xglEndList();
1045     
1046     xglNewList(FontList + ' ', GL_COMPILE);
1047     xglTranslatef(8.0, 0.0, 0.0);
1048     xglEndList();
1049 }
1050
1051 void FGPanel::TexString(char *s, float XPos, float YPos, float size){
1052     xglMatrixMode(GL_MODELVIEW);
1053     xglLoadIdentity();
1054     xglTranslatef(XPos, YPos, 0.0);
1055     xglScalef(size, size, 1.0);
1056     
1057 #ifdef GL_VERSION_1_1
1058     xglBindTexture(GL_TEXTURE_2D, panel_tex_id[1]);
1059 #elif GL_EXT_texture_object
1060     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id[1]);
1061 #else
1062 #  error port me
1063 #endif
1064     
1065     while((*s) != '\0'){
1066         xglCallList(FontList + (*s));
1067         s++;
1068     }
1069     xglLoadIdentity();
1070 }
1071
1072 void FGTexInstrument::Init(void){
1073     CreatePointer();
1074 }
1075
1076 void FGTexInstrument::Render(void){
1077     xglEnable(GL_TEXTURE_2D);
1078     xglLoadIdentity();
1079     xglTranslatef(XPos, YPos, 0.0);
1080     xglRotatef(-tape[0], 0.0, 0.0, 1.0);
1081     fgEraseArea(vertices, 20, (GLfloat)(teXpos),                                               (GLfloat)(texYpos), (GLfloat)(XPos),                                            (GLfloat)(YPos), 0, 1);
1082     
1083     UpdatePointer();
1084     
1085     xglDisable(GL_TEXTURE_2D);
1086 }