ray.c revision 32001f49
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 <string.h> 12#include <math.h> 13 14#ifdef WIN32 15#include <windows.h> 16#endif 17 18#include "glut_wrap.h" 19 20#ifdef XMESA 21#include "GL/xmesa.h" 22static int fullscreen = 1; 23#endif 24 25static int WIDTH = 640; 26static int HEIGHT = 480; 27 28static GLint T0 = 0; 29static GLint Frames = 0; 30 31#define BASESIZE 7.5f 32#define SPHERE_RADIUS 0.75f 33 34#define TEX_CHECK_WIDTH 256 35#define TEX_CHECK_HEIGHT 256 36#define TEX_CHECK_SLOT_SIZE (TEX_CHECK_HEIGHT/16) 37#define TEX_CHECK_NUMSLOT (TEX_CHECK_HEIGHT/TEX_CHECK_SLOT_SIZE) 38 39#define TEX_REFLECT_WIDTH 256 40#define TEX_REFLECT_HEIGHT 256 41#define TEX_REFLECT_SLOT_SIZE (TEX_REFLECT_HEIGHT/16) 42#define TEX_REFLECT_NUMSLOT (TEX_REFLECT_HEIGHT/TEX_REFLECT_SLOT_SIZE) 43 44#ifndef M_PI 45#define M_PI 3.1415926535 46#endif 47 48#define EPSILON 0.0001 49 50#define clamp255(a) ( (a)<(0.0f) ? (0.0f) : ((a)>(255.0f) ? (255.0f) : (a)) ) 51 52#ifndef fabs 53#define fabs(x) ((x)<0.0f?-(x):(x)) 54#endif 55 56#define vequ(a,b) { (a)[0]=(b)[0]; (a)[1]=(b)[1]; (a)[2]=(b)[2]; } 57#define vsub(a,b,c) { (a)[0]=(b)[0]-(c)[0]; (a)[1]=(b)[1]-(c)[1]; (a)[2]=(b)[2]-(c)[2]; } 58#define dprod(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) 59#define vnormalize(a,b) { \ 60 register float m_norm; \ 61 m_norm=sqrt((double)dprod((a),(a))); \ 62 (a)[0] /=m_norm; \ 63 (a)[1] /=m_norm; \ 64 (a)[2] /=m_norm; } 65 66static GLubyte checkmap[TEX_CHECK_HEIGHT][TEX_CHECK_WIDTH][3]; 67static GLuint checkid; 68static int checkmap_currentslot = 0; 69 70static GLubyte reflectmap[TEX_REFLECT_HEIGHT][TEX_REFLECT_WIDTH][3]; 71static GLuint reflectid; 72static int reflectmap_currentslot = 0; 73 74static GLuint lightdlist; 75static GLuint objdlist; 76 77static float lightpos[3] = { 2.1, 2.1, 2.8 }; 78static float objpos[3] = { 0.0, 0.0, 1.0 }; 79 80static float sphere_pos[TEX_CHECK_HEIGHT][TEX_REFLECT_WIDTH][3]; 81 82static int win = 0; 83 84static float fogcolor[4] = { 0.05, 0.05, 0.05, 1.0 }; 85 86static float obs[3] = { 7.0, 0.0, 2.0 }; 87static float dir[3]; 88static float v = 0.0; 89static float alpha = -90.0; 90static float beta = 90.0; 91 92static int fog = 1; 93static int bfcull = 1; 94static int poutline = 0; 95static int help = 1; 96static int showcheckmap = 1; 97static int showreflectmap = 1; 98static int joyavailable = 0; 99static int joyactive = 0; 100 101static void 102calcposobs(void) 103{ 104 dir[0] = sin(alpha * M_PI / 180.0); 105 dir[1] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0); 106 dir[2] = cos(beta * M_PI / 180.0); 107 108 if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5) 109 dir[0] = 0; 110 if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5) 111 dir[1] = 0; 112 if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5) 113 dir[2] = 0; 114 115 obs[0] += v * dir[0]; 116 obs[1] += v * dir[1]; 117 obs[2] += v * dir[2]; 118} 119 120static void 121special(int k, int x, int y) 122{ 123 switch (k) { 124 case GLUT_KEY_LEFT: 125 alpha -= 2.0; 126 break; 127 case GLUT_KEY_RIGHT: 128 alpha += 2.0; 129 break; 130 case GLUT_KEY_DOWN: 131 beta -= 2.0; 132 break; 133 case GLUT_KEY_UP: 134 beta += 2.0; 135 break; 136 } 137} 138 139static void 140key(unsigned char k, int x, int y) 141{ 142 switch (k) { 143 case 27: 144 exit(0); 145 break; 146 147 case 's': 148 lightpos[1] -= 0.1; 149 break; 150 case 'd': 151 lightpos[1] += 0.1; 152 break; 153 case 'e': 154 lightpos[0] -= 0.1; 155 break; 156 case 'x': 157 lightpos[0] += 0.1; 158 break; 159 case 'w': 160 lightpos[2] -= 0.1; 161 break; 162 case 'r': 163 lightpos[2] += 0.1; 164 break; 165 166 case 'j': 167 objpos[1] -= 0.1; 168 break; 169 case 'k': 170 objpos[1] += 0.1; 171 break; 172 case 'i': 173 objpos[0] -= 0.1; 174 break; 175 case 'm': 176 objpos[0] += 0.1; 177 break; 178 case 'u': 179 objpos[2] -= 0.1; 180 break; 181 case 'o': 182 objpos[2] += 0.1; 183 break; 184 185 case 'a': 186 v += 0.005; 187 break; 188 case 'z': 189 v -= 0.005; 190 break; 191 192 case 'g': 193 joyactive = (!joyactive); 194 break; 195 case 'h': 196 help = (!help); 197 break; 198 case 'f': 199 fog = (!fog); 200 break; 201 202 case '1': 203 showcheckmap = (!showcheckmap); 204 break; 205 case '2': 206 showreflectmap = (!showreflectmap); 207 break; 208 209 case 'b': 210 if (bfcull) { 211 glDisable(GL_CULL_FACE); 212 bfcull = 0; 213 } 214 else { 215 glEnable(GL_CULL_FACE); 216 bfcull = 1; 217 } 218 break; 219 case 'p': 220 if (poutline) { 221 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 222 poutline = 0; 223 } 224 else { 225 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 226 poutline = 1; 227 } 228 break; 229#ifdef XMESA 230 case ' ': 231 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW); 232 fullscreen = (!fullscreen); 233 break; 234#endif 235 } 236} 237 238static void 239reshape(int w, int h) 240{ 241 WIDTH = w; 242 HEIGHT = h; 243 glViewport(0, 0, w, h); 244 glMatrixMode(GL_PROJECTION); 245 glLoadIdentity(); 246 gluPerspective(45.0, w / (float) h, 0.8, 40.0); 247 glMatrixMode(GL_MODELVIEW); 248 glLoadIdentity(); 249} 250 251static void 252printstring(void *font, char *string) 253{ 254 int len, i; 255 256 len = (int) strlen(string); 257 for (i = 0; i < len; i++) 258 glutBitmapCharacter(font, string[i]); 259} 260 261static void 262printhelp(void) 263{ 264 glEnable(GL_BLEND); 265 glColor4f(0.5, 0.5, 0.5, 0.5); 266 glRecti(40, 40, 600, 440); 267 glDisable(GL_BLEND); 268 269 glColor3f(0.0, 0.0, 1.0); 270 glRasterPos2i(300, 420); 271 printstring(GLUT_BITMAP_HELVETICA_18, "Help"); 272 273 glRasterPos2i(60, 390); 274 printstring(GLUT_BITMAP_HELVETICA_12, "h - Toggle Help"); 275 glRasterPos2i(60, 370); 276 printstring(GLUT_BITMAP_HELVETICA_12, "f - Toggle Fog"); 277 glRasterPos2i(60, 350); 278 printstring(GLUT_BITMAP_HELVETICA_12, "b - Toggle Back face culling"); 279 glRasterPos2i(60, 330); 280 printstring(GLUT_BITMAP_HELVETICA_12, "p - Toggle Wire frame"); 281 glRasterPos2i(60, 310); 282 printstring(GLUT_BITMAP_HELVETICA_12, "Arrow Keys - Rotate"); 283 glRasterPos2i(60, 290); 284 printstring(GLUT_BITMAP_HELVETICA_12, "a - Increase velocity"); 285 glRasterPos2i(60, 270); 286 printstring(GLUT_BITMAP_HELVETICA_12, "z - Decrease velocity"); 287 288 glRasterPos2i(60, 250); 289 if (joyavailable) 290 printstring(GLUT_BITMAP_HELVETICA_12, 291 "j - Toggle jostick control (Joystick control available)"); 292 else 293 printstring(GLUT_BITMAP_HELVETICA_12, 294 "(No Joystick control available)"); 295 296 glRasterPos2i(60, 230); 297 printstring(GLUT_BITMAP_HELVETICA_12, 298 "To move the light source: s - left, d - right, e - far, x - near, w - down r - up"); 299 glRasterPos2i(60, 210); 300 printstring(GLUT_BITMAP_HELVETICA_12, 301 "To move the mirror sphere: j - left, k - right, i - far, m - near, u - down o - up"); 302 303 glRasterPos2i(60, 190); 304 printstring(GLUT_BITMAP_HELVETICA_12, 305 "1 - Toggle the plane texture map window"); 306 307 glRasterPos2i(60, 170); 308 printstring(GLUT_BITMAP_HELVETICA_12, 309 "2 - Toggle the sphere texture map window"); 310} 311 312static GLboolean 313seelight(float p[3], float dir[3]) 314{ 315 float c[3], b, a, d, t, dist[3]; 316 317 vsub(c, p, objpos); 318 b = -dprod(c, dir); 319 a = dprod(c, c) - SPHERE_RADIUS * SPHERE_RADIUS; 320 321 if ((d = b * b - a) < 0.0 || (b < 0.0 && a > 0.0)) 322 return GL_FALSE; 323 324 d = sqrt(d); 325 326 t = b - d; 327 328 if (t < EPSILON) { 329 t = b + d; 330 if (t < EPSILON) 331 return GL_FALSE; 332 } 333 334 vsub(dist, lightpos, p); 335 if (dprod(dist, dist) < t * t) 336 return GL_FALSE; 337 338 return GL_TRUE; 339} 340 341static int 342colorcheckmap(float ppos[3], float c[3]) 343{ 344 static float norm[3] = { 0.0f, 0.0f, 1.0f }; 345 float ldir[3], vdir[3], h[3], dfact, kfact, r, g, b; 346 int x, y; 347 348 x = (int) ((ppos[0] + BASESIZE / 2) * (10.0f / BASESIZE)); 349 if ((x < 0) || (x > 10)) 350 return GL_FALSE; 351 352 y = (int) ((ppos[1] + BASESIZE / 2) * (10.0f / BASESIZE)); 353 if ((y < 0) || (y > 10)) 354 return GL_FALSE; 355 356 r = 255.0f; 357 if (y & 1) { 358 if (x & 1) 359 g = 255.0f; 360 else 361 g = 0.0f; 362 } 363 else { 364 if (x & 1) 365 g = 0.0f; 366 else 367 g = 255.0f; 368 } 369 b = 0.0f; 370 371 vsub(ldir, lightpos, ppos); 372 vnormalize(ldir, ldir); 373 374 if (seelight(ppos, ldir)) { 375 c[0] = r * 0.05f; 376 c[1] = g * 0.05f; 377 c[2] = b * 0.05f; 378 379 return GL_TRUE; 380 } 381 382 dfact = dprod(ldir, norm); 383 if (dfact < 0.0f) 384 dfact = 0.0f; 385 386 vsub(vdir, obs, ppos); 387 vnormalize(vdir, vdir); 388 h[0] = 0.5f * (vdir[0] + ldir[0]); 389 h[1] = 0.5f * (vdir[1] + ldir[1]); 390 h[2] = 0.5f * (vdir[2] + ldir[2]); 391 kfact = dprod(h, norm); 392 kfact = pow(kfact, 6.0) * 7.0 * 255.0; 393 394 r = r * dfact + kfact; 395 g = g * dfact + kfact; 396 b = b * dfact + kfact; 397 398 c[0] = clamp255(r); 399 c[1] = clamp255(g); 400 c[2] = clamp255(b); 401 402 return GL_TRUE; 403} 404 405static void 406updatecheckmap(int slot) 407{ 408 float c[3], ppos[3]; 409 int x, y; 410 411 glBindTexture(GL_TEXTURE_2D, checkid); 412 413 ppos[2] = 0.0f; 414 for (y = slot * TEX_CHECK_SLOT_SIZE; y < (slot + 1) * TEX_CHECK_SLOT_SIZE; 415 y++) { 416 ppos[1] = (y / (float) TEX_CHECK_HEIGHT) * BASESIZE - BASESIZE / 2; 417 418 for (x = 0; x < TEX_CHECK_WIDTH; x++) { 419 ppos[0] = (x / (float) TEX_CHECK_WIDTH) * BASESIZE - BASESIZE / 2; 420 421 colorcheckmap(ppos, c); 422 checkmap[y][x][0] = (GLubyte) c[0]; 423 checkmap[y][x][1] = (GLubyte) c[1]; 424 checkmap[y][x][2] = (GLubyte) c[2]; 425 } 426 } 427 428 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_CHECK_SLOT_SIZE, 429 TEX_CHECK_WIDTH, TEX_CHECK_SLOT_SIZE, GL_RGB, 430 GL_UNSIGNED_BYTE, 431 &checkmap[slot * TEX_CHECK_SLOT_SIZE][0][0]); 432 433} 434 435static void 436updatereflectmap(int slot) 437{ 438 float rf, r, g, b, t, dfact, kfact, rdir[3]; 439 float rcol[3], ppos[3], norm[3], ldir[3], h[3], vdir[3], planepos[3]; 440 int x, y; 441 442 glBindTexture(GL_TEXTURE_2D, reflectid); 443 444 for (y = slot * TEX_REFLECT_SLOT_SIZE; 445 y < (slot + 1) * TEX_REFLECT_SLOT_SIZE; y++) 446 for (x = 0; x < TEX_REFLECT_WIDTH; x++) { 447 ppos[0] = sphere_pos[y][x][0] + objpos[0]; 448 ppos[1] = sphere_pos[y][x][1] + objpos[1]; 449 ppos[2] = sphere_pos[y][x][2] + objpos[2]; 450 451 vsub(norm, ppos, objpos); 452 vnormalize(norm, norm); 453 454 vsub(ldir, lightpos, ppos); 455 vnormalize(ldir, ldir); 456 vsub(vdir, obs, ppos); 457 vnormalize(vdir, vdir); 458 459 rf = 2.0f * dprod(norm, vdir); 460 if (rf > EPSILON) { 461 rdir[0] = rf * norm[0] - vdir[0]; 462 rdir[1] = rf * norm[1] - vdir[1]; 463 rdir[2] = rf * norm[2] - vdir[2]; 464 465 t = -objpos[2] / rdir[2]; 466 467 if (t > EPSILON) { 468 planepos[0] = objpos[0] + t * rdir[0]; 469 planepos[1] = objpos[1] + t * rdir[1]; 470 planepos[2] = 0.0f; 471 472 if (!colorcheckmap(planepos, rcol)) 473 rcol[0] = rcol[1] = rcol[2] = 0.0f; 474 } 475 else 476 rcol[0] = rcol[1] = rcol[2] = 0.0f; 477 } 478 else 479 rcol[0] = rcol[1] = rcol[2] = 0.0f; 480 481 dfact = 0.1f * dprod(ldir, norm); 482 483 if (dfact < 0.0f) { 484 dfact = 0.0f; 485 kfact = 0.0f; 486 } 487 else { 488 h[0] = 0.5f * (vdir[0] + ldir[0]); 489 h[1] = 0.5f * (vdir[1] + ldir[1]); 490 h[2] = 0.5f * (vdir[2] + ldir[2]); 491 kfact = dprod(h, norm); 492 kfact = pow(kfact, 4.0); 493 if (kfact < 1.0e-10) 494 kfact = 0.0; 495 } 496 497 r = dfact + kfact; 498 g = dfact + kfact; 499 b = dfact + kfact; 500 501 r *= 255.0f; 502 g *= 255.0f; 503 b *= 255.0f; 504 505 r += rcol[0]; 506 g += rcol[1]; 507 b += rcol[2]; 508 509 r = clamp255(r); 510 g = clamp255(g); 511 b = clamp255(b); 512 513 reflectmap[y][x][0] = (GLubyte) r; 514 reflectmap[y][x][1] = (GLubyte) g; 515 reflectmap[y][x][2] = (GLubyte) b; 516 } 517 518 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, slot * TEX_REFLECT_SLOT_SIZE, 519 TEX_REFLECT_WIDTH, TEX_REFLECT_SLOT_SIZE, GL_RGB, 520 GL_UNSIGNED_BYTE, 521 &reflectmap[slot * TEX_REFLECT_SLOT_SIZE][0][0]); 522} 523 524static void 525drawbase(void) 526{ 527 glColor3f(0.0, 0.0, 0.0); 528 glBindTexture(GL_TEXTURE_2D, checkid); 529 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 530 531 glBegin(GL_QUADS); 532 glTexCoord2f(0.0f, 0.0f); 533 glVertex3f(-BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f); 534 535 glTexCoord2f(1.0f, 0.0f); 536 glVertex3f(BASESIZE / 2.0f, -BASESIZE / 2.0f, 0.0f); 537 538 glTexCoord2f(1.0f, 1.0f); 539 glVertex3f(BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f); 540 541 glTexCoord2f(0.0f, 1.0f); 542 glVertex3f(-BASESIZE / 2.0f, BASESIZE / 2.0f, 0.0f); 543 544 glEnd(); 545} 546 547static void 548drawobj(void) 549{ 550 glColor3f(0.0, 0.0, 0.0); 551 glBindTexture(GL_TEXTURE_2D, reflectid); 552 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 553 554 glPushMatrix(); 555 glTranslatef(objpos[0], objpos[1], objpos[2]); 556 glCallList(objdlist); 557 glPopMatrix(); 558} 559 560static void 561dojoy(void) 562{ 563#ifdef WIN32 564 static UINT max[2] = { 0, 0 }; 565 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2]; 566 MMRESULT res; 567 JOYINFO joy; 568 569 res = joyGetPos(JOYSTICKID1, &joy); 570 571 if (res == JOYERR_NOERROR) { 572 joyavailable = 1; 573 574 if (max[0] < joy.wXpos) 575 max[0] = joy.wXpos; 576 if (min[0] > joy.wXpos) 577 min[0] = joy.wXpos; 578 center[0] = (max[0] + min[0]) / 2; 579 580 if (max[1] < joy.wYpos) 581 max[1] = joy.wYpos; 582 if (min[1] > joy.wYpos) 583 min[1] = joy.wYpos; 584 center[1] = (max[1] + min[1]) / 2; 585 586 if (joyactive) { 587 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0])) 588 alpha -= 589 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]); 590 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1])) 591 beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]); 592 593 if (joy.wButtons & JOY_BUTTON1) 594 v += 0.005; 595 if (joy.wButtons & JOY_BUTTON2) 596 v -= 0.005; 597 } 598 } 599 else 600 joyavailable = 0; 601#endif 602} 603 604static void 605updatemaps(void) 606{ 607 updatecheckmap(checkmap_currentslot); 608 checkmap_currentslot = (checkmap_currentslot + 1) % TEX_CHECK_NUMSLOT; 609 610 updatereflectmap(reflectmap_currentslot); 611 reflectmap_currentslot = 612 (reflectmap_currentslot + 1) % TEX_REFLECT_NUMSLOT; 613} 614 615static void 616draw(void) 617{ 618 static char frbuf[80] = ""; 619 620 dojoy(); 621 622 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 623 624 glEnable(GL_TEXTURE_2D); 625 glEnable(GL_DEPTH_TEST); 626 if (fog) 627 glEnable(GL_FOG); 628 else 629 glDisable(GL_FOG); 630 631 glPushMatrix(); 632 calcposobs(); 633 634 gluLookAt(obs[0], obs[1], obs[2], 635 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2], 636 0.0, 0.0, 1.0); 637 638 drawbase(); 639 drawobj(); 640 641 glColor3f(1.0, 1.0, 1.0); 642 glDisable(GL_TEXTURE_2D); 643 644 glPushMatrix(); 645 glTranslatef(lightpos[0], lightpos[1], lightpos[2]); 646 glCallList(lightdlist); 647 glPopMatrix(); 648 649 glPopMatrix(); 650 651 glDisable(GL_DEPTH_TEST); 652 glDisable(GL_FOG); 653 654 glMatrixMode(GL_PROJECTION); 655 glPushMatrix(); 656 glLoadIdentity(); 657 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0); 658 glMatrixMode(GL_MODELVIEW); 659 660 glColor3f(0.0f, 0.3f, 1.0f); 661 662 if (showcheckmap) { 663 glEnable(GL_TEXTURE_2D); 664 glBindTexture(GL_TEXTURE_2D, checkid); 665 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 666 667 glBegin(GL_QUADS); 668 glTexCoord2f(1.0f, 0.0f); 669 glVertex2i(10, 30); 670 glTexCoord2f(1.0f, 1.0f); 671 glVertex2i(10 + 90, 30); 672 glTexCoord2f(0.0f, 1.0f); 673 glVertex2i(10 + 90, 30 + 90); 674 glTexCoord2f(0.0f, 0.0f); 675 glVertex2i(10, 30 + 90); 676 glEnd(); 677 678 glDisable(GL_TEXTURE_2D); 679 glBegin(GL_LINE_LOOP); 680 glVertex2i(10, 30); 681 glVertex2i(10 + 90, 30); 682 glVertex2i(10 + 90, 30 + 90); 683 glVertex2i(10, 30 + 90); 684 glEnd(); 685 glRasterPos2i(105, 65); 686 printstring(GLUT_BITMAP_HELVETICA_18, "Plane Texture Map"); 687 } 688 689 if (showreflectmap) { 690 glEnable(GL_TEXTURE_2D); 691 glBindTexture(GL_TEXTURE_2D, reflectid); 692 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 693 694 glBegin(GL_QUADS); 695 glTexCoord2f(1.0f, 0.0f); 696 glVertex2i(540, 30); 697 glTexCoord2f(1.0f, 1.0f); 698 glVertex2i(540 + 90, 30); 699 glTexCoord2f(0.0f, 1.0f); 700 glVertex2i(540 + 90, 30 + 90); 701 glTexCoord2f(0.0f, 0.0f); 702 glVertex2i(540, 30 + 90); 703 glEnd(); 704 705 glDisable(GL_TEXTURE_2D); 706 glBegin(GL_LINE_LOOP); 707 glVertex2i(540, 30); 708 glVertex2i(540 + 90, 30); 709 glVertex2i(540 + 90, 30 + 90); 710 glVertex2i(540, 30 + 90); 711 glEnd(); 712 glRasterPos2i(360, 65); 713 printstring(GLUT_BITMAP_HELVETICA_18, "Sphere Texture Map"); 714 } 715 716 glDisable(GL_TEXTURE_2D); 717 718 glRasterPos2i(10, 10); 719 printstring(GLUT_BITMAP_HELVETICA_18, frbuf); 720 glRasterPos2i(360, 470); 721 printstring(GLUT_BITMAP_HELVETICA_10, 722 "Ray V1.0 Written by David Bucciarelli (tech.hmw@plus.it)"); 723 724 if (help) 725 printhelp(); 726 727 glMatrixMode(GL_PROJECTION); 728 glPopMatrix(); 729 glMatrixMode(GL_MODELVIEW); 730 731 updatemaps(); 732 733 glutSwapBuffers(); 734 735 Frames++; 736 { 737 GLint t = glutGet(GLUT_ELAPSED_TIME); 738 if (t - T0 >= 2000) { 739 GLfloat seconds = (t - T0) / 1000.0; 740 GLfloat fps = Frames / seconds; 741 sprintf(frbuf, "Frame rate: %f", fps); 742 printf("%s\n", frbuf); 743 T0 = t; 744 Frames = 0; 745 } 746 } 747} 748 749static void 750inittextures(void) 751{ 752 int y; 753 754 glGenTextures(1, &checkid); 755 glBindTexture(GL_TEXTURE_2D, checkid); 756 757 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 758 glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_CHECK_WIDTH, TEX_CHECK_HEIGHT, 759 0, GL_RGB, GL_UNSIGNED_BYTE, checkmap); 760 761 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 762 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 763 764 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 765 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 766 767 for (y = 0; y < TEX_CHECK_NUMSLOT; y++) 768 updatecheckmap(y); 769 770 771 772 glGenTextures(1, &reflectid); 773 glBindTexture(GL_TEXTURE_2D, reflectid); 774 775 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 776 glTexImage2D(GL_TEXTURE_2D, 0, 3, TEX_REFLECT_WIDTH, TEX_REFLECT_HEIGHT, 777 0, GL_RGB, GL_UNSIGNED_BYTE, reflectmap); 778 779 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 780 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 781 782 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 783 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 784 785 for (y = 0; y < TEX_REFLECT_NUMSLOT; y++) 786 updatereflectmap(y); 787 788 789} 790 791static void 792initspherepos(void) 793{ 794 float alpha, beta, sa, ca, sb, cb; 795 int x, y; 796 797 for (y = 0; y < TEX_REFLECT_HEIGHT; y++) { 798 beta = M_PI - y * (M_PI / TEX_REFLECT_HEIGHT); 799 800 for (x = 0; x < TEX_REFLECT_WIDTH; x++) { 801 alpha = -x * (2.0f * M_PI / TEX_REFLECT_WIDTH); 802 803 sa = sin(alpha); 804 ca = cos(alpha); 805 806 sb = sin(beta); 807 cb = cos(beta); 808 809 sphere_pos[y][x][0] = SPHERE_RADIUS * sa * sb; 810 sphere_pos[y][x][1] = SPHERE_RADIUS * ca * sb; 811 sphere_pos[y][x][2] = SPHERE_RADIUS * cb; 812 } 813 } 814} 815 816static void 817initdlists(void) 818{ 819 GLUquadricObj *obj; 820 821 obj = gluNewQuadric(); 822 823 lightdlist = glGenLists(1); 824 glNewList(lightdlist, GL_COMPILE); 825 gluQuadricDrawStyle(obj, GLU_FILL); 826 gluQuadricNormals(obj, GLU_NONE); 827 gluQuadricTexture(obj, GL_TRUE); 828 gluSphere(obj, 0.25f, 6, 6); 829 glEndList(); 830 831 objdlist = glGenLists(1); 832 glNewList(objdlist, GL_COMPILE); 833 gluQuadricDrawStyle(obj, GLU_FILL); 834 gluQuadricNormals(obj, GLU_NONE); 835 gluQuadricTexture(obj, GL_TRUE); 836 gluSphere(obj, SPHERE_RADIUS, 16, 16); 837 glEndList(); 838 839 gluDeleteQuadric(obj); 840} 841 842int 843main(int ac, char **av) 844{ 845 fprintf(stderr, 846 "Ray V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n"); 847 848 /* 849 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) { 850 fprintf(stderr,"Error setting the process class.\n"); 851 return 0; 852 } 853 854 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) { 855 fprintf(stderr,"Error setting the process priority.\n"); 856 return 0; 857 } 858 */ 859 860 glutInitWindowSize(WIDTH, HEIGHT); 861 glutInit(&ac, av); 862 863 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 864 865 if (!(win = glutCreateWindow("Ray"))) { 866 fprintf(stderr, "Error, couldn't open window\n"); 867 return -1; 868 } 869 870 reshape(WIDTH, HEIGHT); 871 872 glShadeModel(GL_FLAT); 873 glEnable(GL_DEPTH_TEST); 874 glDepthFunc(GL_LEQUAL); 875 glEnable(GL_CULL_FACE); 876 glEnable(GL_TEXTURE_2D); 877 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 878 879 glEnable(GL_FOG); 880 glFogi(GL_FOG_MODE, GL_EXP2); 881 glFogfv(GL_FOG_COLOR, fogcolor); 882 883 glFogf(GL_FOG_DENSITY, 0.01); 884#ifdef FX 885 glHint(GL_FOG_HINT, GL_NICEST); 886#endif 887 888 calcposobs(); 889 890 initspherepos(); 891 892 inittextures(); 893 initdlists(); 894 895 glClearColor(fogcolor[0], fogcolor[1], fogcolor[2], fogcolor[3]); 896 897 glutReshapeFunc(reshape); 898 glutDisplayFunc(draw); 899 glutKeyboardFunc(key); 900 glutSpecialFunc(special); 901 glutIdleFunc(draw); 902 903 glutMainLoop(); 904 905 return 0; 906} 907