|
|
1.1 ! root 1: // gl_warp.c -- sky and water polygons ! 2: ! 3: #include "quakedef.h" ! 4: ! 5: extern model_t *loadmodel; ! 6: ! 7: int skytexturenum; ! 8: ! 9: int solidskytexture; ! 10: int alphaskytexture; ! 11: float speedscale; // for top sky and bottom sky ! 12: ! 13: msurface_t *warpface; ! 14: ! 15: #define SUBDIVIDE_SIZE 64 ! 16: ! 17: void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs) ! 18: { ! 19: int i, j; ! 20: float *v; ! 21: ! 22: mins[0] = mins[1] = mins[2] = 9999; ! 23: maxs[0] = maxs[1] = maxs[2] = -9999; ! 24: v = verts; ! 25: for (i=0 ; i<numverts ; i++) ! 26: for (j=0 ; j<3 ; j++, v++) ! 27: { ! 28: if (*v < mins[j]) ! 29: mins[j] = *v; ! 30: if (*v > maxs[j]) ! 31: maxs[j] = *v; ! 32: } ! 33: } ! 34: ! 35: void SubdividePolygon (int numverts, float *verts) ! 36: { ! 37: int i, j, k; ! 38: vec3_t mins, maxs; ! 39: float m; ! 40: float *v; ! 41: vec3_t front[64], back[64]; ! 42: int f, b; ! 43: float dist[64]; ! 44: float frac; ! 45: glpoly_t *poly; ! 46: float s, t; ! 47: ! 48: if (numverts > 60) ! 49: Sys_Error ("numverts = %i", numverts); ! 50: ! 51: BoundPoly (numverts, verts, mins, maxs); ! 52: ! 53: for (i=0 ; i<3 ; i++) ! 54: { ! 55: m = (mins[i] + maxs[i]) * 0.5; ! 56: m = SUBDIVIDE_SIZE * floor (m/SUBDIVIDE_SIZE + 0.5); ! 57: if (maxs[i] - m < 8) ! 58: continue; ! 59: if (m - mins[i] < 8) ! 60: continue; ! 61: ! 62: // cut it ! 63: v = verts + i; ! 64: for (j=0 ; j<numverts ; j++, v+= 3) ! 65: dist[j] = *v - m; ! 66: ! 67: // wrap cases ! 68: dist[j] = dist[0]; ! 69: v-=i; ! 70: VectorCopy (verts, v); ! 71: ! 72: f = b = 0; ! 73: v = verts; ! 74: for (j=0 ; j<numverts ; j++, v+= 3) ! 75: { ! 76: if (dist[j] >= 0) ! 77: { ! 78: VectorCopy (v, front[f]); ! 79: f++; ! 80: } ! 81: if (dist[j] <= 0) ! 82: { ! 83: VectorCopy (v, back[b]); ! 84: b++; ! 85: } ! 86: if (dist[j] == 0 || dist[j+1] == 0) ! 87: continue; ! 88: if ( (dist[j] > 0) != (dist[j+1] > 0) ) ! 89: { ! 90: // clip point ! 91: frac = dist[j] / (dist[j] - dist[j+1]); ! 92: for (k=0 ; k<3 ; k++) ! 93: front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]); ! 94: f++; ! 95: b++; ! 96: } ! 97: } ! 98: ! 99: SubdividePolygon (f, front[0]); ! 100: SubdividePolygon (b, back[0]); ! 101: return; ! 102: } ! 103: ! 104: poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float)); ! 105: poly->next = warpface->polys; ! 106: warpface->polys = poly; ! 107: poly->numverts = numverts; ! 108: for (i=0 ; i<numverts ; i++, verts+= 3) ! 109: { ! 110: VectorCopy (verts, poly->verts[i]); ! 111: s = DotProduct (verts, warpface->texinfo->vecs[0]); ! 112: t = DotProduct (verts, warpface->texinfo->vecs[1]); ! 113: poly->verts[i][3] = s; ! 114: poly->verts[i][4] = t; ! 115: } ! 116: } ! 117: ! 118: /* ! 119: ================ ! 120: GL_SubdivideSurface ! 121: ! 122: Breaks a polygon up along axial 64 unit ! 123: boundaries so that turbulent and sky warps ! 124: can be done reasonably. ! 125: ================ ! 126: */ ! 127: void GL_SubdivideSurface (msurface_t *fa) ! 128: { ! 129: vec3_t verts[64]; ! 130: int numverts; ! 131: int i; ! 132: int lindex; ! 133: float *vec; ! 134: texture_t *t; ! 135: ! 136: warpface = fa; ! 137: ! 138: // ! 139: // convert edges back to a normal polygon ! 140: // ! 141: numverts = 0; ! 142: for (i=0 ; i<fa->numedges ; i++) ! 143: { ! 144: lindex = loadmodel->surfedges[fa->firstedge + i]; ! 145: ! 146: if (lindex > 0) ! 147: vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; ! 148: else ! 149: vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; ! 150: VectorCopy (vec, verts[numverts]); ! 151: numverts++; ! 152: } ! 153: ! 154: SubdividePolygon (numverts, verts[0]); ! 155: } ! 156: ! 157: //========================================================= ! 158: ! 159: ! 160: ! 161: // speed up sin calculations - Ed ! 162: float turbsin[] = ! 163: { ! 164: #include "gl_warp_sin.h" ! 165: }; ! 166: #define TURBSCALE (256.0 / (2 * M_PI)) ! 167: ! 168: /* ! 169: ============= ! 170: EmitWaterPolys ! 171: ! 172: Does a water warp on the pre-fragmented glpoly_t chain ! 173: ============= ! 174: */ ! 175: void EmitWaterPolys (msurface_t *fa) ! 176: { ! 177: glpoly_t *p; ! 178: float *v; ! 179: int i; ! 180: float s, t, os, ot; ! 181: ! 182: ! 183: for (p=fa->polys ; p ; p=p->next) ! 184: { ! 185: glBegin (GL_POLYGON); ! 186: for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE) ! 187: { ! 188: os = v[3]; ! 189: ot = v[4]; ! 190: ! 191: s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255]; ! 192: s *= (1.0/64); ! 193: ! 194: t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255]; ! 195: t *= (1.0/64); ! 196: ! 197: glTexCoord2f (s, t); ! 198: glVertex3fv (v); ! 199: } ! 200: glEnd (); ! 201: } ! 202: } ! 203: ! 204: ! 205: ! 206: ! 207: /* ! 208: ============= ! 209: EmitSkyPolys ! 210: ============= ! 211: */ ! 212: void EmitSkyPolys (msurface_t *fa) ! 213: { ! 214: glpoly_t *p; ! 215: float *v; ! 216: int i; ! 217: float s, t; ! 218: vec3_t dir; ! 219: float length; ! 220: ! 221: for (p=fa->polys ; p ; p=p->next) ! 222: { ! 223: glBegin (GL_POLYGON); ! 224: for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE) ! 225: { ! 226: VectorSubtract (v, r_origin, dir); ! 227: dir[2] *= 3; // flatten the sphere ! 228: ! 229: length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]; ! 230: length = sqrt (length); ! 231: length = 6*63/length; ! 232: ! 233: dir[0] *= length; ! 234: dir[1] *= length; ! 235: ! 236: s = (speedscale + dir[0]) * (1.0/128); ! 237: t = (speedscale + dir[1]) * (1.0/128); ! 238: ! 239: glTexCoord2f (s, t); ! 240: glVertex3fv (v); ! 241: } ! 242: glEnd (); ! 243: } ! 244: } ! 245: ! 246: /* ! 247: =============== ! 248: EmitBothSkyLayers ! 249: ! 250: Does a sky warp on the pre-fragmented glpoly_t chain ! 251: This will be called for brushmodels, the world ! 252: will have them chained together. ! 253: =============== ! 254: */ ! 255: void EmitBothSkyLayers (msurface_t *fa) ! 256: { ! 257: int i; ! 258: int lindex; ! 259: float *vec; ! 260: ! 261: GL_Bind (solidskytexture); ! 262: speedscale = realtime*8; ! 263: speedscale -= (int)speedscale & ~127 ; ! 264: ! 265: EmitSkyPolys (fa); ! 266: ! 267: glEnable (GL_BLEND); ! 268: GL_Bind (alphaskytexture); ! 269: speedscale = realtime*16; ! 270: speedscale -= (int)speedscale & ~127 ; ! 271: ! 272: EmitSkyPolys (fa); ! 273: ! 274: glDisable (GL_BLEND); ! 275: } ! 276: ! 277: #ifndef QUAKE2 ! 278: /* ! 279: ================= ! 280: R_DrawSkyChain ! 281: ================= ! 282: */ ! 283: void R_DrawSkyChain (msurface_t *s) ! 284: { ! 285: msurface_t *fa; ! 286: ! 287: // used when gl_texsort is on ! 288: GL_Bind(solidskytexture); ! 289: speedscale = realtime*8; ! 290: speedscale -= (int)speedscale & ~127 ; ! 291: ! 292: for (fa=s ; fa ; fa=fa->texturechain) ! 293: EmitSkyPolys (fa); ! 294: ! 295: glEnable (GL_BLEND); ! 296: GL_Bind (alphaskytexture); ! 297: speedscale = realtime*16; ! 298: speedscale -= (int)speedscale & ~127 ; ! 299: ! 300: for (fa=s ; fa ; fa=fa->texturechain) ! 301: EmitSkyPolys (fa); ! 302: ! 303: glDisable (GL_BLEND); ! 304: } ! 305: ! 306: #endif ! 307: ! 308: /* ! 309: ================================================================= ! 310: ! 311: Quake 2 environment sky ! 312: ! 313: ================================================================= ! 314: */ ! 315: ! 316: #ifdef QUAKE2 ! 317: ! 318: ! 319: #define SKY_TEX 2000 ! 320: ! 321: /* ! 322: ================================================================= ! 323: ! 324: PCX Loading ! 325: ! 326: ================================================================= ! 327: */ ! 328: ! 329: typedef struct ! 330: { ! 331: char manufacturer; ! 332: char version; ! 333: char encoding; ! 334: char bits_per_pixel; ! 335: unsigned short xmin,ymin,xmax,ymax; ! 336: unsigned short hres,vres; ! 337: unsigned char palette[48]; ! 338: char reserved; ! 339: char color_planes; ! 340: unsigned short bytes_per_line; ! 341: unsigned short palette_type; ! 342: char filler[58]; ! 343: unsigned data; // unbounded ! 344: } pcx_t; ! 345: ! 346: byte *pcx_rgb; ! 347: ! 348: /* ! 349: ============ ! 350: LoadPCX ! 351: ============ ! 352: */ ! 353: void LoadPCX (FILE *f) ! 354: { ! 355: pcx_t *pcx, pcxbuf; ! 356: byte palette[768]; ! 357: byte *pix; ! 358: int x, y; ! 359: int dataByte, runLength; ! 360: int count; ! 361: ! 362: // ! 363: // parse the PCX file ! 364: // ! 365: fread (&pcxbuf, 1, sizeof(pcxbuf), f); ! 366: ! 367: pcx = &pcxbuf; ! 368: ! 369: if (pcx->manufacturer != 0x0a ! 370: || pcx->version != 5 ! 371: || pcx->encoding != 1 ! 372: || pcx->bits_per_pixel != 8 ! 373: || pcx->xmax >= 320 ! 374: || pcx->ymax >= 256) ! 375: { ! 376: Con_Printf ("Bad pcx file\n"); ! 377: return; ! 378: } ! 379: ! 380: // seek to palette ! 381: fseek (f, -768, SEEK_END); ! 382: fread (palette, 1, 768, f); ! 383: ! 384: fseek (f, sizeof(pcxbuf) - 4, SEEK_SET); ! 385: ! 386: count = (pcx->xmax+1) * (pcx->ymax+1); ! 387: pcx_rgb = malloc( count * 4); ! 388: ! 389: for (y=0 ; y<=pcx->ymax ; y++) ! 390: { ! 391: pix = pcx_rgb + 4*y*(pcx->xmax+1); ! 392: for (x=0 ; x<=pcx->ymax ; ) ! 393: { ! 394: dataByte = fgetc(f); ! 395: ! 396: if((dataByte & 0xC0) == 0xC0) ! 397: { ! 398: runLength = dataByte & 0x3F; ! 399: dataByte = fgetc(f); ! 400: } ! 401: else ! 402: runLength = 1; ! 403: ! 404: while(runLength-- > 0) ! 405: { ! 406: pix[0] = palette[dataByte*3]; ! 407: pix[1] = palette[dataByte*3+1]; ! 408: pix[2] = palette[dataByte*3+2]; ! 409: pix[3] = 255; ! 410: pix += 4; ! 411: x++; ! 412: } ! 413: } ! 414: } ! 415: } ! 416: ! 417: /* ! 418: ========================================================= ! 419: ! 420: TARGA LOADING ! 421: ! 422: ========================================================= ! 423: */ ! 424: ! 425: typedef struct _TargaHeader { ! 426: unsigned char id_length, colormap_type, image_type; ! 427: unsigned short colormap_index, colormap_length; ! 428: unsigned char colormap_size; ! 429: unsigned short x_origin, y_origin, width, height; ! 430: unsigned char pixel_size, attributes; ! 431: } TargaHeader; ! 432: ! 433: ! 434: TargaHeader targa_header; ! 435: byte *targa_rgba; ! 436: ! 437: int fgetLittleShort (FILE *f) ! 438: { ! 439: byte b1, b2; ! 440: ! 441: b1 = fgetc(f); ! 442: b2 = fgetc(f); ! 443: ! 444: return (short)(b1 + b2*256); ! 445: } ! 446: ! 447: int fgetLittleLong (FILE *f) ! 448: { ! 449: byte b1, b2, b3, b4; ! 450: ! 451: b1 = fgetc(f); ! 452: b2 = fgetc(f); ! 453: b3 = fgetc(f); ! 454: b4 = fgetc(f); ! 455: ! 456: return b1 + (b2<<8) + (b3<<16) + (b4<<24); ! 457: } ! 458: ! 459: ! 460: /* ! 461: ============= ! 462: LoadTGA ! 463: ============= ! 464: */ ! 465: void LoadTGA (FILE *fin) ! 466: { ! 467: int columns, rows, numPixels; ! 468: byte *pixbuf; ! 469: int row, column; ! 470: ! 471: targa_header.id_length = fgetc(fin); ! 472: targa_header.colormap_type = fgetc(fin); ! 473: targa_header.image_type = fgetc(fin); ! 474: ! 475: targa_header.colormap_index = fgetLittleShort(fin); ! 476: targa_header.colormap_length = fgetLittleShort(fin); ! 477: targa_header.colormap_size = fgetc(fin); ! 478: targa_header.x_origin = fgetLittleShort(fin); ! 479: targa_header.y_origin = fgetLittleShort(fin); ! 480: targa_header.width = fgetLittleShort(fin); ! 481: targa_header.height = fgetLittleShort(fin); ! 482: targa_header.pixel_size = fgetc(fin); ! 483: targa_header.attributes = fgetc(fin); ! 484: ! 485: if (targa_header.image_type!=2 ! 486: && targa_header.image_type!=10) ! 487: Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n"); ! 488: ! 489: if (targa_header.colormap_type !=0 ! 490: || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) ! 491: Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); ! 492: ! 493: columns = targa_header.width; ! 494: rows = targa_header.height; ! 495: numPixels = columns * rows; ! 496: ! 497: targa_rgba = malloc (numPixels*4); ! 498: ! 499: if (targa_header.id_length != 0) ! 500: fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment ! 501: ! 502: if (targa_header.image_type==2) { // Uncompressed, RGB images ! 503: for(row=rows-1; row>=0; row--) { ! 504: pixbuf = targa_rgba + row*columns*4; ! 505: for(column=0; column<columns; column++) { ! 506: unsigned char red,green,blue,alphabyte; ! 507: switch (targa_header.pixel_size) { ! 508: case 24: ! 509: ! 510: blue = getc(fin); ! 511: green = getc(fin); ! 512: red = getc(fin); ! 513: *pixbuf++ = red; ! 514: *pixbuf++ = green; ! 515: *pixbuf++ = blue; ! 516: *pixbuf++ = 255; ! 517: break; ! 518: case 32: ! 519: blue = getc(fin); ! 520: green = getc(fin); ! 521: red = getc(fin); ! 522: alphabyte = getc(fin); ! 523: *pixbuf++ = red; ! 524: *pixbuf++ = green; ! 525: *pixbuf++ = blue; ! 526: *pixbuf++ = alphabyte; ! 527: break; ! 528: } ! 529: } ! 530: } ! 531: } ! 532: else if (targa_header.image_type==10) { // Runlength encoded RGB images ! 533: unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; ! 534: for(row=rows-1; row>=0; row--) { ! 535: pixbuf = targa_rgba + row*columns*4; ! 536: for(column=0; column<columns; ) { ! 537: packetHeader=getc(fin); ! 538: packetSize = 1 + (packetHeader & 0x7f); ! 539: if (packetHeader & 0x80) { // run-length packet ! 540: switch (targa_header.pixel_size) { ! 541: case 24: ! 542: blue = getc(fin); ! 543: green = getc(fin); ! 544: red = getc(fin); ! 545: alphabyte = 255; ! 546: break; ! 547: case 32: ! 548: blue = getc(fin); ! 549: green = getc(fin); ! 550: red = getc(fin); ! 551: alphabyte = getc(fin); ! 552: break; ! 553: } ! 554: ! 555: for(j=0;j<packetSize;j++) { ! 556: *pixbuf++=red; ! 557: *pixbuf++=green; ! 558: *pixbuf++=blue; ! 559: *pixbuf++=alphabyte; ! 560: column++; ! 561: if (column==columns) { // run spans across rows ! 562: column=0; ! 563: if (row>0) ! 564: row--; ! 565: else ! 566: goto breakOut; ! 567: pixbuf = targa_rgba + row*columns*4; ! 568: } ! 569: } ! 570: } ! 571: else { // non run-length packet ! 572: for(j=0;j<packetSize;j++) { ! 573: switch (targa_header.pixel_size) { ! 574: case 24: ! 575: blue = getc(fin); ! 576: green = getc(fin); ! 577: red = getc(fin); ! 578: *pixbuf++ = red; ! 579: *pixbuf++ = green; ! 580: *pixbuf++ = blue; ! 581: *pixbuf++ = 255; ! 582: break; ! 583: case 32: ! 584: blue = getc(fin); ! 585: green = getc(fin); ! 586: red = getc(fin); ! 587: alphabyte = getc(fin); ! 588: *pixbuf++ = red; ! 589: *pixbuf++ = green; ! 590: *pixbuf++ = blue; ! 591: *pixbuf++ = alphabyte; ! 592: break; ! 593: } ! 594: column++; ! 595: if (column==columns) { // pixel packet run spans across rows ! 596: column=0; ! 597: if (row>0) ! 598: row--; ! 599: else ! 600: goto breakOut; ! 601: pixbuf = targa_rgba + row*columns*4; ! 602: } ! 603: } ! 604: } ! 605: } ! 606: breakOut:; ! 607: } ! 608: } ! 609: ! 610: fclose(fin); ! 611: } ! 612: ! 613: /* ! 614: ================== ! 615: R_LoadSkys ! 616: ================== ! 617: */ ! 618: char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; ! 619: void R_LoadSkys (void) ! 620: { ! 621: int i; ! 622: FILE *f; ! 623: char name[64]; ! 624: ! 625: for (i=0 ; i<6 ; i++) ! 626: { ! 627: GL_Bind (SKY_TEX + i); ! 628: sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]); ! 629: COM_FOpenFile (name, &f); ! 630: if (!f) ! 631: { ! 632: Con_Printf ("Couldn't load %s\n", name); ! 633: continue; ! 634: } ! 635: LoadTGA (f); ! 636: // LoadPCX (f); ! 637: ! 638: glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba); ! 639: // glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb); ! 640: ! 641: free (targa_rgba); ! 642: // free (pcx_rgb); ! 643: ! 644: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ! 645: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ! 646: } ! 647: } ! 648: ! 649: ! 650: vec3_t skyclip[6] = { ! 651: {1,1,0}, ! 652: {1,-1,0}, ! 653: {0,-1,1}, ! 654: {0,1,1}, ! 655: {1,0,1}, ! 656: {-1,0,1} ! 657: }; ! 658: int c_sky; ! 659: ! 660: // 1 = s, 2 = t, 3 = 2048 ! 661: int st_to_vec[6][3] = ! 662: { ! 663: {3,-1,2}, ! 664: {-3,1,2}, ! 665: ! 666: {1,3,2}, ! 667: {-1,-3,2}, ! 668: ! 669: {-2,-1,3}, // 0 degrees yaw, look straight up ! 670: {2,-1,-3} // look straight down ! 671: ! 672: // {-1,2,3}, ! 673: // {1,2,-3} ! 674: }; ! 675: ! 676: // s = [0]/[2], t = [1]/[2] ! 677: int vec_to_st[6][3] = ! 678: { ! 679: {-2,3,1}, ! 680: {2,3,-1}, ! 681: ! 682: {1,3,2}, ! 683: {-1,3,-2}, ! 684: ! 685: {-2,-1,3}, ! 686: {-2,1,-3} ! 687: ! 688: // {-1,2,3}, ! 689: // {1,2,-3} ! 690: }; ! 691: ! 692: float skymins[2][6], skymaxs[2][6]; ! 693: ! 694: void DrawSkyPolygon (int nump, vec3_t vecs) ! 695: { ! 696: int i,j; ! 697: vec3_t v, av; ! 698: float s, t, dv; ! 699: int axis; ! 700: float *vp; ! 701: ! 702: c_sky++; ! 703: #if 0 ! 704: glBegin (GL_POLYGON); ! 705: for (i=0 ; i<nump ; i++, vecs+=3) ! 706: { ! 707: VectorAdd(vecs, r_origin, v); ! 708: glVertex3fv (v); ! 709: } ! 710: glEnd(); ! 711: return; ! 712: #endif ! 713: // decide which face it maps to ! 714: VectorCopy (vec3_origin, v); ! 715: for (i=0, vp=vecs ; i<nump ; i++, vp+=3) ! 716: { ! 717: VectorAdd (vp, v, v); ! 718: } ! 719: av[0] = fabs(v[0]); ! 720: av[1] = fabs(v[1]); ! 721: av[2] = fabs(v[2]); ! 722: if (av[0] > av[1] && av[0] > av[2]) ! 723: { ! 724: if (v[0] < 0) ! 725: axis = 1; ! 726: else ! 727: axis = 0; ! 728: } ! 729: else if (av[1] > av[2] && av[1] > av[0]) ! 730: { ! 731: if (v[1] < 0) ! 732: axis = 3; ! 733: else ! 734: axis = 2; ! 735: } ! 736: else ! 737: { ! 738: if (v[2] < 0) ! 739: axis = 5; ! 740: else ! 741: axis = 4; ! 742: } ! 743: ! 744: // project new texture coords ! 745: for (i=0 ; i<nump ; i++, vecs+=3) ! 746: { ! 747: j = vec_to_st[axis][2]; ! 748: if (j > 0) ! 749: dv = vecs[j - 1]; ! 750: else ! 751: dv = -vecs[-j - 1]; ! 752: ! 753: j = vec_to_st[axis][0]; ! 754: if (j < 0) ! 755: s = -vecs[-j -1] / dv; ! 756: else ! 757: s = vecs[j-1] / dv; ! 758: j = vec_to_st[axis][1]; ! 759: if (j < 0) ! 760: t = -vecs[-j -1] / dv; ! 761: else ! 762: t = vecs[j-1] / dv; ! 763: ! 764: if (s < skymins[0][axis]) ! 765: skymins[0][axis] = s; ! 766: if (t < skymins[1][axis]) ! 767: skymins[1][axis] = t; ! 768: if (s > skymaxs[0][axis]) ! 769: skymaxs[0][axis] = s; ! 770: if (t > skymaxs[1][axis]) ! 771: skymaxs[1][axis] = t; ! 772: } ! 773: } ! 774: ! 775: #define MAX_CLIP_VERTS 64 ! 776: void ClipSkyPolygon (int nump, vec3_t vecs, int stage) ! 777: { ! 778: float *norm; ! 779: float *v; ! 780: qboolean front, back; ! 781: float d, e; ! 782: float dists[MAX_CLIP_VERTS]; ! 783: int sides[MAX_CLIP_VERTS]; ! 784: vec3_t newv[2][MAX_CLIP_VERTS]; ! 785: int newc[2]; ! 786: int i, j; ! 787: ! 788: if (nump > MAX_CLIP_VERTS-2) ! 789: Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS"); ! 790: if (stage == 6) ! 791: { // fully clipped, so draw it ! 792: DrawSkyPolygon (nump, vecs); ! 793: return; ! 794: } ! 795: ! 796: front = back = false; ! 797: norm = skyclip[stage]; ! 798: for (i=0, v = vecs ; i<nump ; i++, v+=3) ! 799: { ! 800: d = DotProduct (v, norm); ! 801: if (d > ON_EPSILON) ! 802: { ! 803: front = true; ! 804: sides[i] = SIDE_FRONT; ! 805: } ! 806: else if (d < ON_EPSILON) ! 807: { ! 808: back = true; ! 809: sides[i] = SIDE_BACK; ! 810: } ! 811: else ! 812: sides[i] = SIDE_ON; ! 813: dists[i] = d; ! 814: } ! 815: ! 816: if (!front || !back) ! 817: { // not clipped ! 818: ClipSkyPolygon (nump, vecs, stage+1); ! 819: return; ! 820: } ! 821: ! 822: // clip it ! 823: sides[i] = sides[0]; ! 824: dists[i] = dists[0]; ! 825: VectorCopy (vecs, (vecs+(i*3)) ); ! 826: newc[0] = newc[1] = 0; ! 827: ! 828: for (i=0, v = vecs ; i<nump ; i++, v+=3) ! 829: { ! 830: switch (sides[i]) ! 831: { ! 832: case SIDE_FRONT: ! 833: VectorCopy (v, newv[0][newc[0]]); ! 834: newc[0]++; ! 835: break; ! 836: case SIDE_BACK: ! 837: VectorCopy (v, newv[1][newc[1]]); ! 838: newc[1]++; ! 839: break; ! 840: case SIDE_ON: ! 841: VectorCopy (v, newv[0][newc[0]]); ! 842: newc[0]++; ! 843: VectorCopy (v, newv[1][newc[1]]); ! 844: newc[1]++; ! 845: break; ! 846: } ! 847: ! 848: if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) ! 849: continue; ! 850: ! 851: d = dists[i] / (dists[i] - dists[i+1]); ! 852: for (j=0 ; j<3 ; j++) ! 853: { ! 854: e = v[j] + d*(v[j+3] - v[j]); ! 855: newv[0][newc[0]][j] = e; ! 856: newv[1][newc[1]][j] = e; ! 857: } ! 858: newc[0]++; ! 859: newc[1]++; ! 860: } ! 861: ! 862: // continue ! 863: ClipSkyPolygon (newc[0], newv[0][0], stage+1); ! 864: ClipSkyPolygon (newc[1], newv[1][0], stage+1); ! 865: } ! 866: ! 867: /* ! 868: ================= ! 869: R_DrawSkyChain ! 870: ================= ! 871: */ ! 872: void R_DrawSkyChain (msurface_t *s) ! 873: { ! 874: msurface_t *fa; ! 875: ! 876: int i; ! 877: vec3_t verts[MAX_CLIP_VERTS]; ! 878: glpoly_t *p; ! 879: ! 880: c_sky = 0; ! 881: GL_Bind(solidskytexture); ! 882: ! 883: // calculate vertex values for sky box ! 884: ! 885: for (fa=s ; fa ; fa=fa->texturechain) ! 886: { ! 887: for (p=fa->polys ; p ; p=p->next) ! 888: { ! 889: for (i=0 ; i<p->numverts ; i++) ! 890: { ! 891: VectorSubtract (p->verts[i], r_origin, verts[i]); ! 892: } ! 893: ClipSkyPolygon (p->numverts, verts[0], 0); ! 894: } ! 895: } ! 896: } ! 897: ! 898: ! 899: /* ! 900: ============== ! 901: R_ClearSkyBox ! 902: ============== ! 903: */ ! 904: void R_ClearSkyBox (void) ! 905: { ! 906: int i; ! 907: ! 908: for (i=0 ; i<6 ; i++) ! 909: { ! 910: skymins[0][i] = skymins[1][i] = 9999; ! 911: skymaxs[0][i] = skymaxs[1][i] = -9999; ! 912: } ! 913: } ! 914: ! 915: ! 916: void MakeSkyVec (float s, float t, int axis) ! 917: { ! 918: vec3_t v, b; ! 919: int j, k; ! 920: ! 921: b[0] = s*2048; ! 922: b[1] = t*2048; ! 923: b[2] = 2048; ! 924: ! 925: for (j=0 ; j<3 ; j++) ! 926: { ! 927: k = st_to_vec[axis][j]; ! 928: if (k < 0) ! 929: v[j] = -b[-k - 1]; ! 930: else ! 931: v[j] = b[k - 1]; ! 932: v[j] += r_origin[j]; ! 933: } ! 934: ! 935: // avoid bilerp seam ! 936: s = (s+1)*0.5; ! 937: t = (t+1)*0.5; ! 938: ! 939: if (s < 1.0/512) ! 940: s = 1.0/512; ! 941: else if (s > 511.0/512) ! 942: s = 511.0/512; ! 943: if (t < 1.0/512) ! 944: t = 1.0/512; ! 945: else if (t > 511.0/512) ! 946: t = 511.0/512; ! 947: ! 948: t = 1.0 - t; ! 949: glTexCoord2f (s, t); ! 950: glVertex3fv (v); ! 951: } ! 952: ! 953: /* ! 954: ============== ! 955: R_DrawSkyBox ! 956: ============== ! 957: */ ! 958: int skytexorder[6] = {0,2,1,3,4,5}; ! 959: void R_DrawSkyBox (void) ! 960: { ! 961: int i, j, k; ! 962: vec3_t v; ! 963: float s, t; ! 964: ! 965: #if 0 ! 966: glEnable (GL_BLEND); ! 967: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); ! 968: glColor4f (1,1,1,0.5); ! 969: glDisable (GL_DEPTH_TEST); ! 970: #endif ! 971: for (i=0 ; i<6 ; i++) ! 972: { ! 973: if (skymins[0][i] >= skymaxs[0][i] ! 974: || skymins[1][i] >= skymaxs[1][i]) ! 975: continue; ! 976: ! 977: GL_Bind (SKY_TEX+skytexorder[i]); ! 978: #if 0 ! 979: skymins[0][i] = -1; ! 980: skymins[1][i] = -1; ! 981: skymaxs[0][i] = 1; ! 982: skymaxs[1][i] = 1; ! 983: #endif ! 984: glBegin (GL_QUADS); ! 985: MakeSkyVec (skymins[0][i], skymins[1][i], i); ! 986: MakeSkyVec (skymins[0][i], skymaxs[1][i], i); ! 987: MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); ! 988: MakeSkyVec (skymaxs[0][i], skymins[1][i], i); ! 989: glEnd (); ! 990: } ! 991: #if 0 ! 992: glDisable (GL_BLEND); ! 993: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); ! 994: glColor4f (1,1,1,0.5); ! 995: glEnable (GL_DEPTH_TEST); ! 996: #endif ! 997: } ! 998: ! 999: ! 1000: #endif ! 1001: ! 1002: //=============================================================== ! 1003: ! 1004: /* ! 1005: ============= ! 1006: R_InitSky ! 1007: ! 1008: A sky texture is 256*128, with the right side being a masked overlay ! 1009: ============== ! 1010: */ ! 1011: void R_InitSky (texture_t *mt) ! 1012: { ! 1013: int i, j, p; ! 1014: byte *src; ! 1015: unsigned trans[128*128]; ! 1016: unsigned transpix; ! 1017: int r, g, b; ! 1018: unsigned *rgba; ! 1019: extern int skytexturenum; ! 1020: ! 1021: src = (byte *)mt + mt->offsets[0]; ! 1022: ! 1023: // make an average value for the back to avoid ! 1024: // a fringe on the top level ! 1025: ! 1026: r = g = b = 0; ! 1027: for (i=0 ; i<128 ; i++) ! 1028: for (j=0 ; j<128 ; j++) ! 1029: { ! 1030: p = src[i*256 + j + 128]; ! 1031: rgba = &d_8to24table[p]; ! 1032: trans[(i*128) + j] = *rgba; ! 1033: r += ((byte *)rgba)[0]; ! 1034: g += ((byte *)rgba)[1]; ! 1035: b += ((byte *)rgba)[2]; ! 1036: } ! 1037: ! 1038: ((byte *)&transpix)[0] = r/(128*128); ! 1039: ((byte *)&transpix)[1] = g/(128*128); ! 1040: ((byte *)&transpix)[2] = b/(128*128); ! 1041: ((byte *)&transpix)[3] = 0; ! 1042: ! 1043: ! 1044: if (!solidskytexture) ! 1045: solidskytexture = texture_extension_number++; ! 1046: GL_Bind (solidskytexture ); ! 1047: glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 1048: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ! 1049: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ! 1050: ! 1051: ! 1052: for (i=0 ; i<128 ; i++) ! 1053: for (j=0 ; j<128 ; j++) ! 1054: { ! 1055: p = src[i*256 + j]; ! 1056: if (p == 0) ! 1057: trans[(i*128) + j] = transpix; ! 1058: else ! 1059: trans[(i*128) + j] = d_8to24table[p]; ! 1060: } ! 1061: ! 1062: if (!alphaskytexture) ! 1063: alphaskytexture = texture_extension_number++; ! 1064: GL_Bind(alphaskytexture); ! 1065: glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 1066: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ! 1067: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ! 1068: } ! 1069:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.