1 /****************************************************************************
2 * Small Precludes OpenGL demo
3 *
4 * By Jason Nunn <jsno8192@yahoo.com.au>
5 * (C) Copyright 2000-2003
6 * Darwin, NT, Australia
7 * http://jsno.arafuraconnect.com.au
8 *
9 * =====================================================================
10 * misc stuff
11 *
12 ****************************************************************************/
13 #include "defs.h"
14 #include "protos.p"
15
16 typedef struct _tex_ll_t
17 {
18 GLuint id;
19 struct _tex_ll_t *next;
20 } tex_ll_t;
21
22 PUBLIC int window_size_x = SCREEN_SIZE_X,
23 window_size_y = SCREEN_SIZE_Y;
24
25 PUBLIC void (*draw_h_hook)(void);
26 PUBLIC void (*calc_hook)(void);
27
28 PUBLIC GLfloat black_pixel[1][3],
29 white_pixel[8][3],
30 blue_pixel[8][3],
31 yellow_pixel[1][3] = {{0.9375, 0.9375, 0.0}},
32 green_pixel[MAX_SCORE_TABLE][3],
33 red_pixel[MAX_SCORE_TABLE][3],
34 intro_haze[2][3] = {{0.0, 0.9, 0.0}, {0.0, 0.35, 0.0}},
35 purple_pixel[1][3] = {{0.7, 0.1, 8.0}};
36
37 PUBLIC GLfloat bm_colour[4] = {1.0, 1.0, 1.0, 1.0},
38 bm_colour2[4] = {1.0, 1.0, 1.0, 0.6};
39
40 PUBLIC unsigned int update_speed = UPDATE_SPEED;
41
42 PUBLIC char *console_message[MAX_MESSAGES];
43 PUBLIC float console_message_alpha_fade;
44
45 PRIVATE GLdouble time_start;
46 PRIVATE tex_ll_t *tex_ll;
47 PRIVATE int fps_f;
48 PRIVATE Display *x_display;
49 PRIVATE unsigned int xkb_delay, xkb_rate;
50
51 /****************************************************************************
52 *
53 ****************************************************************************/
ramp_colour(GLfloat r1,float g1,float b1,GLfloat r2,float g2,float b2,GLfloat * p,int run)54 PUBLIC void ramp_colour(
55 GLfloat r1, float g1, float b1,
56 GLfloat r2, float g2, float b2,
57 GLfloat *p, int run)
58 {
59 int i, m1, m2;
60 GLfloat rs, gs, bs;
61
62 p[R] = r1;
63 p[G] = g1;
64 p[B] = b1;
65 i = run - 1;
66 rs = (r2 - r1) / (GLfloat)i;
67 gs = (g2 - g1) / (GLfloat)i;
68 bs = (b2 - b1) / (GLfloat)i;
69
70 m1 = 3;
71 m2 = 0;
72 for(i = 1; i < run; i++)
73 {
74 p[m1 + R] = p[m2 + R] + rs;
75 p[m1 + G] = p[m2 + G] + gs;
76 p[m1 + B] = p[m2 + B] + bs;
77 m1 += 3;
78 m2 += 3;
79 }
80 }
81
82 /****************************************************************************
83 *
84 ****************************************************************************/
get_clock(void)85 PUBLIC GLdouble get_clock(void)
86 {
87 struct timeval t;
88
89 gettimeofday(&t,NULL);
90 return ((GLdouble)t.tv_sec + (0.000001 * (GLdouble)t.tv_usec));
91 }
92
sync_time_lapse(void)93 PUBLIC void sync_time_lapse(void)
94 {
95 time_start = get_clock();
96 }
97
get_time_lapse(void)98 PUBLIC GLdouble get_time_lapse(void)
99 {
100 return (get_clock() - time_start) * 32;
101 }
102
103 /****************************************************************************
104 *
105 ****************************************************************************/
blit_line(int x1,int y1,int x2,int y2)106 PUBLIC void blit_line(int x1, int y1, int x2, int y2)
107 {
108 glDisable(GL_TEXTURE_2D);
109
110 glBegin(GL_LINES);
111 glVertex2i(x1, y1);
112 glVertex2i(x2, y2);
113 glEnd();
114
115 glEnable(GL_TEXTURE_2D);
116 }
117
118 /****************************************************************************
119 *
120 ****************************************************************************/
blit_rect(int x,int y,int size_x,int size_y)121 PUBLIC void blit_rect(int x, int y, int size_x, int size_y)
122 {
123 size_x += x;
124 size_y += y;
125
126 glDisable(GL_TEXTURE_2D);
127
128 glBegin(GL_POLYGON);
129 glVertex2i(x, y);
130 glVertex2i(x, size_y);
131 glVertex2i(size_x, size_y);
132 glVertex2i(size_x, y);
133 glEnd();
134
135 glEnable(GL_TEXTURE_2D);
136 }
137
138 /****************************************************************************
139 *
140 ****************************************************************************/
blit_rect_hollow(int x,int y,int size_x,int size_y)141 PUBLIC void blit_rect_hollow(int x, int y, int size_x, int size_y)
142 {
143 size_x += x;
144 size_y += y;
145
146 glDisable(GL_TEXTURE_2D);
147
148 glBegin(GL_LINE_STRIP);
149 glVertex2i(x, y);
150 glVertex2i(x, size_y);
151 glVertex2i(size_x, size_y);
152 glVertex2i(size_x, y);
153 glVertex2i(x, y);
154 glEnd();
155
156 glEnable(GL_TEXTURE_2D);
157 }
158
159 /****************************************************************************
160 *
161 ****************************************************************************/
blit_bm(bm_t * bm,int x,int y)162 PUBLIC void blit_bm(bm_t *bm, int x, int y)
163 {
164 int x1, y1;
165 static const GLfloat tc[4][2] =
166 {{0.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}};
167
168 x1 = x + bm->size_x;
169 y1 = y + bm->size_y;
170
171 if(x1 < 0 || y1 < 0)
172 return;
173 if(x >= SCREEN_SIZE_X || y >= SCREEN_SIZE_Y)
174 return;
175
176 glBindTexture(GL_TEXTURE_2D, bm->id);
177 glBegin(GL_POLYGON);
178 glTexCoord2fv(tc[0]);
179 glVertex2i(x, y);
180
181 glTexCoord2fv(tc[1]);
182 glVertex2i(x, y1);
183
184 glTexCoord2fv(tc[2]);
185 glVertex2i(x1, y1);
186
187 glTexCoord2fv(tc[3]);
188 glVertex2i(x1, y);
189 glEnd();
190 }
191
192 /****************************************************************************
193 *
194 ****************************************************************************/
print_str_len(char * str,int l,int x,int y)195 PUBLIC void print_str_len(char *str, int l, int x, int y)
196 {
197 int i;
198
199 for(i = 0; i < l; i++)
200 {
201 if(str[i] < 32)
202 continue;
203
204 blit_bm(&(font_bm[(int)(str[i] - ' ')]), x, y);
205 x += 8;
206 }
207 }
208
print_str(char * str,int x,int y)209 PUBLIC void print_str(char *str, int x, int y)
210 {
211 print_str_len(str, strlen(str), x, y);
212 }
213
print_str_hazey(char * str,int x,int y,GLfloat * c1,GLfloat * c2)214 PUBLIC void print_str_hazey(char *str, int x, int y, GLfloat *c1, GLfloat *c2)
215 {
216 glColor3fv(c2);
217 print_str_len(str, strlen(str), x - 1, y);
218 print_str_len(str, strlen(str), x + 1, y);
219 print_str_len(str, strlen(str), x, y - 1);
220 print_str_len(str, strlen(str), x, y + 1);
221
222 glColor3fv(c1);
223 print_str_len(str, strlen(str), x, y);
224 }
225
226 /****************************************************************************
227 *
228 ****************************************************************************/
display_message(char * s,int y)229 PUBLIC void display_message(char *s, int y)
230 {
231 int l;
232 char *s1;
233
234 for(;;)
235 {
236 if(*s == '\0')
237 return;
238
239 s1 = strchr(s, '\n');
240 if(s1 == NULL)
241 return;
242
243 l = (int)(s1 - s);
244 if(l)
245 print_str_len(s, l, SCREEN_HSIZE_X - ((l << 3) >> 1), y);
246 y += 16;
247 s = s1 + 1;
248 }
249 }
250
251 /****************************************************************************
252 * tex management
253 ****************************************************************************/
append_tex(GLuint id)254 PUBLIC void append_tex(GLuint id)
255 {
256 tex_ll_t *t;
257
258 t = tex_ll;
259 tex_ll = (tex_ll_t *)alloc_mem(sizeof(tex_ll_t));
260 tex_ll->id = id;
261 tex_ll->next = t;
262 }
263
delete_tex(GLuint id)264 PUBLIC void delete_tex(GLuint id)
265 {
266 tex_ll_t *p, *t;
267
268 p = tex_ll;
269 for(;;)
270 {
271 if(p == NULL)
272 break;
273
274 if(p->id == id)
275 {
276 glDeleteTextures(1, &(p->id));
277
278 p->id = p->next->id;
279 t = p->next;
280 p->next = p->next->next;
281 free(t);
282 }
283
284 p = p->next;
285 }
286 }
287
free_textures(void)288 PUBLIC void free_textures(void)
289 {
290 tex_ll_t *p;
291
292 printf("Freeing Textures.\n");
293
294 p = tex_ll;
295 for(;;)
296 {
297 if(p == NULL)
298 break;
299
300 glDeleteTextures(1, &(p->id));
301
302 p = p->next;
303 }
304 }
305
306 /****************************************************************************
307 *
308 ****************************************************************************/
convert_2_tex(GLubyte * buf,bm_t * bm,int aligned_f)309 PUBLIC void convert_2_tex(GLubyte *buf, bm_t *bm, int aligned_f)
310 {
311 glGenTextures(1, &(bm->id));
312 if(!bm->id)
313 {
314 fprintf(stderr, "convert_2_tex()::glGenTextures(): Error.\n");
315 end_game(-1);
316 }
317 glBindTexture(GL_TEXTURE_2D, bm->id);
318
319 /* Set texture parameters */
320 if(aligned_f)
321 {
322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
323 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
324 }
325 else
326 {
327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
329 }
330
331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
332 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
333 glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
334
335 if(aligned_f)
336 glTexImage2D(GL_TEXTURE_2D, 0, 4, bm->size_x, bm->size_y,
337 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
338 else
339 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, bm->size_x, bm->size_y,
340 GL_RGBA, GL_UNSIGNED_BYTE, buf);
341
342 append_tex(bm->id);
343 }
344
345 /****************************************************************************
346 *
347 ****************************************************************************/
console_message_add(char * str)348 PUBLIC void console_message_add(char *str)
349 {
350 int x;
351
352 if(console_message[0] != NULL)
353 free(console_message[0]);
354
355 for(x = 0; x < (MAX_MESSAGES - 1); x++)
356 console_message[x] = console_message[x + 1];
357
358 console_message[MAX_MESSAGES - 1] = (char *)alloc_mem(strlen(str) + 1);
359 strcpy(console_message[MAX_MESSAGES - 1], str);
360 console_message_alpha_fade = 0.8;
361 }
362
console_message_display(void)363 PUBLIC void console_message_display(void)
364 {
365 int x;
366
367 if(console_message_alpha_fade < 0.0)
368 return;
369
370 glColor4f(0.0, 1.0, 0.0, console_message_alpha_fade);
371
372 for(x = 0; x < MAX_MESSAGES; x++)
373 {
374 if(console_message[x] == NULL)
375 continue;
376
377 print_str(
378 console_message[x],
379 SCREEN_SIZE_X - (strlen(console_message[x]) << 3),
380 (SCREEN_SIZE_Y - 80) + (x << 4));
381 }
382 }
383
console_message_free(void)384 PUBLIC void console_message_free(void)
385 {
386 int x;
387
388 for(x = 0; x < MAX_MESSAGES; x++)
389 if(console_message[x] != NULL)
390 {
391 free(console_message[x]);
392 console_message[x] = NULL;
393 }
394 }
395
396 /****************************************************************************
397 *
398 ****************************************************************************/
on_exit_h()399 PRIVATE void on_exit_h()
400 {
401 free_textures();
402
403 printf("See ya\n");
404 }
405
406 /*
407 * have to have this as XkbSetAutoRepeatRate() doesn't work after exit
408 * called
409 */
end_game(int code)410 PUBLIC void end_game(int code)
411 {
412 if(x_display != NULL)
413 {
414 printf("Resetting X keyboard.\n");
415 XkbSetAutoRepeatRate(x_display, XkbUseCoreKbd, xkb_delay, xkb_rate);
416 }
417
418 exit(code);
419 }
420
421 /****************************************************************************
422 *
423 ****************************************************************************/
mouse_aspect(int v,int w,int r)424 PRIVATE inline int mouse_aspect(int v, int w, int r)
425 {
426 return v * r / w;
427 }
428
keyboard_h(unsigned char key,int x,int y)429 PRIVATE void keyboard_h(unsigned char key, int x, int y)
430 {
431 switch(key)
432 {
433 case 27:
434 end_game(0);
435
436 case KEY_FPS:
437 fps_f ^= 1;
438 break;
439
440 case KEY_REDUCED:
441 reduced_f ^= 1;
442 break;
443
444 default:
445 {
446 tkevent k;
447
448 k.type = KEYBOARD_EVENT;
449 k.val = key;
450 k.mouse_x = mouse_aspect(x, window_size_x, 320);
451 k.mouse_y = mouse_aspect(y, window_size_y, 200);
452 put_kb_event(&k);
453 break;
454 }
455 }
456 }
457
special_h(int key,int x,int y)458 PRIVATE void special_h(int key, int x, int y)
459 {
460 tkevent k;
461
462 k.type = SPECIAL_EVENT;
463 k.val = (unsigned int)key;
464 k.mouse_x = mouse_aspect(x, window_size_x, 320);
465 k.mouse_y = mouse_aspect(y, window_size_y, 200);
466 put_kb_event(&k);
467 }
468
mouse_h(int button,int state,int x,int y)469 PRIVATE void mouse_h(int button, int state, int x, int y)
470 {
471 tkevent k;
472
473 if(!state)
474 return;
475
476 k.type = MOUSE_EVENT;
477 k.val = button;
478 k.mouse_x = mouse_aspect(x, window_size_x, 320);
479 k.mouse_y = mouse_aspect(y, window_size_y, 200);
480 put_kb_event(&k);
481 }
482
483 /****************************************************************************
484 *
485 ****************************************************************************/
timer_h(int value)486 PRIVATE void timer_h(int value)
487 {
488 glutPostRedisplay();
489 glutTimerFunc(update_speed, timer_h, 1);
490 }
491
492 /****************************************************************************
493 *
494 ****************************************************************************/
resize_h(int w,int h)495 PRIVATE void resize_h(int w, int h)
496 {
497 window_size_x = w;
498 window_size_y = h;
499
500 /*Prevent a divide by zero*/
501 if(h == 0)
502 h = 1;
503
504 /*Set Viewport to window dimensions*/
505 glViewport(0, 0, w, h);
506
507 glMatrixMode(GL_PROJECTION);
508 glLoadIdentity();
509
510 /*clipping volume*/
511 glOrtho(0.0, SCREEN_SIZE_X, SCREEN_SIZE_Y, 0.0, 1.0, -1.0);
512
513 glMatrixMode(GL_MODELVIEW);
514 glLoadIdentity();
515 }
516
517 /****************************************************************************
518 *
519 ****************************************************************************/
main_draw_h(void)520 PRIVATE void main_draw_h(void)
521 {
522 static int frame_count;
523 static double old_clock;
524 double x;
525 static char str[40],
526 *mess = "You fucking cheat !\n";
527
528 if(fps_f)
529 {
530 if((frame_count % 50) == 0)
531 {
532 x = get_clock();
533 sprintf(str, "%.2f fps", 50 / (x - old_clock));
534 old_clock = x;
535 }
536 frame_count++;
537 }
538
539 glClear(GL_COLOR_BUFFER_BIT);
540
541 glEnable(GL_BLEND);
542 glEnable(GL_TEXTURE_2D);
543
544 if(draw_h_hook != NULL)
545 draw_h_hook();
546
547 if(fps_f)
548 {
549 glColor4f(1.0, 1.0, 1.0, 0.5);
550 print_str(str, 0, 184);
551 }
552
553 if(god_mode)
554 {
555 glColor4fv(bm_colour);
556 display_message(mess, 50);
557 display_message(mess, 120);
558 }
559
560 glDisable(GL_TEXTURE_2D);
561 glDisable(GL_BLEND);
562
563 glutSwapBuffers();
564
565 /*
566 * do calc
567 */
568 if(calc_hook != NULL)
569 calc_hook();
570 sync_time_lapse();
571 }
572
573 /****************************************************************************
574 *
575 ****************************************************************************/
opengl_init(int argc,char * argv[],int mode)576 PUBLIC void opengl_init(int argc, char *argv[], int mode)
577 {
578 int x, fs_f = 0;
579
580 atexit(on_exit_h);
581 glutInit(&argc, argv);
582 glutInitDisplayMode(mode);
583
584 window_size_x = 640;
585 window_size_y = 480;
586
587 for(x = 1; x < argc; x++)
588 {
589 if(argv[x][0] == '-')
590 {
591 switch(argv[x][1])
592 {
593 case '3':
594 window_size_x = 320;
595 window_size_y = 200;
596 printf("320x200 mode.\n");
597 break;
598
599 case '6':
600 window_size_x = 640;
601 window_size_y = 480;
602 printf("640x480 mode.\n");
603 break;
604
605 case '1':
606 window_size_x = 1024;
607 window_size_y = 768;
608 printf("1024x768 mode.\n");
609 break;
610
611 case 'f':
612 window_size_x = 320;
613 window_size_y = 200;
614 fs_f = 1;
615 printf("Full screen mode.\n");
616 break;
617 }
618 }
619 }
620
621 glutInitWindowSize(window_size_x, window_size_y);
622 glutCreateWindow("Nighthawk " VERSION);
623
624 glutKeyboardFunc(keyboard_h);
625 glutSpecialFunc(special_h);
626 glutMouseFunc(mouse_h);
627
628 glutTimerFunc(update_speed, timer_h, 1);
629 glutReshapeFunc(resize_h);
630 glutDisplayFunc(main_draw_h);
631
632 if(fs_f)
633 glutFullScreen();
634
635 glutSetCursor(GLUT_CURSOR_CROSSHAIR);
636
637 glShadeModel(GL_SMOOTH);
638 glFrontFace(GL_CCW);
639 glDepthFunc(GL_LEQUAL);
640 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
641 glDisable(GL_LIGHTING);
642
643 glClearColor(0.0, 0.0, 0.0, 1.0);
644
645 x_display = glXGetCurrentDisplay();
646 if(x_display != NULL)
647 {
648 XkbGetAutoRepeatRate(x_display, XkbUseCoreKbd, &xkb_delay, &xkb_rate);
649 XkbSetAutoRepeatRate(x_display, XkbUseCoreKbd, 200, 33);
650 }
651 }
652