blob: 3cced8b2a93965b66b09114c82d267884ac53711 [file] [log] [blame]
Brian Paul5b0a7f32000-06-27 16:52:38 +00001/*
2 * This program is under the GNU GPL.
3 * Use at your own risk.
4 *
5 * written by David Bucciarelli (tech.hmw@plus.it)
6 * Humanware s.r.l.
7 */
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <math.h>
12#include <time.h>
13
14#ifdef WIN32
15#include <windows.h>
16#endif
17
18#include <GL/glut.h>
19#include "../util/readtex.c"
20#include "tunneldat.c"
21
22#ifdef XMESA
23#include "GL/xmesa.h"
24static int fullscreen = 1;
25#endif
26
27static int WIDTH = 640;
28static int HEIGHT = 480;
29
30#define FRAME 50
31
32#define NUMBLOC 5
33
34#ifndef M_PI
35#define M_PI 3.1415926535
36#endif
37
38extern int striplength_skin_13[];
39extern float stripdata_skin_13[];
40
41extern int striplength_skin_12[];
42extern float stripdata_skin_12[];
43
44extern int striplength_skin_11[];
45extern float stripdata_skin_11[];
46
47extern int striplength_skin_9[];
48extern float stripdata_skin_9[];
49
50
51static int win = 0;
52
53static float obs[3] = { 1000.0, 0.0, 2.0 };
54static float dir[3];
55static float v = 0.5;
56static float alpha = 90.0;
57static float beta = 90.0;
58
59static int fog = 0;
60static int bfcull = 1;
61static int usetex = 1;
62static int cstrip = 0;
63static int help = 1;
64static int joyavailable = 0;
65static int joyactive = 0;
66
67static GLuint t1id, t2id;
68
69static void
70inittextures(void)
71{
72 GLenum gluerr;
73
74 glGenTextures(1, &t1id);
75 glBindTexture(GL_TEXTURE_2D, t1id);
76
77 if (!LoadRGBMipmaps("../images/tile.rgb", GL_RGB)) {
78 fprintf(stderr, "Error reading a texture.\n");
79 exit(-1);
80 }
81
82 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
83 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
84
85 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
86 GL_LINEAR_MIPMAP_LINEAR);
87 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
88
89 glGenTextures(1, &t2id);
90 glBindTexture(GL_TEXTURE_2D, t2id);
91
92 if (!LoadRGBMipmaps("../images/bw.rgb", GL_RGB)) {
93 fprintf(stderr, "Error reading a texture.\n");
94 exit(-1);
95 }
96
97 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
98 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
99
100 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
101 GL_LINEAR_MIPMAP_LINEAR);
102 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
103
104 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
105}
106
107static void
108drawobjs(int *l, float *f)
109{
110 int mend, j;
111
112 if (cstrip) {
113 float r = 0.33, g = 0.33, b = 0.33;
114
115 for (; (*l) != 0;) {
116 mend = *l++;
117
118 r += 0.33;
119 if (r > 1.0) {
120 r = 0.33;
121 g += 0.33;
122 if (g > 1.0) {
123 g = 0.33;
124 b += 0.33;
125 if (b > 1.0)
126 b = 0.33;
127 }
128 }
129
130 glColor3f(r, g, b);
131 glBegin(GL_TRIANGLE_STRIP);
132 for (j = 0; j < mend; j++) {
133 f += 4;
134 glTexCoord2fv(f);
135 f += 2;
136 glVertex3fv(f);
137 f += 3;
138 }
139 glEnd();
140 }
141 }
142 else
143 for (; (*l) != 0;) {
144 mend = *l++;
145
146 glBegin(GL_TRIANGLE_STRIP);
147 for (j = 0; j < mend; j++) {
148 glColor4fv(f);
149 f += 4;
150 glTexCoord2fv(f);
151 f += 2;
152 glVertex3fv(f);
153 f += 3;
154 }
155 glEnd();
156 }
157}
158
159static float
160gettime(void)
161{
162 static clock_t told = 0;
163 clock_t tnew, ris;
164
165 tnew = clock();
166
167 ris = tnew - told;
168
169 told = tnew;
170
171 return (ris / (float) CLOCKS_PER_SEC);
172}
173
174static void
175calcposobs(void)
176{
177 dir[0] = sin(alpha * M_PI / 180.0);
178 dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
179 dir[2] = cos(beta * M_PI / 180.0);
180
181 obs[0] += v * dir[0];
182 obs[1] += v * dir[1];
183 obs[2] += v * dir[2];
184}
185
186static void
187special(int k, int x, int y)
188{
189 switch (k) {
190 case GLUT_KEY_LEFT:
191 alpha -= 2.0;
192 break;
193 case GLUT_KEY_RIGHT:
194 alpha += 2.0;
195 break;
196 case GLUT_KEY_DOWN:
197 beta -= 2.0;
198 break;
199 case GLUT_KEY_UP:
200 beta += 2.0;
201 break;
202 }
203}
204
205static void
206key(unsigned char k, int x, int y)
207{
208 switch (k) {
209 case 27:
210 exit(0);
211 break;
212
213 case 'a':
214 v += 0.01;
215 break;
216 case 'z':
217 v -= 0.01;
218 break;
219
220#ifdef XMESA
221 case ' ':
222 fullscreen = (!fullscreen);
223 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
224 break;
225#endif
226
227 case 'j':
228 joyactive = (!joyactive);
229 break;
230 case 'h':
231 help = (!help);
232 break;
233 case 'f':
234 fog = (!fog);
235 break;
236 case 't':
237 usetex = (!usetex);
238 break;
239 case 'b':
240 if (bfcull) {
241 glDisable(GL_CULL_FACE);
242 bfcull = 0;
243 }
244 else {
245 glEnable(GL_CULL_FACE);
246 bfcull = 1;
247 }
248 break;
249 case 'm':
250 cstrip = (!cstrip);
251 break;
252
253 case 'd':
254 fprintf(stderr, "Deleting textures...\n");
255 glDeleteTextures(1, &t1id);
256 glDeleteTextures(1, &t2id);
257 fprintf(stderr, "Loading textures...\n");
258 inittextures();
259 fprintf(stderr, "Done.\n");
260 break;
261 }
262}
263
264static void
265reshape(int w, int h)
266{
267 WIDTH = w;
268 HEIGHT = h;
269 glMatrixMode(GL_PROJECTION);
270 glLoadIdentity();
271 gluPerspective(80.0, w / (float) h, 1.0, 50.0);
272 glMatrixMode(GL_MODELVIEW);
273 glLoadIdentity();
274 glViewport(0, 0, w, h);
275}
276
277static void
278printstring(void *font, char *string)
279{
280 int len, i;
281
282 len = (int) strlen(string);
283 for (i = 0; i < len; i++)
284 glutBitmapCharacter(font, string[i]);
285}
286
287static void
288printhelp(void)
289{
290 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
291 glColor4f(0.0, 0.0, 0.0, 0.5);
292 glRecti(40, 40, 600, 440);
293
294 glColor3f(1.0, 0.0, 0.0);
295 glRasterPos2i(300, 420);
296 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
297
298 glRasterPos2i(60, 390);
299 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
300 glRasterPos2i(60, 360);
301 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Togle Textures");
302 glRasterPos2i(60, 330);
303 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
304 glRasterPos2i(60, 300);
305 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "m - Togle strips");
306 glRasterPos2i(60, 270);
307 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Togle Back face culling");
308 glRasterPos2i(60, 240);
309 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
310 glRasterPos2i(60, 210);
311 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
312 glRasterPos2i(60, 180);
313 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
314
315 glRasterPos2i(60, 150);
316 if (joyavailable)
317 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
318 "j - Togle jostick control (Joystick control available)");
319 else
320 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
321 "(No Joystick control available)");
322}
323
324static void
325dojoy(void)
326{
327#ifdef WIN32
328 static UINT max[2] = { 0, 0 };
329 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
330 MMRESULT res;
331 JOYINFO joy;
332
333 res = joyGetPos(JOYSTICKID1, &joy);
334
335 if (res == JOYERR_NOERROR) {
336 joyavailable = 1;
337
338 if (max[0] < joy.wXpos)
339 max[0] = joy.wXpos;
340 if (min[0] > joy.wXpos)
341 min[0] = joy.wXpos;
342 center[0] = (max[0] + min[0]) / 2;
343
344 if (max[1] < joy.wYpos)
345 max[1] = joy.wYpos;
346 if (min[1] > joy.wYpos)
347 min[1] = joy.wYpos;
348 center[1] = (max[1] + min[1]) / 2;
349
350 if (joyactive) {
351 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
352 alpha -=
353 2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
354 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
355 beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
356
357 if (joy.wButtons & JOY_BUTTON1)
358 v += 0.01;
359 if (joy.wButtons & JOY_BUTTON2)
360 v -= 0.01;
361 }
362 }
363 else
364 joyavailable = 0;
365#endif
366}
367
368static void
369draw(void)
370{
371 static int count = 0;
372 static char frbuf[80];
373 int i;
374 float fr, base, offset;
375
376 dojoy();
377
378 glClear(GL_COLOR_BUFFER_BIT);
379
380 if (usetex)
381 glEnable(GL_TEXTURE_2D);
382 else
383 glDisable(GL_TEXTURE_2D);
384
385 if (fog)
386 glEnable(GL_FOG);
387 else
388 glDisable(GL_FOG);
389
390 glShadeModel(GL_SMOOTH);
391
392 glPushMatrix();
393 calcposobs();
394 gluLookAt(obs[0], obs[1], obs[2],
395 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
396 0.0, 0.0, 1.0);
397
398 if (dir[0] > 0) {
399 offset = 8.0;
400 base = obs[0] - fmod(obs[0], 8.0);
401 }
402 else {
403 offset = -8.0;
404 base = obs[0] + (8.0 - fmod(obs[0], 8.0));
405 }
406
407 glPushMatrix();
408 glTranslatef(base - offset / 2.0, 0.0, 0.0);
409 for (i = 0; i < NUMBLOC; i++) {
410 glTranslatef(offset, 0.0, 0.0);
411 glBindTexture(GL_TEXTURE_2D, t1id);
412 drawobjs(striplength_skin_11, stripdata_skin_11);
413 glBindTexture(GL_TEXTURE_2D, t2id);
414 drawobjs(striplength_skin_12, stripdata_skin_12);
415 drawobjs(striplength_skin_9, stripdata_skin_9);
416 drawobjs(striplength_skin_13, stripdata_skin_13);
417 }
418 glPopMatrix();
419 glPopMatrix();
420
421 if ((count % FRAME) == 0) {
422 fr = gettime();
423 sprintf(frbuf, "Frame rate: %f", FRAME / fr);
424 }
425
426 glDisable(GL_TEXTURE_2D);
427 glDisable(GL_FOG);
428 glShadeModel(GL_FLAT);
429
430 glMatrixMode(GL_PROJECTION);
431 glPushMatrix();
432 glLoadIdentity();
433 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
434
435 glMatrixMode(GL_MODELVIEW);
436 glLoadIdentity();
437
438 glColor3f(1.0, 0.0, 0.0);
439 glRasterPos2i(10, 10);
440 printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
441 glRasterPos2i(350, 470);
442 printstring(GLUT_BITMAP_HELVETICA_10,
443 "Tunnel V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
444
445 if (help)
446 printhelp();
447
448 glMatrixMode(GL_PROJECTION);
449 glPopMatrix();
450 glMatrixMode(GL_MODELVIEW);
451
452 glutSwapBuffers();
453
454 count++;
455}
456
457int
458main(int ac, char **av)
459{
460 float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
461
462 fprintf(stderr,
463 "Tunnel V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
464
465 glutInitWindowPosition(0, 0);
466 glutInitWindowSize(WIDTH, HEIGHT);
467 glutInit(&ac, av);
468
469 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
470
471 if (!(win = glutCreateWindow("Tunnel"))) {
472 fprintf(stderr, "Error, couldn't open window\n");
473 return -1;
474 }
475
476 glMatrixMode(GL_PROJECTION);
477 glLoadIdentity();
478 gluPerspective(80.0, WIDTH / (float) HEIGHT, 1.0, 50.0);
479
480 glMatrixMode(GL_MODELVIEW);
481
482 glShadeModel(GL_SMOOTH);
483 glDisable(GL_DEPTH_TEST);
484 glEnable(GL_CULL_FACE);
485 glEnable(GL_TEXTURE_2D);
486
487 glEnable(GL_FOG);
488 glFogi(GL_FOG_MODE, GL_EXP2);
489 glFogfv(GL_FOG_COLOR, fogcolor);
490
491 glFogf(GL_FOG_DENSITY, 0.06);
492 glHint(GL_FOG_HINT, GL_NICEST);
493
494 inittextures();
495
496 glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
497 glClear(GL_COLOR_BUFFER_BIT);
498
499 calcposobs();
500
501 glutReshapeFunc(reshape);
502 glutDisplayFunc(draw);
503 glutKeyboardFunc(key);
504 glutSpecialFunc(special);
505 glutIdleFunc(draw);
506
507 glEnable(GL_BLEND);
508 /*glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE); */
509 /*glEnable(GL_POLYGON_SMOOTH); */
510
511 glutMainLoop();
512
513 return 0;
514}