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