]> git.mxchange.org Git - flightgear.git/blob - Cockpit/panel.cxx
Contributions from Bernie Bright <bbright@c031.aone.net.au>
[flightgear.git] / Cockpit / panel.cxx
1 /**************************************************************************
2  * panel.cxx -- routines to draw an instrument panel
3  *
4  * Written by Friedemann Reinhard, started June 1998.
5  *
6  * Copyright (C) 1997  Michele F. America  - nomimarketing@mail.telepac.pt
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 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30
31 #ifdef HAVE_WINDOWS_H          
32 #  include <windows.h>
33 #endif
34
35 #include <GL/glut.h>
36 #include <XGL/xgl.h>
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <string>
42
43 #include <Aircraft/aircraft.h>
44 #include <Debug/fg_debug.h>
45 #include <Main/options.hxx>
46
47 #include "panel.hxx"
48
49   // Intriquing. Needs documentation.
50
51 #define IMAGIC      0x01da
52 #define IMAGIC_SWAP 0xda01
53
54 #define SWAP_SHORT_BYTES(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
55 #define SWAP_LONG_BYTES(x) (((((x) & 0xff) << 24) | (((x) & 0xff00) << 8)) | \
56 ((((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)))
57
58 typedef struct {
59     unsigned short imagic;
60     unsigned short type;
61     unsigned short dim;
62     unsigned short sizeX, sizeY, sizeZ;
63     unsigned long min, max;
64     unsigned long wasteBytes;
65     char name[80];
66     unsigned long colorMap;
67     FILE *file;
68     unsigned char *tmp[5];
69     unsigned long rleEnd;
70     unsigned long *rowStart;
71     unsigned long *rowSize;
72 } Image;
73
74
75 IMAGE *img;
76
77 static GLuint panel_list;
78 static GLuint panel_tex_id;
79 static GLubyte tex[512][256][4];
80
81
82 extern double get_speed( void );
83
84
85 /* image.c ,temporary hack, I know*/
86 static Image *ImageOpen(char *fileName)
87 {
88   Image *image;
89   unsigned long *rowStart, *rowSize, ulTmp;
90   int x, i;
91
92   image = (Image *)malloc(sizeof(Image));
93   if (image == NULL) 
94     {
95       fprintf(stderr, "Out of memory!\n");
96       exit(-1);
97     }
98   if ((image->file = fopen(fileName, "rb")) == NULL) 
99     {
100       perror(fileName);
101       exit(-1);
102     }
103   /*
104    *    Read the image header
105    */
106   fread(image, 1, 12, image->file);
107   /*
108    *    Check byte order
109    */
110   if (image->imagic == IMAGIC_SWAP) 
111     {
112       image->type = SWAP_SHORT_BYTES(image->type);
113       image->dim = SWAP_SHORT_BYTES(image->dim);
114       image->sizeX = SWAP_SHORT_BYTES(image->sizeX);
115       image->sizeY = SWAP_SHORT_BYTES(image->sizeY);
116       image->sizeZ = SWAP_SHORT_BYTES(image->sizeZ);
117     }
118
119   for ( i = 0 ; i <= image->sizeZ ; i++ )
120     {
121       image->tmp[i] = (unsigned char *)malloc(image->sizeX*256);
122       if (image->tmp[i] == NULL ) 
123         {
124           fprintf(stderr, "Out of memory!\n");
125           exit(-1);
126         }
127     }
128
129   if ((image->type & 0xFF00) == 0x0100) /* RLE image */
130     {
131       x = image->sizeY * image->sizeZ * sizeof(long);
132       image->rowStart = (unsigned long *)malloc(x);
133       image->rowSize = (unsigned long *)malloc(x);
134       if (image->rowStart == NULL || image->rowSize == NULL) 
135         {
136           fprintf(stderr, "Out of memory!\n");
137           exit(-1);
138         }
139       image->rleEnd = 512 + (2 * x);
140       fseek(image->file, 512, SEEK_SET);
141       fread(image->rowStart, 1, x, image->file);
142       fread(image->rowSize, 1, x, image->file);
143       if (image->imagic == IMAGIC_SWAP) 
144         {
145           x /= sizeof(long);
146           rowStart = image->rowStart;
147           rowSize = image->rowSize;
148           while (x--) 
149             {
150               ulTmp = *rowStart;
151               *rowStart++ = SWAP_LONG_BYTES(ulTmp);
152               ulTmp = *rowSize;
153               *rowSize++ = SWAP_LONG_BYTES(ulTmp);
154             }
155         }
156     }
157   return image;
158 }
159
160 static void ImageClose( Image *image)
161 {
162   int i;
163
164   fclose(image->file);
165   for ( i = 0 ; i <= image->sizeZ ; i++ )
166     free(image->tmp[i]);
167   free(image);
168 }
169
170 static void ImageGetRow( Image *image, unsigned char *buf, int y, int z)
171 {
172   unsigned char *iPtr, *oPtr, pixel;
173   int count;
174
175   if ((image->type & 0xFF00) == 0x0100)  /* RLE image */
176     {
177       fseek(image->file, image->rowStart[y+z*image->sizeY], SEEK_SET);
178       fread(image->tmp[0], 1, (unsigned int)image->rowSize[y+z*image->sizeY],
179             image->file);
180
181       iPtr = image->tmp[0];
182       oPtr = buf;
183       while (1) 
184         {
185           pixel = *iPtr++;
186           count = (int)(pixel & 0x7F);
187           if (!count)
188             return;
189           if (pixel & 0x80) 
190             {
191               while (count--) 
192                 {
193                   *oPtr++ = *iPtr++;
194                 }
195             } 
196           else 
197             {
198               pixel = *iPtr++;
199               while (count--) 
200                 {
201                   *oPtr++ = pixel;
202                 }
203             }
204         }
205     }
206   else /* verbatim image */
207     {
208       fseek(image->file, 512+(y*image->sizeX)+(z*image->sizeX*image->sizeY),
209             SEEK_SET);
210       fread(buf, 1, image->sizeX, image->file);
211     }
212 }
213
214 static void ImageGetRawData( Image *image, unsigned char *data)
215 {
216   int i, j, k;
217   int remain;
218
219   switch ( image->sizeZ )
220     {
221     case 1:
222       remain = image->sizeX % 4;
223       break;
224     case 2:
225       remain = image->sizeX % 2;
226       break;
227     case 3:
228       remain = (image->sizeX * 3) & 0x3;
229       if (remain)
230         remain = 4 - remain;
231       break;
232     case 4:
233       remain = 0;
234       break;
235     }
236
237   for (i = 0; i < image->sizeY; i++) 
238     {
239       for ( k = 0; k < image->sizeZ ; k++ )
240         ImageGetRow(image, image->tmp[k+1], i, k);
241       for (j = 0; j < image->sizeX; j++) 
242         for ( k = 1; k <= image->sizeZ ; k++ )
243           *data++ = *(image->tmp[k] + j);
244       data += remain;
245     }
246 }
247
248 static IMAGE *ImageLoad(char *fileName)
249 {
250   Image *image;
251   IMAGE *final;
252   int sx;
253
254   image = ImageOpen(fileName);
255
256   final = (IMAGE *)malloc(sizeof(IMAGE));
257   if (final == NULL) 
258     {
259       fprintf(stderr, "Out of memory!\n");
260       exit(-1);
261     }
262   final->imagic = image->imagic;
263   final->type = image->type;
264   final->dim = image->dim;
265   final->sizeX = image->sizeX; 
266   final->sizeY = image->sizeY;
267   final->sizeZ = image->sizeZ;
268
269   /* 
270    * Round up so rows are long-word aligned 
271    */
272   sx = ( (image->sizeX) * (image->sizeZ) + 3) >> 2;
273
274   final->data 
275     = (unsigned char *)malloc( sx * image->sizeY * sizeof(unsigned int));
276
277   if (final->data == NULL) 
278     {
279       fprintf(stderr, "Out of memory!\n");
280       exit(-1);
281     }
282
283   ImageGetRawData(image, final->data);
284   ImageClose(image);
285   return final;
286 }
287
288
289 void fgPanelInit ( void ) {
290     string tpath;
291     int x, y;
292
293 #ifdef GL_VERSION_1_1
294     xglGenTextures(1, &panel_tex_id);
295     xglBindTexture(GL_TEXTURE_2D, panel_tex_id);
296 #elif GL_EXT_texture_object
297     xglGenTexturesEXT(1, &panel_tex_id);
298     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id);
299 #else
300 #  error port me
301 #endif
302
303     // xglPixelStorei(GL_UNPACK_ALIGNMENT, 4);
304     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 512);
305     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
306     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   
307     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
308     xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
309
310     /* load in the texture data */
311     tpath = current_options.get_fg_root() + "/Textures/panel1.rgb";
312
313     if ( (img = ImageLoad((char *)tpath.c_str()) ) == NULL ){
314         fgPrintf( FG_COCKPIT, FG_EXIT, 
315                   "Error loading cockpit texture %s\n", tpath.c_str() );
316     }
317
318     for ( y = 0; y < 256; y++ ) {
319         for ( x = 0; x < 512; x++ ) { 
320             tex[x][y][0]=img->data[(y+x*256)*3];
321             tex[x][y][1]=img->data[(y+x*256)*3+1];
322             tex[x][y][2]=img->data[(y+x*256)*3+2];
323             if ( (tex[x][y][0] == 0) && (tex[x][y][1] == 0) && 
324                  (tex[x][y][2] == 0) ) {
325                 tex[x][y][3]=0;
326             } else {
327                 tex[x][y][3]=255;
328             }
329         }
330     }
331     xglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 256, 0, GL_RGBA, 
332                   GL_UNSIGNED_BYTE, (GLvoid *)(tex));
333     xglPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
334
335     printf("ALPHA=%d\n", tex[0][0][3]);
336     printf("ALPHA=%d\n", tex[512][0][3]);
337     printf("ALPHA=%d\n", tex[512][256][3]);
338     printf("ALPHA=%d\n", tex[0][256][3]);
339
340     panel_list = xglGenLists (1);
341     xglNewList(panel_list, GL_COMPILE);
342     xglBegin(GL_POLYGON);
343     xglTexCoord2f(0.0,0.0); glVertex2f(0.0,0.0);
344     xglTexCoord2f(1.0,0.0); glVertex2f(640.0,0.0);
345     xglTexCoord2f(1.0,1.0); glVertex2f(640.0,330.0);
346     // xglTexCoord2f(0.6,1.0); glVertex2f(384.0,330.0); 
347     // xglTexCoord2f(0.166666,0.91111); glVertex2f(106.66666,303.182);
348     // xglTexCoord2f(0.0, 0.75769231); glVertex2f(0.0, 279.61); 
349     xglTexCoord2f(0.0,1.0); glVertex2f(0.0,330.0); 
350     xglEnd();
351     xglEndList ();
352 }
353
354
355 void fgPanelUpdate ( void ) {
356     float alpha;
357     double speed;
358
359     xglMatrixMode(GL_PROJECTION);
360     xglPushMatrix();
361     xglLoadIdentity();
362     // xglViewport(0, 0, 640, 480);
363     gluOrtho2D(0, 640, 0, 480);
364     xglMatrixMode(GL_MODELVIEW);
365     xglPushMatrix();
366     xglLoadIdentity();
367
368     xglDisable(GL_DEPTH_TEST);
369     xglDisable(GL_LIGHTING);
370     xglEnable(GL_TEXTURE_2D);
371 #ifdef GL_VERSION_1_1
372     xglBindTexture(GL_TEXTURE_2D, panel_tex_id);
373 #elif GL_EXT_texture_object
374     xglBindTextureEXT(GL_TEXTURE_2D, panel_tex_id);
375 #else
376 #  error port me
377 #endif
378     xglEnable(GL_BLEND);
379     xglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
380     xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_BLEND);
381     xglColor4f(1.0, 1.0, 1.0, 1.0);
382
383     xglCallList(panel_list);
384
385     xglPushMatrix();
386     xglDisable(GL_TEXTURE_2D);
387     speed = get_speed();
388     alpha=((((float)(speed))/150)*270 + 20);
389     xglTranslatef(130, 146, 0);
390     xglRotatef(-alpha, 0.0, 0.0, 1.0);
391     xglScalef(20, 23, 0.0);
392     xglBegin(GL_POLYGON);
393     xglColor4f(1.0, 1.0, 1.0, 1.0);
394     xglVertex2f(0.0, 0.0);
395     xglVertex2f(0.1, 0.2);
396     xglVertex2f(0.0, 1.0);
397     xglVertex2f(-0.1, 0.2);
398     xglVertex2f(0.0, 0.0);
399     xglEnd();  
400     xglPopMatrix();   
401
402     // xglFlush();
403
404     xglEnable(GL_DEPTH_TEST);
405     xglEnable(GL_LIGHTING);
406     xglDisable(GL_TEXTURE_2D);
407     xglDisable(GL_BLEND);
408     xglDisable(GL_ALPHA_TEST);
409
410     xglMatrixMode(GL_PROJECTION);
411     xglPopMatrix();
412     xglMatrixMode(GL_MODELVIEW);
413     xglPopMatrix();
414 }
415
416
417 /* $Log$
418 /* Revision 1.5  1998/08/27 17:02:03  curt
419 /* Contributions from Bernie Bright <bbright@c031.aone.net.au>
420 /* - use strings for fg_root and airport_id and added methods to return
421 /*   them as strings,
422 /* - inlined all access methods,
423 /* - made the parsing functions private methods,
424 /* - deleted some unused functions.
425 /* - propogated some of these changes out a bit further.
426 /*
427  * Revision 1.4  1998/07/24 21:37:00  curt
428  * Ran dos2unix to get rid of extraneous ^M's.  Tweaked parameter in
429  * ImageGetRawData() to match usage.
430  *
431  * Revision 1.3  1998/07/13 21:00:52  curt
432  * Integrated Charlies latest HUD updates.
433  * Wrote access functions for current fgOPTIONS.
434  *
435  * Revision 1.2  1998/07/03 11:55:37  curt
436  * A few small rearrangements and tweaks.
437  *
438  * Revision 1.1  1998/06/27 16:47:54  curt
439  * Incorporated Friedemann Reinhard's <mpt218@faupt212.physik.uni-erlangen.de>
440  * first pass at an isntrument panel.
441  *
442  */