tunnel.c revision 7ec3b29a
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 <string.h>
13
14#ifdef WIN32
15#include <windows.h>
16#endif
17
18#include "glut_wrap.h"
19#include "readtex.h"
20#include "tunneldat.h"
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
30static GLint T0 = 0;
31static GLint Frames = 0;
32static GLint NiceFog = 1;
33
34#define NUMBLOC 5
35
36#ifndef M_PI
37#define M_PI 3.1415926535
38#endif
39
40/*
41extern int striplength_skin_13[];
42extern float stripdata_skin_13[];
43
44extern int striplength_skin_12[];
45extern float stripdata_skin_12[];
46
47extern int striplength_skin_11[];
48extern float stripdata_skin_11[];
49
50extern int striplength_skin_9[];
51extern float stripdata_skin_9[];
52*/
53
54static int win = 0;
55
56static float obs[3] = { 1000.0, 0.0, 2.0 };
57static float dir[3];
58static float v = 30.;
59static float alpha = 90.0;
60static float beta = 90.0;
61
62static int fog = 1;
63static int bfcull = 1;
64static int usetex = 1;
65static int cstrip = 0;
66static int help = 1;
67static int joyavailable = 0;
68static int joyactive = 0;
69
70static GLuint t1id, t2id;
71
72static void
73inittextures(void)
74{
75   glGenTextures(1, &t1id);
76   glBindTexture(GL_TEXTURE_2D, t1id);
77
78   if (!LoadRGBMipmaps(DEMOS_DATA_DIR "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_NEAREST);
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(DEMOS_DATA_DIR "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
108static void
109drawobjs(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
160static void
161calcposobs(void)
162{
163   static double t0 = -1.;
164   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
165   if (t0 < 0.0)
166      t0 = t;
167   dt = t - t0;
168   t0 = t;
169
170   dir[0] = sin(alpha * M_PI / 180.0);
171   dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
172   dir[2] = cos(beta * M_PI / 180.0);
173
174   if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
175      dir[0] = 0;
176   if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
177      dir[1] = 0;
178   if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
179      dir[2] = 0;
180
181   obs[0] += v * dir[0] * dt;
182   obs[1] += v * dir[1] * dt;
183   obs[2] += v * dir[2] * dt;
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
206cleanup(void)
207{
208   glDeleteTextures(1, &t1id);
209   glDeleteTextures(1, &t2id);
210}
211
212static void
213key(unsigned char k, int x, int y)
214{
215   switch (k) {
216   case 27:
217      cleanup();
218      exit(0);
219      break;
220
221   case 'a':
222      v += 5.;
223      break;
224   case 'z':
225      v -= 5.;
226      break;
227
228#ifdef XMESA
229   case ' ':
230      fullscreen = (!fullscreen);
231      XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
232      break;
233#endif
234   case 'j':
235      joyactive = (!joyactive);
236      break;
237   case 'h':
238      help = (!help);
239      break;
240   case 'f':
241      fog = (!fog);
242      break;
243   case 't':
244      usetex = (!usetex);
245      break;
246   case 'b':
247      if (bfcull) {
248	 glDisable(GL_CULL_FACE);
249	 bfcull = 0;
250      }
251      else {
252	 glEnable(GL_CULL_FACE);
253	 bfcull = 1;
254      }
255      break;
256   case 'm':
257      cstrip = (!cstrip);
258      break;
259
260   case 'd':
261      fprintf(stderr, "Deleting textures...\n");
262      glDeleteTextures(1, &t1id);
263      glDeleteTextures(1, &t2id);
264      fprintf(stderr, "Loading textures...\n");
265      inittextures();
266      fprintf(stderr, "Done.\n");
267      break;
268   case 'n':
269      NiceFog = !NiceFog;
270      printf("NiceFog %d\n", NiceFog);
271      break;
272   }
273   glutPostRedisplay();
274}
275
276static void
277reshape(int w, int h)
278{
279   WIDTH = w;
280   HEIGHT = h;
281   glMatrixMode(GL_PROJECTION);
282   glLoadIdentity();
283   gluPerspective(80.0, w / (float) h, 1.0, 50.0);
284   glMatrixMode(GL_MODELVIEW);
285   glLoadIdentity();
286   glViewport(0, 0, w, h);
287}
288
289static void
290printstring(void *font, char *string)
291{
292   int len, i;
293
294   len = (int) strlen(string);
295   for (i = 0; i < len; i++)
296      glutBitmapCharacter(font, string[i]);
297}
298
299static void
300printhelp(void)
301{
302   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
303   glColor4f(0.0, 0.0, 0.0, 0.5);
304   glRecti(40, 40, 600, 440);
305
306   glColor3f(1.0, 0.0, 0.0);
307   glRasterPos2i(300, 420);
308   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
309
310   glRasterPos2i(60, 390);
311   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
312   glRasterPos2i(60, 360);
313   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Toggle Textures");
314   glRasterPos2i(60, 330);
315   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
316   glRasterPos2i(60, 300);
317   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "m - Toggle strips");
318   glRasterPos2i(60, 270);
319   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "b - Toggle Back face culling");
320   glRasterPos2i(60, 240);
321   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
322   glRasterPos2i(60, 210);
323   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
324   glRasterPos2i(60, 180);
325   printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
326
327   glRasterPos2i(60, 150);
328   if (joyavailable)
329      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
330		  "j - Toggle jostick control (Joystick control available)");
331   else
332      printstring(GLUT_BITMAP_TIMES_ROMAN_24,
333		  "(No Joystick control available)");
334}
335
336static void
337dojoy(void)
338{
339#ifdef WIN32
340   static UINT max[2] = { 0, 0 };
341   static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
342   MMRESULT res;
343   JOYINFO joy;
344
345   res = joyGetPos(JOYSTICKID1, &joy);
346
347   if (res == JOYERR_NOERROR) {
348      joyavailable = 1;
349
350      if (max[0] < joy.wXpos)
351	 max[0] = joy.wXpos;
352      if (min[0] > joy.wXpos)
353	 min[0] = joy.wXpos;
354      center[0] = (max[0] + min[0]) / 2;
355
356      if (max[1] < joy.wYpos)
357	 max[1] = joy.wYpos;
358      if (min[1] > joy.wYpos)
359	 min[1] = joy.wYpos;
360      center[1] = (max[1] + min[1]) / 2;
361
362      if (joyactive) {
363	 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
364	    alpha -=
365	       2.0 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
366	 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
367	    beta += 2.0 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
368
369	 if (joy.wButtons & JOY_BUTTON1)
370	    v += 0.01;
371	 if (joy.wButtons & JOY_BUTTON2)
372	    v -= 0.01;
373      }
374   }
375   else
376      joyavailable = 0;
377#endif
378}
379
380static void
381draw(void)
382{
383   static char frbuf[80] = "";
384   int i;
385   float base, offset;
386
387   if (NiceFog)
388      glHint(GL_FOG_HINT, GL_NICEST);
389   else
390      glHint(GL_FOG_HINT, GL_DONT_CARE);
391
392   dojoy();
393
394   glClear(GL_COLOR_BUFFER_BIT);
395
396   if (usetex)
397      glEnable(GL_TEXTURE_2D);
398   else
399      glDisable(GL_TEXTURE_2D);
400
401   if (fog)
402      glEnable(GL_FOG);
403   else
404      glDisable(GL_FOG);
405
406   glShadeModel(GL_SMOOTH);
407
408   glPushMatrix();
409   calcposobs();
410   gluLookAt(obs[0], obs[1], obs[2],
411	     obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
412	     0.0, 0.0, 1.0);
413
414   if (dir[0] > 0) {
415      offset = 8.0;
416      base = obs[0] - fmod(obs[0], 8.0);
417   }
418   else {
419      offset = -8.0;
420      base = obs[0] + (8.0 - fmod(obs[0], 8.0));
421   }
422
423   glPushMatrix();
424   glTranslatef(base - offset / 2.0, 0.0, 0.0);
425   for (i = 0; i < NUMBLOC; i++) {
426      glTranslatef(offset, 0.0, 0.0);
427      glBindTexture(GL_TEXTURE_2D, t1id);
428      drawobjs(striplength_skin_11, stripdata_skin_11);
429      glBindTexture(GL_TEXTURE_2D, t2id);
430      drawobjs(striplength_skin_12, stripdata_skin_12);
431      drawobjs(striplength_skin_9, stripdata_skin_9);
432      drawobjs(striplength_skin_13, stripdata_skin_13);
433   }
434   glPopMatrix();
435   glPopMatrix();
436
437   glDisable(GL_TEXTURE_2D);
438   glDisable(GL_FOG);
439   glShadeModel(GL_FLAT);
440
441   glMatrixMode(GL_PROJECTION);
442   glPushMatrix();
443   glLoadIdentity();
444   glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
445
446   glMatrixMode(GL_MODELVIEW);
447   glLoadIdentity();
448
449   glColor3f(1.0, 0.0, 0.0);
450   glRasterPos2i(10, 10);
451   printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
452   glRasterPos2i(350, 470);
453   printstring(GLUT_BITMAP_HELVETICA_10,
454	       "Tunnel V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
455
456   if (help)
457      printhelp();
458
459   glMatrixMode(GL_PROJECTION);
460   glPopMatrix();
461   glMatrixMode(GL_MODELVIEW);
462
463   glutSwapBuffers();
464
465   Frames++;
466   {
467      GLint t = glutGet(GLUT_ELAPSED_TIME);
468      if (t - T0 >= 2000) {
469         GLfloat seconds = (t - T0) / 1000.0;
470         GLfloat fps = Frames / seconds;
471         sprintf(frbuf, "Frame rate: %f", fps);
472         printf("%s\n", frbuf);
473         fflush(stdout);
474         T0 = t;
475         Frames = 0;
476      }
477   }
478}
479
480static void
481idle(void)
482{
483   glutPostRedisplay();
484}
485
486
487
488int
489main(int ac, char **av)
490{
491   float fogcolor[4] = { 0.7, 0.7, 0.7, 1.0 };
492
493   fprintf(stderr,
494	   "Tunnel V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
495
496   glutInitWindowSize(WIDTH, HEIGHT);
497   glutInit(&ac, av);
498
499   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
500
501   if (!(win = glutCreateWindow("Tunnel"))) {
502      fprintf(stderr, "Error, couldn't open window\n");
503      return -1;
504   }
505
506   glMatrixMode(GL_PROJECTION);
507   glLoadIdentity();
508   gluPerspective(80.0, WIDTH / (float) HEIGHT, 1.0, 50.0);
509
510   glMatrixMode(GL_MODELVIEW);
511
512   glShadeModel(GL_SMOOTH);
513   glDisable(GL_DEPTH_TEST);
514   glEnable(GL_CULL_FACE);
515   glEnable(GL_TEXTURE_2D);
516
517   glEnable(GL_FOG);
518   glFogi(GL_FOG_MODE, GL_EXP2);
519   glFogfv(GL_FOG_COLOR, fogcolor);
520
521   glFogf(GL_FOG_DENSITY, 0.06);
522   glHint(GL_FOG_HINT, GL_NICEST);
523
524   inittextures();
525
526   glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]);
527   glClear(GL_COLOR_BUFFER_BIT);
528
529   calcposobs();
530
531   glutReshapeFunc(reshape);
532   glutDisplayFunc(draw);
533   glutKeyboardFunc(key);
534   glutSpecialFunc(special);
535   glutIdleFunc(idle);
536
537   glEnable(GL_BLEND);
538   /*glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE); */
539   /*glEnable(GL_POLYGON_SMOOTH); */
540
541   glutMainLoop();
542
543   cleanup();
544   return 0;
545}
546