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