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