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