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