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