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