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// r_surf.c: surface-related refresh code 21 22#include "quakedef.h" 23 24int skytexturenum; 25 26#ifndef GL_RGBA4 27#define GL_RGBA4 0 28#endif 29 30 31int lightmap_bytes; // 1, 2, or 4 32 33int lightmap_textures; 34 35unsigned blocklights[18*18]; 36 37#define BLOCK_WIDTH 128 38#define BLOCK_HEIGHT 128 39 40#define MAX_LIGHTMAPS 64 41int active_lightmaps; 42 43typedef struct glRect_s { 44 unsigned char l,t,w,h; 45} glRect_t; 46 47glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; 48qboolean lightmap_modified[MAX_LIGHTMAPS]; 49glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; 50 51int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; 52 53// the lightmap texture data needs to be kept in 54// main memory so texsubimage can update properly 55byte lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT]; 56 57// For gl_texsort 0 58msurface_t *skychain = NULL; 59msurface_t *waterchain = NULL; 60 61void R_RenderDynamicLightmaps (msurface_t *fa); 62 63/* 64=============== 65R_AddDynamicLights 66=============== 67*/ 68void R_AddDynamicLights (msurface_t *surf) 69{ 70 int lnum; 71 int sd, td; 72 float dist, rad, minlight; 73 vec3_t impact, local; 74 int s, t; 75 int i; 76 int smax, tmax; 77 mtexinfo_t *tex; 78 79 smax = (surf->extents[0]>>4)+1; 80 tmax = (surf->extents[1]>>4)+1; 81 tex = surf->texinfo; 82 83 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) 84 { 85 if ( !(surf->dlightbits & (1<<lnum) ) ) 86 continue; // not lit by this light 87 88 rad = cl_dlights[lnum].radius; 89 dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) - 90 surf->plane->dist; 91 rad -= fabs(dist); 92 minlight = cl_dlights[lnum].minlight; 93 if (rad < minlight) 94 continue; 95 minlight = rad - minlight; 96 97 for (i=0 ; i<3 ; i++) 98 { 99 impact[i] = cl_dlights[lnum].origin[i] - 100 surf->plane->normal[i]*dist; 101 } 102 103 local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; 104 local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; 105 106 local[0] -= surf->texturemins[0]; 107 local[1] -= surf->texturemins[1]; 108 109 for (t = 0 ; t<tmax ; t++) 110 { 111 td = local[1] - t*16; 112 if (td < 0) 113 td = -td; 114 for (s=0 ; s<smax ; s++) 115 { 116 sd = local[0] - s*16; 117 if (sd < 0) 118 sd = -sd; 119 if (sd > td) 120 dist = sd + (td>>1); 121 else 122 dist = td + (sd>>1); 123 if (dist < minlight) 124 blocklights[t*smax + s] += (rad - dist)*256; 125 } 126 } 127 } 128} 129 130 131/* 132=============== 133R_BuildLightMap 134 135Combine and scale multiple lightmaps into the 8.8 format in blocklights 136=============== 137*/ 138void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) 139{ 140 int smax, tmax; 141 int t; 142 int i, j, size; 143 byte *lightmap; 144 unsigned scale; 145 int maps; 146 unsigned *bl; 147 148 surf->cached_dlight = (surf->dlightframe == r_framecount); 149 150 smax = (surf->extents[0]>>4)+1; 151 tmax = (surf->extents[1]>>4)+1; 152 size = smax*tmax; 153 lightmap = surf->samples; 154 155// set to full bright if no light data 156 if (/* r_fullbright.value || */ !cl.worldmodel->lightdata) 157 { 158 for (i=0 ; i<size ; i++) 159 blocklights[i] = 255*256; 160 goto store; 161 } 162 163// clear to no light 164 for (i=0 ; i<size ; i++) 165 blocklights[i] = 0; 166 167// add all the lightmaps 168 if (lightmap) 169 for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; 170 maps++) 171 { 172 scale = d_lightstylevalue[surf->styles[maps]]; 173 surf->cached_light[maps] = scale; // 8.8 fraction 174 for (i=0 ; i<size ; i++) 175 blocklights[i] += lightmap[i] * scale; 176 lightmap += size; // skip to next lightmap 177 } 178 179// add all the dynamic lights 180 if (surf->dlightframe == r_framecount) 181 R_AddDynamicLights (surf); 182 183// bound, invert, and shift 184store: 185 switch (gl_lightmap_format) 186 { 187 case GL_RGBA: 188 stride -= (smax<<2); 189 bl = blocklights; 190 for (i=0 ; i<tmax ; i++, dest += stride) 191 { 192 for (j=0 ; j<smax ; j++) 193 { 194 t = *bl++; 195 t >>= 7; 196 if (t > 255) 197 t = 255; 198 dest[3] = 255-t; 199 dest += 4; 200 } 201 } 202 break; 203 case GL_ALPHA: 204 case GL_LUMINANCE: 205 case GL_INTENSITY: 206 bl = blocklights; 207 for (i=0 ; i<tmax ; i++, dest += stride) 208 { 209 for (j=0 ; j<smax ; j++) 210 { 211 t = *bl++; 212 t >>= 7; 213 if (t > 255) 214 t = 255; 215 dest[j] = 255-t; 216 } 217 } 218 break; 219 default: 220 Sys_Error ("Bad lightmap format"); 221 } 222} 223 224 225/* 226=============== 227R_TextureAnimation 228 229Returns the proper texture for a given time and base texture 230=============== 231*/ 232texture_t *R_TextureAnimation (texture_t *base) 233{ 234 int reletive; 235 int count; 236 237 if (currententity->frame) 238 { 239 if (base->alternate_anims) 240 base = base->alternate_anims; 241 } 242 243 if (!base->anim_total) 244 return base; 245 246 reletive = (int)(cl.time*10) % base->anim_total; 247 248 count = 0; 249 while (base->anim_min > reletive || base->anim_max <= reletive) 250 { 251 base = base->anim_next; 252 if (!base) 253 Sys_Error ("R_TextureAnimation: broken cycle"); 254 if (++count > 100) 255 Sys_Error ("R_TextureAnimation: infinite cycle"); 256 } 257 258 return base; 259} 260 261 262/* 263============================================================= 264 265 BRUSH MODELS 266 267============================================================= 268*/ 269 270 271extern int solidskytexture; 272extern int alphaskytexture; 273extern float speedscale; // for top sky and bottom sky 274 275void DrawGLWaterPoly (glpoly_t *p); 276void DrawGLWaterPolyLightmap (glpoly_t *p); 277 278#ifdef _WIN32 279lpMTexFUNC qglMTexCoord2fSGIS = NULL; 280lpSelTexFUNC qglSelectTextureSGIS = NULL; 281#endif 282 283qboolean mtexenabled = false; 284 285void GL_SelectTexture (GLenum target); 286 287void GL_DisableMultitexture(void) 288{ 289 if (mtexenabled) { 290 glDisable(GL_TEXTURE_2D); 291 GL_SelectTexture(TEXTURE0_SGIS); 292 mtexenabled = false; 293 } 294} 295 296void GL_EnableMultitexture(void) 297{ 298 if (gl_mtexable) { 299 GL_SelectTexture(TEXTURE1_SGIS); 300 glEnable(GL_TEXTURE_2D); 301 mtexenabled = true; 302 } 303} 304 305#ifndef _WIN32 306/* 307================ 308R_DrawSequentialPoly 309 310Systems that have fast state and texture changes can 311just do everything as it passes with no need to sort 312================ 313*/ 314void R_DrawSequentialPoly (msurface_t *s) 315{ 316 glpoly_t *p; 317 float *v; 318 int i; 319 texture_t *t; 320 321 // 322 // normal lightmaped poly 323 // 324// if ((!(s->flags & (SURF_DRAWSKY|SURF_DRAWTURB))) 325// && ((r_viewleaf->contents!=CONTENTS_EMPTY && (s->flags & SURF_UNDERWATER)) || 326// (r_viewleaf->contents==CONTENTS_EMPTY && !(s->flags & SURF_UNDERWATER)))) 327#if 0 328 if (0) 329 { 330 p = s->polys; 331 332 t = R_TextureAnimation (s->texinfo->texture); 333 GL_Bind (t->gl_texturenum); 334 glBegin (GL_POLYGON); 335 v = p->verts[0]; 336 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 337 { 338 glTexCoord2f (v[3], v[4]); 339 glVertex3fv (v); 340 } 341 glEnd (); 342 343 GL_Bind (lightmap_textures + s->lightmaptexturenum); 344 glEnable (GL_BLEND); 345 glBegin (GL_POLYGON); 346 v = p->verts[0]; 347 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 348 { 349 glTexCoord2f (v[5], v[6]); 350 glVertex3fv (v); 351 } 352 glEnd (); 353 354 glDisable (GL_BLEND); 355 356 return; 357 } 358#endif 359 360 // 361 // subdivided water surface warp 362 // 363 if (s->flags & SURF_DRAWTURB) 364 { 365 GL_Bind (s->texinfo->texture->gl_texturenum); 366 EmitWaterPolys (s); 367 return; 368 } 369 370 // 371 // subdivided sky warp 372 // 373 if (s->flags & SURF_DRAWSKY) 374 { 375 GL_Bind (solidskytexture); 376 speedscale = realtime*8; 377 speedscale -= (int)speedscale; 378 379 EmitSkyPolys (s); 380 381 glEnable (GL_BLEND); 382 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 383 GL_Bind (alphaskytexture); 384 speedscale = realtime*16; 385 speedscale -= (int)speedscale; 386 EmitSkyPolys (s); 387 if (gl_lightmap_format == GL_LUMINANCE) 388 glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR); 389 390 glDisable (GL_BLEND); 391 } 392 393 // 394 // underwater warped with lightmap 395 // 396 p = s->polys; 397 398 t = R_TextureAnimation (s->texinfo->texture); 399 GL_Bind (t->gl_texturenum); 400 DrawGLWaterPoly (p); 401 402 GL_Bind (lightmap_textures + s->lightmaptexturenum); 403 glEnable (GL_BLEND); 404 DrawGLWaterPolyLightmap (p); 405 glDisable (GL_BLEND); 406} 407#else 408/* 409================ 410R_DrawSequentialPoly 411 412Systems that have fast state and texture changes can 413just do everything as it passes with no need to sort 414================ 415*/ 416void R_DrawSequentialPoly (msurface_t *s) 417{ 418 glpoly_t *p; 419 float *v; 420 int i; 421 texture_t *t; 422 vec3_t nv, dir; 423 float ss, ss2, length; 424 float s1, t1; 425 glRect_t *theRect; 426 427 // 428 // normal lightmaped poly 429 // 430 431 if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) ) 432 { 433 R_RenderDynamicLightmaps (s); 434 if (gl_mtexable) { 435 p = s->polys; 436 437 t = R_TextureAnimation (s->texinfo->texture); 438 // Binds world to texture env 0 439 GL_SelectTexture(TEXTURE0_SGIS); 440 GL_Bind (t->gl_texturenum); 441 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 442 // Binds lightmap to texenv 1 443 GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1) 444 GL_Bind (lightmap_textures + s->lightmaptexturenum); 445 i = s->lightmaptexturenum; 446 if (lightmap_modified[i]) 447 { 448 lightmap_modified[i] = false; 449 theRect = &lightmap_rectchange[i]; 450 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 451 BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, 452 lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); 453 theRect->l = BLOCK_WIDTH; 454 theRect->t = BLOCK_HEIGHT; 455 theRect->h = 0; 456 theRect->w = 0; 457 } 458 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); 459 glBegin(GL_POLYGON); 460 v = p->verts[0]; 461 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 462 { 463 qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]); 464 qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]); 465 glVertex3fv (v); 466 } 467 glEnd (); 468 return; 469 } else { 470 p = s->polys; 471 472 t = R_TextureAnimation (s->texinfo->texture); 473 GL_Bind (t->gl_texturenum); 474 glBegin (GL_POLYGON); 475 v = p->verts[0]; 476 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 477 { 478 glTexCoord2f (v[3], v[4]); 479 glVertex3fv (v); 480 } 481 glEnd (); 482 483 GL_Bind (lightmap_textures + s->lightmaptexturenum); 484 glEnable (GL_BLEND); 485 glBegin (GL_POLYGON); 486 v = p->verts[0]; 487 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 488 { 489 glTexCoord2f (v[5], v[6]); 490 glVertex3fv (v); 491 } 492 glEnd (); 493 494 glDisable (GL_BLEND); 495 } 496 497 return; 498 } 499 500 // 501 // subdivided water surface warp 502 // 503 504 if (s->flags & SURF_DRAWTURB) 505 { 506 GL_DisableMultitexture(); 507 GL_Bind (s->texinfo->texture->gl_texturenum); 508 EmitWaterPolys (s); 509 return; 510 } 511 512 // 513 // subdivided sky warp 514 // 515 if (s->flags & SURF_DRAWSKY) 516 { 517 GL_DisableMultitexture(); 518 GL_Bind (solidskytexture); 519 speedscale = realtime*8; 520 speedscale -= (int)speedscale & ~127; 521 522 EmitSkyPolys (s); 523 524 glEnable (GL_BLEND); 525 GL_Bind (alphaskytexture); 526 speedscale = realtime*16; 527 speedscale -= (int)speedscale & ~127; 528 EmitSkyPolys (s); 529 530 glDisable (GL_BLEND); 531 return; 532 } 533 534 // 535 // underwater warped with lightmap 536 // 537 R_RenderDynamicLightmaps (s); 538 if (gl_mtexable) { 539 p = s->polys; 540 541 t = R_TextureAnimation (s->texinfo->texture); 542 GL_SelectTexture(TEXTURE0_SGIS); 543 GL_Bind (t->gl_texturenum); 544 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 545 GL_EnableMultitexture(); 546 GL_Bind (lightmap_textures + s->lightmaptexturenum); 547 i = s->lightmaptexturenum; 548 if (lightmap_modified[i]) 549 { 550 lightmap_modified[i] = false; 551 theRect = &lightmap_rectchange[i]; 552 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 553 BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, 554 lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); 555 theRect->l = BLOCK_WIDTH; 556 theRect->t = BLOCK_HEIGHT; 557 theRect->h = 0; 558 theRect->w = 0; 559 } 560 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); 561 glBegin (GL_TRIANGLE_FAN); 562 v = p->verts[0]; 563 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 564 { 565 qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]); 566 qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]); 567 568 nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); 569 nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); 570 nv[2] = v[2]; 571 572 glVertex3fv (nv); 573 } 574 glEnd (); 575 576 } else { 577 p = s->polys; 578 579 t = R_TextureAnimation (s->texinfo->texture); 580 GL_Bind (t->gl_texturenum); 581 DrawGLWaterPoly (p); 582 583 GL_Bind (lightmap_textures + s->lightmaptexturenum); 584 glEnable (GL_BLEND); 585 DrawGLWaterPolyLightmap (p); 586 glDisable (GL_BLEND); 587 } 588} 589#endif 590 591 592/* 593================ 594DrawGLWaterPoly 595 596Warp the vertex coordinates 597================ 598*/ 599void DrawGLWaterPoly (glpoly_t *p) 600{ 601 int i; 602 float *v; 603 vec3_t nv; 604 605 GL_DisableMultitexture(); 606 607#ifdef USE_OPENGLES 608 // !!! Implement this. 609#else 610 glBegin (GL_TRIANGLE_FAN); 611 v = p->verts[0]; 612 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 613 { 614 glTexCoord2f (v[3], v[4]); 615 616 nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); 617 nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); 618 nv[2] = v[2]; 619 620 glVertex3fv (nv); 621 } 622 glEnd (); 623#endif 624} 625 626void DrawGLWaterPolyLightmap (glpoly_t *p) 627{ 628 int i; 629 float *v; 630 vec3_t nv; 631 632 GL_DisableMultitexture(); 633 634#ifdef USE_OPENGLES 635 // !!! Implement this. 636#else 637 glBegin (GL_TRIANGLE_FAN); 638 v = p->verts[0]; 639 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 640 { 641 glTexCoord2f (v[5], v[6]); 642 643 nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); 644 nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); 645 nv[2] = v[2]; 646 647 glVertex3fv (nv); 648 } 649 glEnd (); 650#endif 651} 652 653/* 654================ 655DrawGLPoly 656================ 657*/ 658void DrawGLPoly (glpoly_t *p) 659{ 660 int i; 661 float *v; 662 663#ifdef USE_OPENGLES 664 // !!! Implement this. 665#else 666 glBegin (GL_POLYGON); 667 v = p->verts[0]; 668 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE) 669 { 670 glTexCoord2f (v[3], v[4]); 671 glVertex3fv (v); 672 } 673 glEnd (); 674#endif 675} 676 677 678/* 679================ 680R_BlendLightmaps 681================ 682*/ 683void R_BlendLightmaps (void) 684{ 685 int i, j; 686 glpoly_t *p; 687 float *v; 688 glRect_t *theRect; 689 690#if 0 691 if (r_fullbright.value) 692 return; 693#endif 694 if (!gl_texsort.value) 695 return; 696 697 glDepthMask (0); // don't bother writing Z 698 699 if (gl_lightmap_format == GL_LUMINANCE) 700 glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR); 701 else if (gl_lightmap_format == GL_INTENSITY) 702 { 703 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 704 glColor4f (0,0,0,1); 705 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 706 } 707 708 if (!r_lightmap.value) 709 { 710 glEnable (GL_BLEND); 711 } 712 713 for (i=0 ; i<MAX_LIGHTMAPS ; i++) 714 { 715 p = lightmap_polys[i]; 716 if (!p) 717 continue; 718 GL_Bind(lightmap_textures+i); 719 if (lightmap_modified[i]) 720 { 721 lightmap_modified[i] = false; 722 theRect = &lightmap_rectchange[i]; 723// theRect->l = 0; 724// theRect->t = 0; 725// theRect->w = BLOCK_WIDTH; 726// theRect->h = BLOCK_HEIGHT; 727// glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes 728// , BLOCK_WIDTH, BLOCK_HEIGHT, 0, 729// gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes); 730// glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes 731// , BLOCK_WIDTH, theRect->h, 0, 732// gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes); 733 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, 734 BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, 735 lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); 736 theRect->l = BLOCK_WIDTH; 737 theRect->t = BLOCK_HEIGHT; 738 theRect->h = 0; 739 theRect->w = 0; 740 } 741 for ( ; p ; p=p->chain) 742 { 743// if (p->flags & SURF_UNDERWATER) 744// DrawGLWaterPolyLightmap (p); 745 if (((r_viewleaf->contents==CONTENTS_EMPTY && (p->flags & SURF_UNDERWATER)) || 746 (r_viewleaf->contents!=CONTENTS_EMPTY && !(p->flags & SURF_UNDERWATER))) 747 && !(p->flags & SURF_DONTWARP)) 748 DrawGLWaterPolyLightmap (p); 749 else 750 { 751#ifdef USE_OPENGLES 752 // !!! Implement this. 753#else 754 glBegin (GL_POLYGON); 755 v = p->verts[0]; 756 for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE) 757 { 758 glTexCoord2f (v[5], v[6]); 759 glVertex3fv (v); 760 } 761 glEnd (); 762#endif 763 } 764 } 765 } 766 767 glDisable (GL_BLEND); 768 if (gl_lightmap_format == GL_LUMINANCE) 769 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 770 else if (gl_lightmap_format == GL_INTENSITY) 771 { 772 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 773 glColor4f (1,1,1,1); 774 } 775 776 glDepthMask (1); // back to normal Z buffering 777} 778 779/* 780================ 781R_RenderBrushPoly 782================ 783*/ 784void R_RenderBrushPoly (msurface_t *fa) 785{ 786 texture_t *t; 787 byte *base; 788 int maps; 789 glRect_t *theRect; 790 int smax, tmax; 791 792 c_brush_polys++; 793 794 if (fa->flags & SURF_DRAWSKY) 795 { // warp texture, no lightmaps 796 EmitBothSkyLayers (fa); 797 return; 798 } 799 800 t = R_TextureAnimation (fa->texinfo->texture); 801 GL_Bind (t->gl_texturenum); 802 803 if (fa->flags & SURF_DRAWTURB) 804 { // warp texture, no lightmaps 805 EmitWaterPolys (fa); 806 return; 807 } 808 809 if (((r_viewleaf->contents==CONTENTS_EMPTY && (fa->flags & SURF_UNDERWATER)) || 810 (r_viewleaf->contents!=CONTENTS_EMPTY && !(fa->flags & SURF_UNDERWATER))) 811 && !(fa->flags & SURF_DONTWARP)) 812 DrawGLWaterPoly (fa->polys); 813 else 814 DrawGLPoly (fa->polys); 815 816 // add the poly to the proper lightmap chain 817 818 fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; 819 lightmap_polys[fa->lightmaptexturenum] = fa->polys; 820 821 // check for lightmap modification 822 for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; 823 maps++) 824 if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) 825 goto dynamic; 826 827 if (fa->dlightframe == r_framecount // dynamic this frame 828 || fa->cached_dlight) // dynamic previously 829 { 830dynamic: 831 if (r_dynamic.value) 832 { 833 lightmap_modified[fa->lightmaptexturenum] = true; 834 theRect = &lightmap_rectchange[fa->lightmaptexturenum]; 835 if (fa->light_t < theRect->t) { 836 if (theRect->h) 837 theRect->h += theRect->t - fa->light_t; 838 theRect->t = fa->light_t; 839 } 840 if (fa->light_s < theRect->l) { 841 if (theRect->w) 842 theRect->w += theRect->l - fa->light_s; 843 theRect->l = fa->light_s; 844 } 845 smax = (fa->extents[0]>>4)+1; 846 tmax = (fa->extents[1]>>4)+1; 847 if ((theRect->w + theRect->l) < (fa->light_s + smax)) 848 theRect->w = (fa->light_s-theRect->l)+smax; 849 if ((theRect->h + theRect->t) < (fa->light_t + tmax)) 850 theRect->h = (fa->light_t-theRect->t)+tmax; 851 base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; 852 base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; 853 R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); 854 } 855 } 856} 857 858/* 859================ 860R_RenderDynamicLightmaps 861Multitexture 862================ 863*/ 864void R_RenderDynamicLightmaps (msurface_t *fa) 865{ 866 byte *base; 867 int maps; 868 glRect_t *theRect; 869 int smax, tmax; 870 871 c_brush_polys++; 872 873 if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) ) 874 return; 875 876 fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; 877 lightmap_polys[fa->lightmaptexturenum] = fa->polys; 878 879 // check for lightmap modification 880 for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; 881 maps++) 882 if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) 883 goto dynamic; 884 885 if (fa->dlightframe == r_framecount // dynamic this frame 886 || fa->cached_dlight) // dynamic previously 887 { 888dynamic: 889 if (r_dynamic.value) 890 { 891 lightmap_modified[fa->lightmaptexturenum] = true; 892 theRect = &lightmap_rectchange[fa->lightmaptexturenum]; 893 if (fa->light_t < theRect->t) { 894 if (theRect->h) 895 theRect->h += theRect->t - fa->light_t; 896 theRect->t = fa->light_t; 897 } 898 if (fa->light_s < theRect->l) { 899 if (theRect->w) 900 theRect->w += theRect->l - fa->light_s; 901 theRect->l = fa->light_s; 902 } 903 smax = (fa->extents[0]>>4)+1; 904 tmax = (fa->extents[1]>>4)+1; 905 if ((theRect->w + theRect->l) < (fa->light_s + smax)) 906 theRect->w = (fa->light_s-theRect->l)+smax; 907 if ((theRect->h + theRect->t) < (fa->light_t + tmax)) 908 theRect->h = (fa->light_t-theRect->t)+tmax; 909 base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; 910 base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; 911 R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); 912 } 913 } 914} 915 916/* 917================ 918R_MirrorChain 919================ 920*/ 921void R_MirrorChain (msurface_t *s) 922{ 923 if (mirror) 924 return; 925 mirror = true; 926 mirror_plane = s->plane; 927} 928 929 930#if 0 931/* 932================ 933R_DrawWaterSurfaces 934================ 935*/ 936void R_DrawWaterSurfaces (void) 937{ 938 int i; 939 msurface_t *s; 940 texture_t *t; 941 942 if (r_wateralpha.value == 1.0) 943 return; 944 945 // 946 // go back to the world matrix 947 // 948 glLoadMatrixf (r_world_matrix); 949 950 glEnable (GL_BLEND); 951 glColor4f (1,1,1,r_wateralpha.value); 952 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 953 954 for (i=0 ; i<cl.worldmodel->numtextures ; i++) 955 { 956 t = cl.worldmodel->textures[i]; 957 if (!t) 958 continue; 959 s = t->texturechain; 960 if (!s) 961 continue; 962 if ( !(s->flags & SURF_DRAWTURB) ) 963 continue; 964 965 // set modulate mode explicitly 966 GL_Bind (t->gl_texturenum); 967 968 for ( ; s ; s=s->texturechain) 969 R_RenderBrushPoly (s); 970 971 t->texturechain = NULL; 972 } 973 974 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 975 976 glColor4f (1,1,1,1); 977 glDisable (GL_BLEND); 978} 979#else 980/* 981================ 982R_DrawWaterSurfaces 983================ 984*/ 985void R_DrawWaterSurfaces (void) 986{ 987 int i; 988 msurface_t *s; 989 texture_t *t; 990 991 if (r_wateralpha.value == 1.0 && gl_texsort.value) 992 return; 993 994 // 995 // go back to the world matrix 996 // 997 998 glLoadMatrixf (r_world_matrix); 999 1000 if (r_wateralpha.value < 1.0) { 1001 glEnable (GL_BLEND); 1002 glColor4f (1,1,1,r_wateralpha.value); 1003 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 1004 } 1005 1006 if (!gl_texsort.value) { 1007 if (!waterchain) 1008 return; 1009 1010 for ( s = waterchain ; s ; s=s->texturechain) { 1011 GL_Bind (s->texinfo->texture->gl_texturenum); 1012 EmitWaterPolys (s); 1013 } 1014 1015 waterchain = NULL; 1016 } else { 1017 1018 for (i=0 ; i<cl.worldmodel->numtextures ; i++) 1019 { 1020 t = cl.worldmodel->textures[i]; 1021 if (!t) 1022 continue; 1023 s = t->texturechain; 1024 if (!s) 1025 continue; 1026 if ( !(s->flags & SURF_DRAWTURB ) ) 1027 continue; 1028 1029 // set modulate mode explicitly 1030 1031 GL_Bind (t->gl_texturenum); 1032 1033 for ( ; s ; s=s->texturechain) 1034 EmitWaterPolys (s); 1035 1036 t->texturechain = NULL; 1037 } 1038 1039 } 1040 1041 if (r_wateralpha.value < 1.0) { 1042 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1043 1044 glColor4f (1,1,1,1); 1045 glDisable (GL_BLEND); 1046 } 1047 1048} 1049 1050#endif 1051 1052/* 1053================ 1054DrawTextureChains 1055================ 1056*/ 1057void DrawTextureChains (void) 1058{ 1059 int i; 1060 msurface_t *s; 1061 texture_t *t; 1062 1063 if (!gl_texsort.value) { 1064 GL_DisableMultitexture(); 1065 1066 if (skychain) { 1067 R_DrawSkyChain(skychain); 1068 skychain = NULL; 1069 } 1070 1071 return; 1072 } 1073 1074 for (i=0 ; i<cl.worldmodel->numtextures ; i++) 1075 { 1076 t = cl.worldmodel->textures[i]; 1077 if (!t) 1078 continue; 1079 s = t->texturechain; 1080 if (!s) 1081 continue; 1082 if (i == skytexturenum) 1083 R_DrawSkyChain (s); 1084 else if (i == mirrortexturenum && r_mirroralpha.value != 1.0) 1085 { 1086 R_MirrorChain (s); 1087 continue; 1088 } 1089 else 1090 { 1091 if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0) 1092 continue; // draw translucent water later 1093 for ( ; s ; s=s->texturechain) 1094 R_RenderBrushPoly (s); 1095 } 1096 1097 t->texturechain = NULL; 1098 } 1099} 1100 1101/* 1102================= 1103R_DrawBrushModel 1104================= 1105*/ 1106void R_DrawBrushModel (entity_t *e) 1107{ 1108 int i; 1109 int k; 1110 vec3_t mins, maxs; 1111 msurface_t *psurf; 1112 float dot; 1113 mplane_t *pplane; 1114 model_t *clmodel; 1115 qboolean rotated; 1116 1117 currententity = e; 1118 currenttexture = -1; 1119 1120 clmodel = e->model; 1121 1122 if (e->angles[0] || e->angles[1] || e->angles[2]) 1123 { 1124 rotated = true; 1125 for (i=0 ; i<3 ; i++) 1126 { 1127 mins[i] = e->origin[i] - clmodel->radius; 1128 maxs[i] = e->origin[i] + clmodel->radius; 1129 } 1130 } 1131 else 1132 { 1133 rotated = false; 1134 VectorAdd (e->origin, clmodel->mins, mins); 1135 VectorAdd (e->origin, clmodel->maxs, maxs); 1136 } 1137 1138 if (R_CullBox (mins, maxs)) 1139 return; 1140 1141 glColor3f (1,1,1); 1142 memset (lightmap_polys, 0, sizeof(lightmap_polys)); 1143 1144 VectorSubtract (r_refdef.vieworg, e->origin, modelorg); 1145 if (rotated) 1146 { 1147 vec3_t temp; 1148 vec3_t forward, right, up; 1149 1150 VectorCopy (modelorg, temp); 1151 AngleVectors (e->angles, forward, right, up); 1152 modelorg[0] = DotProduct (temp, forward); 1153 modelorg[1] = -DotProduct (temp, right); 1154 modelorg[2] = DotProduct (temp, up); 1155 } 1156 1157 psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; 1158 1159// calculate dynamic lighting for bmodel if it's not an 1160// instanced model 1161 if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value) 1162 { 1163 for (k=0 ; k<MAX_DLIGHTS ; k++) 1164 { 1165 if ((cl_dlights[k].die < cl.time) || 1166 (!cl_dlights[k].radius)) 1167 continue; 1168 1169 R_MarkLights (&cl_dlights[k], 1<<k, 1170 clmodel->nodes + clmodel->hulls[0].firstclipnode); 1171 } 1172 } 1173 1174 glPushMatrix (); 1175e->angles[0] = -e->angles[0]; // stupid quake bug 1176 R_RotateForEntity (e); 1177e->angles[0] = -e->angles[0]; // stupid quake bug 1178 1179 // 1180 // draw texture 1181 // 1182 for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++) 1183 { 1184 // find which side of the node we are on 1185 pplane = psurf->plane; 1186 1187 dot = DotProduct (modelorg, pplane->normal) - pplane->dist; 1188 1189 // draw the polygon 1190 if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || 1191 (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) 1192 { 1193 if (gl_texsort.value) 1194 R_RenderBrushPoly (psurf); 1195 else 1196 R_DrawSequentialPoly (psurf); 1197 } 1198 } 1199 1200 R_BlendLightmaps (); 1201 1202 glPopMatrix (); 1203} 1204 1205/* 1206============================================================= 1207 1208 WORLD MODEL 1209 1210============================================================= 1211*/ 1212 1213/* 1214================ 1215R_RecursiveWorldNode 1216================ 1217*/ 1218void R_RecursiveWorldNode (mnode_t *node) 1219{ 1220 int c, side; 1221 mplane_t *plane; 1222 msurface_t *surf, **mark; 1223 mleaf_t *pleaf; 1224 double dot; 1225 1226 if (node->contents == CONTENTS_SOLID) 1227 return; // solid 1228 1229 if (node->visframe != r_visframecount) 1230 return; 1231 if (R_CullBox (node->minmaxs, node->minmaxs+3)) 1232 return; 1233 1234// if a leaf node, draw stuff 1235 if (node->contents < 0) 1236 { 1237 pleaf = (mleaf_t *)node; 1238 1239 mark = pleaf->firstmarksurface; 1240 c = pleaf->nummarksurfaces; 1241 1242 if (c) 1243 { 1244 do 1245 { 1246 (*mark)->visframe = r_framecount; 1247 mark++; 1248 } while (--c); 1249 } 1250 1251 // deal with model fragments in this leaf 1252 if (pleaf->efrags) 1253 R_StoreEfrags (&pleaf->efrags); 1254 1255 return; 1256 } 1257 1258// node is just a decision point, so go down the apropriate sides 1259 1260// find which side of the node we are on 1261 plane = node->plane; 1262 1263 switch (plane->type) 1264 { 1265 case PLANE_X: 1266 dot = modelorg[0] - plane->dist; 1267 break; 1268 case PLANE_Y: 1269 dot = modelorg[1] - plane->dist; 1270 break; 1271 case PLANE_Z: 1272 dot = modelorg[2] - plane->dist; 1273 break; 1274 default: 1275 dot = DotProduct (modelorg, plane->normal) - plane->dist; 1276 break; 1277 } 1278 1279 if (dot >= 0) 1280 side = 0; 1281 else 1282 side = 1; 1283 1284// recurse down the children, front side first 1285 R_RecursiveWorldNode (node->children[side]); 1286 1287// draw stuff 1288 c = node->numsurfaces; 1289 1290 if (c) 1291 { 1292 surf = cl.worldmodel->surfaces + node->firstsurface; 1293 1294 if (dot < 0 -BACKFACE_EPSILON) 1295 side = SURF_PLANEBACK; 1296 else if (dot > BACKFACE_EPSILON) 1297 side = 0; 1298 { 1299 for ( ; c ; c--, surf++) 1300 { 1301 if (surf->visframe != r_framecount) 1302 continue; 1303 1304 // don't backface underwater surfaces, because they warp 1305// if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) 1306// continue; // wrong side 1307 if ( !(((r_viewleaf->contents==CONTENTS_EMPTY && (surf->flags & SURF_UNDERWATER)) || 1308 (r_viewleaf->contents!=CONTENTS_EMPTY && !(surf->flags & SURF_UNDERWATER))) 1309 && !(surf->flags & SURF_DONTWARP)) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) 1310 continue; // wrong side 1311 1312 // if sorting by texture, just store it out 1313 if (gl_texsort.value) 1314 { 1315 if (!mirror 1316 || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) 1317 { 1318 surf->texturechain = surf->texinfo->texture->texturechain; 1319 surf->texinfo->texture->texturechain = surf; 1320 } 1321 } else if (surf->flags & SURF_DRAWSKY) { 1322 surf->texturechain = skychain; 1323 skychain = surf; 1324 } else if (surf->flags & SURF_DRAWTURB) { 1325 surf->texturechain = waterchain; 1326 waterchain = surf; 1327 } else 1328 R_DrawSequentialPoly (surf); 1329 1330 } 1331 } 1332 1333 } 1334 1335// recurse down the back side 1336 R_RecursiveWorldNode (node->children[!side]); 1337} 1338 1339 1340 1341/* 1342============= 1343R_DrawWorld 1344============= 1345*/ 1346void R_DrawWorld (void) 1347{ 1348 entity_t ent; 1349 1350 memset (&ent, 0, sizeof(ent)); 1351 ent.model = cl.worldmodel; 1352 1353 VectorCopy (r_refdef.vieworg, modelorg); 1354 1355 currententity = &ent; 1356 currenttexture = -1; 1357 1358 glColor3f (1,1,1); 1359 memset (lightmap_polys, 0, sizeof(lightmap_polys)); 1360#ifdef QUAKE2 1361 R_ClearSkyBox (); 1362#endif 1363 1364 R_RecursiveWorldNode (cl.worldmodel->nodes); 1365 1366 DrawTextureChains (); 1367 1368 R_BlendLightmaps (); 1369 1370#ifdef QUAKE2 1371 R_DrawSkyBox (); 1372#endif 1373} 1374 1375 1376/* 1377=============== 1378R_MarkLeaves 1379=============== 1380*/ 1381void R_MarkLeaves (void) 1382{ 1383 byte *vis; 1384 mnode_t *node; 1385 int i; 1386 byte solid[4096]; 1387 1388 if (r_oldviewleaf == r_viewleaf && !r_novis.value) 1389 return; 1390 1391 if (mirror) 1392 return; 1393 1394 r_visframecount++; 1395 r_oldviewleaf = r_viewleaf; 1396 1397 if (r_novis.value) 1398 { 1399 vis = solid; 1400 memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3); 1401 } 1402 else 1403 vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); 1404 1405 for (i=0 ; i<cl.worldmodel->numleafs ; i++) 1406 { 1407 if (vis[i>>3] & (1<<(i&7))) 1408 { 1409 node = (mnode_t *)&cl.worldmodel->leafs[i+1]; 1410 do 1411 { 1412 if (node->visframe == r_visframecount) 1413 break; 1414 node->visframe = r_visframecount; 1415 node = node->parent; 1416 } while (node); 1417 } 1418 } 1419} 1420 1421 1422 1423/* 1424============================================================================= 1425 1426 LIGHTMAP ALLOCATION 1427 1428============================================================================= 1429*/ 1430 1431// returns a texture number and the position inside it 1432int AllocBlock (int w, int h, int *x, int *y) 1433{ 1434 int i, j; 1435 int best, best2; 1436 int texnum; 1437 1438 for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++) 1439 { 1440 best = BLOCK_HEIGHT; 1441 1442 for (i=0 ; i<BLOCK_WIDTH-w ; i++) 1443 { 1444 best2 = 0; 1445 1446 for (j=0 ; j<w ; j++) 1447 { 1448 if (allocated[texnum][i+j] >= best) 1449 break; 1450 if (allocated[texnum][i+j] > best2) 1451 best2 = allocated[texnum][i+j]; 1452 } 1453 if (j == w) 1454 { // this is a valid spot 1455 *x = i; 1456 *y = best = best2; 1457 } 1458 } 1459 1460 if (best + h > BLOCK_HEIGHT) 1461 continue; 1462 1463 for (i=0 ; i<w ; i++) 1464 allocated[texnum][*x + i] = best + h; 1465 1466 return texnum; 1467 } 1468 1469 Sys_Error ("AllocBlock: full"); 1470 return 0; 1471} 1472 1473 1474mvertex_t *r_pcurrentvertbase; 1475model_t *currentmodel; 1476 1477int nColinElim; 1478 1479/* 1480================ 1481BuildSurfaceDisplayList 1482================ 1483*/ 1484void BuildSurfaceDisplayList (msurface_t *fa) 1485{ 1486 int i, lindex, lnumverts; 1487 medge_t *pedges, *r_pedge; 1488 int vertpage; 1489 float *vec; 1490 float s, t; 1491 glpoly_t *poly; 1492 1493// reconstruct the polygon 1494 pedges = currentmodel->edges; 1495 lnumverts = fa->numedges; 1496 vertpage = 0; 1497 1498 // 1499 // draw texture 1500 // 1501 poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float)); 1502 poly->next = fa->polys; 1503 poly->flags = fa->flags; 1504 fa->polys = poly; 1505 poly->numverts = lnumverts; 1506 1507 for (i=0 ; i<lnumverts ; i++) 1508 { 1509 lindex = currentmodel->surfedges[fa->firstedge + i]; 1510 1511 if (lindex > 0) 1512 { 1513 r_pedge = &pedges[lindex]; 1514 vec = r_pcurrentvertbase[r_pedge->v[0]].position; 1515 } 1516 else 1517 { 1518 r_pedge = &pedges[-lindex]; 1519 vec = r_pcurrentvertbase[r_pedge->v[1]].position; 1520 } 1521 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; 1522 s /= fa->texinfo->texture->width; 1523 1524 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; 1525 t /= fa->texinfo->texture->height; 1526 1527 VectorCopy (vec, poly->verts[i]); 1528 poly->verts[i][3] = s; 1529 poly->verts[i][4] = t; 1530 1531 // 1532 // lightmap texture coordinates 1533 // 1534 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; 1535 s -= fa->texturemins[0]; 1536 s += fa->light_s*16; 1537 s += 8; 1538 s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width; 1539 1540 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; 1541 t -= fa->texturemins[1]; 1542 t += fa->light_t*16; 1543 t += 8; 1544 t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height; 1545 1546 poly->verts[i][5] = s; 1547 poly->verts[i][6] = t; 1548 } 1549 1550 // 1551 // remove co-linear points - Ed 1552 // 1553 if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) ) 1554 { 1555 for (i = 0 ; i < lnumverts ; ++i) 1556 { 1557 vec3_t v1, v2; 1558 float *prev, *this, *next; 1559 1560 prev = poly->verts[(i + lnumverts - 1) % lnumverts]; 1561 this = poly->verts[i]; 1562 next = poly->verts[(i + 1) % lnumverts]; 1563 1564 VectorSubtract( this, prev, v1 ); 1565 VectorNormalize( v1 ); 1566 VectorSubtract( next, prev, v2 ); 1567 VectorNormalize( v2 ); 1568 1569 // skip co-linear points 1570 #define COLINEAR_EPSILON 0.001 1571 if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) && 1572 (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && 1573 (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON)) 1574 { 1575 int j; 1576 for (j = i + 1; j < lnumverts; ++j) 1577 { 1578 int k; 1579 for (k = 0; k < VERTEXSIZE; ++k) 1580 poly->verts[j - 1][k] = poly->verts[j][k]; 1581 } 1582 --lnumverts; 1583 ++nColinElim; 1584 // retry next vertex next time, which is now current vertex 1585 --i; 1586 } 1587 } 1588 } 1589 poly->numverts = lnumverts; 1590 1591} 1592 1593/* 1594======================== 1595GL_CreateSurfaceLightmap 1596======================== 1597*/ 1598void GL_CreateSurfaceLightmap (msurface_t *surf) 1599{ 1600 int smax, tmax; 1601 byte *base; 1602 1603 if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) 1604 return; 1605 1606 smax = (surf->extents[0]>>4)+1; 1607 tmax = (surf->extents[1]>>4)+1; 1608 1609 surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); 1610 base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; 1611 base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; 1612 R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes); 1613} 1614 1615 1616/* 1617================== 1618GL_BuildLightmaps 1619 1620Builds the lightmap texture 1621with all the surfaces from all brush models 1622================== 1623*/ 1624void GL_BuildLightmaps (void) 1625{ 1626 int i, j; 1627 model_t *m; 1628 1629 memset (allocated, 0, sizeof(allocated)); 1630 1631 r_framecount = 1; // no dlightcache 1632 1633 if (!lightmap_textures) 1634 { 1635 lightmap_textures = texture_extension_number; 1636 texture_extension_number += MAX_LIGHTMAPS; 1637 } 1638 1639 gl_lightmap_format = GL_LUMINANCE; 1640 if (COM_CheckParm ("-lm_1")) 1641 gl_lightmap_format = GL_LUMINANCE; 1642 if (COM_CheckParm ("-lm_a")) 1643 gl_lightmap_format = GL_ALPHA; 1644 if (COM_CheckParm ("-lm_i")) 1645 gl_lightmap_format = GL_INTENSITY; 1646 if (COM_CheckParm ("-lm_2")) 1647 gl_lightmap_format = GL_RGBA4; 1648 if (COM_CheckParm ("-lm_4")) 1649 gl_lightmap_format = GL_RGBA; 1650 1651 switch (gl_lightmap_format) 1652 { 1653 case GL_RGBA: 1654 lightmap_bytes = 4; 1655 break; 1656 case GL_RGBA4: 1657 lightmap_bytes = 2; 1658 break; 1659 case GL_LUMINANCE: 1660 case GL_INTENSITY: 1661 case GL_ALPHA: 1662 lightmap_bytes = 1; 1663 break; 1664 } 1665 1666 for (j=1 ; j<MAX_MODELS ; j++) 1667 { 1668 m = cl.model_precache[j]; 1669 if (!m) 1670 break; 1671 if (m->name[0] == '*') 1672 continue; 1673 r_pcurrentvertbase = m->vertexes; 1674 currentmodel = m; 1675 for (i=0 ; i<m->numsurfaces ; i++) 1676 { 1677 GL_CreateSurfaceLightmap (m->surfaces + i); 1678 if ( m->surfaces[i].flags & SURF_DRAWTURB ) 1679 continue; 1680#ifndef QUAKE2 1681 if ( m->surfaces[i].flags & SURF_DRAWSKY ) 1682 continue; 1683#endif 1684 BuildSurfaceDisplayList (m->surfaces + i); 1685 } 1686 } 1687 1688 if (!gl_texsort.value) 1689 GL_SelectTexture(TEXTURE1_SGIS); 1690 1691 // 1692 // upload all lightmaps that were filled 1693 // 1694 for (i=0 ; i<MAX_LIGHTMAPS ; i++) 1695 { 1696 if (!allocated[i][0]) 1697 break; // no more used 1698 lightmap_modified[i] = false; 1699 lightmap_rectchange[i].l = BLOCK_WIDTH; 1700 lightmap_rectchange[i].t = BLOCK_HEIGHT; 1701 lightmap_rectchange[i].w = 0; 1702 lightmap_rectchange[i].h = 0; 1703 GL_Bind(lightmap_textures + i); 1704 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1705 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1706 glTexImage2DHelper (GL_TEXTURE_2D, 0, lightmap_bytes 1707 , BLOCK_WIDTH, BLOCK_HEIGHT, 0, 1708 gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes); 1709 } 1710 1711 if (!gl_texsort.value) 1712 GL_SelectTexture(TEXTURE0_SGIS); 1713 1714} 1715 1716