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