r_poly.c (29528B)
1 /* 2 Copyright (C) 1997-2001 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 #include <assert.h> 21 #include "r_local.h" 22 23 #define AFFINE_SPANLET_SIZE 16 24 #define AFFINE_SPANLET_SIZE_BITS 4 25 26 typedef struct 27 { 28 byte *pbase, *pdest; 29 short *pz; 30 fixed16_t s, t; 31 fixed16_t sstep, tstep; 32 int izi, izistep, izistep_times_2; 33 int spancount; 34 unsigned u, v; 35 } spanletvars_t; 36 37 spanletvars_t s_spanletvars; 38 39 static int r_polyblendcolor; 40 41 static espan_t *s_polygon_spans; 42 43 polydesc_t r_polydesc; 44 45 msurface_t *r_alpha_surfaces; 46 47 extern int *r_turb_turb; 48 49 static int clip_current; 50 vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]; 51 52 static int s_minindex, s_maxindex; 53 54 static void R_DrawPoly( qboolean iswater ); 55 56 /* 57 ** R_DrawSpanletOpaque 58 */ 59 void R_DrawSpanletOpaque( void ) 60 { 61 unsigned btemp; 62 63 do 64 { 65 unsigned ts, tt; 66 67 ts = s_spanletvars.s >> 16; 68 tt = s_spanletvars.t >> 16; 69 70 btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); 71 if (btemp != 255) 72 { 73 if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) 74 { 75 *s_spanletvars.pz = s_spanletvars.izi >> 16; 76 *s_spanletvars.pdest = btemp; 77 } 78 } 79 80 s_spanletvars.izi += s_spanletvars.izistep; 81 s_spanletvars.pdest++; 82 s_spanletvars.pz++; 83 s_spanletvars.s += s_spanletvars.sstep; 84 s_spanletvars.t += s_spanletvars.tstep; 85 } while (--s_spanletvars.spancount > 0); 86 } 87 88 /* 89 ** R_DrawSpanletTurbulentStipple33 90 */ 91 void R_DrawSpanletTurbulentStipple33( void ) 92 { 93 unsigned btemp; 94 int sturb, tturb; 95 byte *pdest = s_spanletvars.pdest; 96 short *pz = s_spanletvars.pz; 97 int izi = s_spanletvars.izi; 98 99 if ( s_spanletvars.v & 1 ) 100 { 101 s_spanletvars.pdest += s_spanletvars.spancount; 102 s_spanletvars.pz += s_spanletvars.spancount; 103 104 if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) 105 s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; 106 else 107 s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; 108 109 if ( s_spanletvars.u & 1 ) 110 { 111 izi += s_spanletvars.izistep; 112 s_spanletvars.s += s_spanletvars.sstep; 113 s_spanletvars.t += s_spanletvars.tstep; 114 115 pdest++; 116 pz++; 117 s_spanletvars.spancount--; 118 } 119 120 s_spanletvars.sstep *= 2; 121 s_spanletvars.tstep *= 2; 122 123 while ( s_spanletvars.spancount > 0 ) 124 { 125 sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; 126 tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; 127 128 btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); 129 130 if ( *pz <= ( izi >> 16 ) ) 131 *pdest = btemp; 132 133 izi += s_spanletvars.izistep_times_2; 134 s_spanletvars.s += s_spanletvars.sstep; 135 s_spanletvars.t += s_spanletvars.tstep; 136 137 pdest += 2; 138 pz += 2; 139 140 s_spanletvars.spancount -= 2; 141 } 142 } 143 } 144 145 /* 146 ** R_DrawSpanletTurbulentStipple66 147 */ 148 void R_DrawSpanletTurbulentStipple66( void ) 149 { 150 unsigned btemp; 151 int sturb, tturb; 152 byte *pdest = s_spanletvars.pdest; 153 short *pz = s_spanletvars.pz; 154 int izi = s_spanletvars.izi; 155 156 if ( !( s_spanletvars.v & 1 ) ) 157 { 158 s_spanletvars.pdest += s_spanletvars.spancount; 159 s_spanletvars.pz += s_spanletvars.spancount; 160 161 if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) 162 s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; 163 else 164 s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; 165 166 if ( s_spanletvars.u & 1 ) 167 { 168 izi += s_spanletvars.izistep; 169 s_spanletvars.s += s_spanletvars.sstep; 170 s_spanletvars.t += s_spanletvars.tstep; 171 172 pdest++; 173 pz++; 174 s_spanletvars.spancount--; 175 } 176 177 s_spanletvars.sstep *= 2; 178 s_spanletvars.tstep *= 2; 179 180 while ( s_spanletvars.spancount > 0 ) 181 { 182 sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; 183 tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; 184 185 btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); 186 187 if ( *pz <= ( izi >> 16 ) ) 188 *pdest = btemp; 189 190 izi += s_spanletvars.izistep_times_2; 191 s_spanletvars.s += s_spanletvars.sstep; 192 s_spanletvars.t += s_spanletvars.tstep; 193 194 pdest += 2; 195 pz += 2; 196 197 s_spanletvars.spancount -= 2; 198 } 199 } 200 else 201 { 202 s_spanletvars.pdest += s_spanletvars.spancount; 203 s_spanletvars.pz += s_spanletvars.spancount; 204 205 if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) 206 s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; 207 else 208 s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; 209 210 while ( s_spanletvars.spancount > 0 ) 211 { 212 sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; 213 tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; 214 215 btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); 216 217 if ( *pz <= ( izi >> 16 ) ) 218 *pdest = btemp; 219 220 izi += s_spanletvars.izistep; 221 s_spanletvars.s += s_spanletvars.sstep; 222 s_spanletvars.t += s_spanletvars.tstep; 223 224 pdest++; 225 pz++; 226 227 s_spanletvars.spancount--; 228 } 229 } 230 } 231 232 /* 233 ** R_DrawSpanletTurbulentBlended 234 */ 235 void R_DrawSpanletTurbulentBlended66( void ) 236 { 237 unsigned btemp; 238 int sturb, tturb; 239 240 do 241 { 242 sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; 243 tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; 244 245 btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); 246 247 if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) 248 *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest]; 249 250 s_spanletvars.izi += s_spanletvars.izistep; 251 s_spanletvars.pdest++; 252 s_spanletvars.pz++; 253 s_spanletvars.s += s_spanletvars.sstep; 254 s_spanletvars.t += s_spanletvars.tstep; 255 256 } while ( --s_spanletvars.spancount > 0 ); 257 } 258 259 void R_DrawSpanletTurbulentBlended33( void ) 260 { 261 unsigned btemp; 262 int sturb, tturb; 263 264 do 265 { 266 sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; 267 tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; 268 269 btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); 270 271 if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) 272 *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256]; 273 274 s_spanletvars.izi += s_spanletvars.izistep; 275 s_spanletvars.pdest++; 276 s_spanletvars.pz++; 277 s_spanletvars.s += s_spanletvars.sstep; 278 s_spanletvars.t += s_spanletvars.tstep; 279 280 } while ( --s_spanletvars.spancount > 0 ); 281 } 282 283 /* 284 ** R_DrawSpanlet33 285 */ 286 void R_DrawSpanlet33( void ) 287 { 288 unsigned btemp; 289 290 do 291 { 292 unsigned ts, tt; 293 294 ts = s_spanletvars.s >> 16; 295 tt = s_spanletvars.t >> 16; 296 297 btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); 298 299 if ( btemp != 255 ) 300 { 301 if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) 302 { 303 *s_spanletvars.pdest = vid.alphamap[btemp+*s_spanletvars.pdest*256]; 304 } 305 } 306 307 s_spanletvars.izi += s_spanletvars.izistep; 308 s_spanletvars.pdest++; 309 s_spanletvars.pz++; 310 s_spanletvars.s += s_spanletvars.sstep; 311 s_spanletvars.t += s_spanletvars.tstep; 312 } while (--s_spanletvars.spancount > 0); 313 } 314 315 void R_DrawSpanletConstant33( void ) 316 { 317 do 318 { 319 if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) 320 { 321 *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256]; 322 } 323 324 s_spanletvars.izi += s_spanletvars.izistep; 325 s_spanletvars.pdest++; 326 s_spanletvars.pz++; 327 } while (--s_spanletvars.spancount > 0); 328 } 329 330 /* 331 ** R_DrawSpanlet66 332 */ 333 void R_DrawSpanlet66( void ) 334 { 335 unsigned btemp; 336 337 do 338 { 339 unsigned ts, tt; 340 341 ts = s_spanletvars.s >> 16; 342 tt = s_spanletvars.t >> 16; 343 344 btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); 345 346 if ( btemp != 255 ) 347 { 348 if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) 349 { 350 *s_spanletvars.pdest = vid.alphamap[btemp*256+*s_spanletvars.pdest]; 351 } 352 } 353 354 s_spanletvars.izi += s_spanletvars.izistep; 355 s_spanletvars.pdest++; 356 s_spanletvars.pz++; 357 s_spanletvars.s += s_spanletvars.sstep; 358 s_spanletvars.t += s_spanletvars.tstep; 359 } while (--s_spanletvars.spancount > 0); 360 } 361 362 /* 363 ** R_DrawSpanlet33Stipple 364 */ 365 void R_DrawSpanlet33Stipple( void ) 366 { 367 unsigned btemp; 368 byte *pdest = s_spanletvars.pdest; 369 short *pz = s_spanletvars.pz; 370 int izi = s_spanletvars.izi; 371 372 if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) 373 { 374 s_spanletvars.pdest += s_spanletvars.spancount; 375 s_spanletvars.pz += s_spanletvars.spancount; 376 377 if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) 378 s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; 379 else 380 s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; 381 382 if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) 383 { 384 izi += s_spanletvars.izistep; 385 s_spanletvars.s += s_spanletvars.sstep; 386 s_spanletvars.t += s_spanletvars.tstep; 387 388 pdest++; 389 pz++; 390 s_spanletvars.spancount--; 391 } 392 393 s_spanletvars.sstep *= 2; 394 s_spanletvars.tstep *= 2; 395 396 while ( s_spanletvars.spancount > 0 ) 397 { 398 unsigned s = s_spanletvars.s >> 16; 399 unsigned t = s_spanletvars.t >> 16; 400 401 btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); 402 403 if ( btemp != 255 ) 404 { 405 if ( *pz <= ( izi >> 16 ) ) 406 *pdest = btemp; 407 } 408 409 izi += s_spanletvars.izistep_times_2; 410 s_spanletvars.s += s_spanletvars.sstep; 411 s_spanletvars.t += s_spanletvars.tstep; 412 413 pdest += 2; 414 pz += 2; 415 416 s_spanletvars.spancount -= 2; 417 } 418 } 419 } 420 421 /* 422 ** R_DrawSpanlet66Stipple 423 */ 424 void R_DrawSpanlet66Stipple( void ) 425 { 426 unsigned btemp; 427 byte *pdest = s_spanletvars.pdest; 428 short *pz = s_spanletvars.pz; 429 int izi = s_spanletvars.izi; 430 431 s_spanletvars.pdest += s_spanletvars.spancount; 432 s_spanletvars.pz += s_spanletvars.spancount; 433 434 if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) 435 s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; 436 else 437 s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; 438 439 if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) 440 { 441 if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) 442 { 443 izi += s_spanletvars.izistep; 444 s_spanletvars.s += s_spanletvars.sstep; 445 s_spanletvars.t += s_spanletvars.tstep; 446 447 pdest++; 448 pz++; 449 s_spanletvars.spancount--; 450 } 451 452 s_spanletvars.sstep *= 2; 453 s_spanletvars.tstep *= 2; 454 455 while ( s_spanletvars.spancount > 0 ) 456 { 457 unsigned s = s_spanletvars.s >> 16; 458 unsigned t = s_spanletvars.t >> 16; 459 460 btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); 461 462 if ( btemp != 255 ) 463 { 464 if ( *pz <= ( izi >> 16 ) ) 465 *pdest = btemp; 466 } 467 468 izi += s_spanletvars.izistep_times_2; 469 s_spanletvars.s += s_spanletvars.sstep; 470 s_spanletvars.t += s_spanletvars.tstep; 471 472 pdest += 2; 473 pz += 2; 474 475 s_spanletvars.spancount -= 2; 476 } 477 } 478 else 479 { 480 while ( s_spanletvars.spancount > 0 ) 481 { 482 unsigned s = s_spanletvars.s >> 16; 483 unsigned t = s_spanletvars.t >> 16; 484 485 btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); 486 487 if ( btemp != 255 ) 488 { 489 if ( *pz <= ( izi >> 16 ) ) 490 *pdest = btemp; 491 } 492 493 izi += s_spanletvars.izistep; 494 s_spanletvars.s += s_spanletvars.sstep; 495 s_spanletvars.t += s_spanletvars.tstep; 496 497 pdest++; 498 pz++; 499 500 s_spanletvars.spancount--; 501 } 502 } 503 } 504 505 /* 506 ** R_ClipPolyFace 507 ** 508 ** Clips the winding at clip_verts[clip_current] and changes clip_current 509 ** Throws out the back side 510 */ 511 int R_ClipPolyFace (int nump, clipplane_t *pclipplane) 512 { 513 int i, outcount; 514 float dists[MAXWORKINGVERTS+3]; 515 float frac, clipdist, *pclipnormal; 516 float *in, *instep, *outstep, *vert2; 517 518 clipdist = pclipplane->dist; 519 pclipnormal = pclipplane->normal; 520 521 // calc dists 522 if (clip_current) 523 { 524 in = r_clip_verts[1][0]; 525 outstep = r_clip_verts[0][0]; 526 clip_current = 0; 527 } 528 else 529 { 530 in = r_clip_verts[0][0]; 531 outstep = r_clip_verts[1][0]; 532 clip_current = 1; 533 } 534 535 instep = in; 536 for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float)) 537 { 538 dists[i] = DotProduct (instep, pclipnormal) - clipdist; 539 } 540 541 // handle wraparound case 542 dists[nump] = dists[0]; 543 memcpy (instep, in, sizeof (vec5_t)); 544 545 546 // clip the winding 547 instep = in; 548 outcount = 0; 549 550 for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float)) 551 { 552 if (dists[i] >= 0) 553 { 554 memcpy (outstep, instep, sizeof (vec5_t)); 555 outstep += sizeof (vec5_t) / sizeof (float); 556 outcount++; 557 } 558 559 if (dists[i] == 0 || dists[i+1] == 0) 560 continue; 561 562 if ( (dists[i] > 0) == (dists[i+1] > 0) ) 563 continue; 564 565 // split it into a new vertex 566 frac = dists[i] / (dists[i] - dists[i+1]); 567 568 vert2 = instep + sizeof (vec5_t) / sizeof (float); 569 570 outstep[0] = instep[0] + frac*(vert2[0] - instep[0]); 571 outstep[1] = instep[1] + frac*(vert2[1] - instep[1]); 572 outstep[2] = instep[2] + frac*(vert2[2] - instep[2]); 573 outstep[3] = instep[3] + frac*(vert2[3] - instep[3]); 574 outstep[4] = instep[4] + frac*(vert2[4] - instep[4]); 575 576 outstep += sizeof (vec5_t) / sizeof (float); 577 outcount++; 578 } 579 580 return outcount; 581 } 582 583 /* 584 ** R_PolygonDrawSpans 585 */ 586 void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater ) 587 { 588 int count; 589 fixed16_t snext, tnext; 590 float sdivz, tdivz, zi, z, du, dv, spancountminus1; 591 float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu; 592 593 s_spanletvars.pbase = cacheblock; 594 595 if ( iswater ) 596 r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); 597 598 sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE; 599 tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE; 600 zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE; 601 602 // we count on FP exceptions being turned off to avoid range problems 603 s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000); 604 s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2; 605 606 s_spanletvars.pz = 0; 607 608 do 609 { 610 s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u; 611 s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; 612 s_spanletvars.u = pspan->u; 613 s_spanletvars.v = pspan->v; 614 615 count = pspan->count; 616 617 if (count <= 0) 618 goto NextSpan; 619 620 // calculate the initial s/z, t/z, 1/z, s, and t and clamp 621 du = (float)pspan->u; 622 dv = (float)pspan->v; 623 624 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; 625 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; 626 627 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; 628 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 629 // we count on FP exceptions being turned off to avoid range problems 630 s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000); 631 632 s_spanletvars.s = (int)(sdivz * z) + sadjust; 633 s_spanletvars.t = (int)(tdivz * z) + tadjust; 634 635 if ( !iswater ) 636 { 637 if (s_spanletvars.s > bbextents) 638 s_spanletvars.s = bbextents; 639 else if (s_spanletvars.s < 0) 640 s_spanletvars.s = 0; 641 642 if (s_spanletvars.t > bbextentt) 643 s_spanletvars.t = bbextentt; 644 else if (s_spanletvars.t < 0) 645 s_spanletvars.t = 0; 646 } 647 648 do 649 { 650 // calculate s and t at the far end of the span 651 if (count >= AFFINE_SPANLET_SIZE ) 652 s_spanletvars.spancount = AFFINE_SPANLET_SIZE; 653 else 654 s_spanletvars.spancount = count; 655 656 count -= s_spanletvars.spancount; 657 658 if (count) 659 { 660 // calculate s/z, t/z, zi->fixed s and t at far end of span, 661 // calculate s and t steps across span by shifting 662 sdivz += sdivzspanletstepu; 663 tdivz += tdivzspanletstepu; 664 zi += zispanletstepu; 665 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 666 667 snext = (int)(sdivz * z) + sadjust; 668 tnext = (int)(tdivz * z) + tadjust; 669 670 if ( !iswater ) 671 { 672 if (snext > bbextents) 673 snext = bbextents; 674 else if (snext < AFFINE_SPANLET_SIZE) 675 snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from 676 // from causing overstepping & running off the 677 // edge of the texture 678 679 if (tnext > bbextentt) 680 tnext = bbextentt; 681 else if (tnext < AFFINE_SPANLET_SIZE) 682 tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps 683 } 684 685 s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS; 686 s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS; 687 } 688 else 689 { 690 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so 691 // can't step off polygon), clamp, calculate s and t steps across 692 // span by division, biasing steps low so we don't run off the 693 // texture 694 spancountminus1 = (float)(s_spanletvars.spancount - 1); 695 sdivz += d_sdivzstepu * spancountminus1; 696 tdivz += d_tdivzstepu * spancountminus1; 697 zi += d_zistepu * spancountminus1; 698 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 699 snext = (int)(sdivz * z) + sadjust; 700 tnext = (int)(tdivz * z) + tadjust; 701 702 if ( !iswater ) 703 { 704 if (snext > bbextents) 705 snext = bbextents; 706 else if (snext < AFFINE_SPANLET_SIZE) 707 snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from 708 // from causing overstepping & running off the 709 // edge of the texture 710 711 if (tnext > bbextentt) 712 tnext = bbextentt; 713 else if (tnext < AFFINE_SPANLET_SIZE) 714 tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps 715 } 716 717 if (s_spanletvars.spancount > 1) 718 { 719 s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1); 720 s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1); 721 } 722 } 723 724 if ( iswater ) 725 { 726 s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1); 727 s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1); 728 } 729 730 r_polydesc.drawspanlet(); 731 732 s_spanletvars.s = snext; 733 s_spanletvars.t = tnext; 734 735 } while (count > 0); 736 737 NextSpan: 738 pspan++; 739 740 } while (pspan->count != DS_SPAN_LIST_END); 741 } 742 743 /* 744 ** 745 ** R_PolygonScanLeftEdge 746 ** 747 ** Goes through the polygon and scans the left edge, filling in 748 ** screen coordinate data for the spans 749 */ 750 void R_PolygonScanLeftEdge (void) 751 { 752 int i, v, itop, ibottom, lmaxindex; 753 emitpoint_t *pvert, *pnext; 754 espan_t *pspan; 755 float du, dv, vtop, vbottom, slope; 756 fixed16_t u, u_step; 757 758 pspan = s_polygon_spans; 759 i = s_minindex; 760 if (i == 0) 761 i = r_polydesc.nump; 762 763 lmaxindex = s_maxindex; 764 if (lmaxindex == 0) 765 lmaxindex = r_polydesc.nump; 766 767 vtop = ceil (r_polydesc.pverts[i].v); 768 769 do 770 { 771 pvert = &r_polydesc.pverts[i]; 772 pnext = pvert - 1; 773 774 vbottom = ceil (pnext->v); 775 776 if (vtop < vbottom) 777 { 778 du = pnext->u - pvert->u; 779 dv = pnext->v - pvert->v; 780 781 slope = du / dv; 782 u_step = (int)(slope * 0x10000); 783 // adjust u to ceil the integer portion 784 u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + 785 (0x10000 - 1); 786 itop = (int)vtop; 787 ibottom = (int)vbottom; 788 789 for (v=itop ; v<ibottom ; v++) 790 { 791 pspan->u = u >> 16; 792 pspan->v = v; 793 u += u_step; 794 pspan++; 795 } 796 } 797 798 vtop = vbottom; 799 800 i--; 801 if (i == 0) 802 i = r_polydesc.nump; 803 804 } while (i != lmaxindex); 805 } 806 807 /* 808 ** R_PolygonScanRightEdge 809 ** 810 ** Goes through the polygon and scans the right edge, filling in 811 ** count values. 812 */ 813 void R_PolygonScanRightEdge (void) 814 { 815 int i, v, itop, ibottom; 816 emitpoint_t *pvert, *pnext; 817 espan_t *pspan; 818 float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; 819 fixed16_t u, u_step; 820 821 pspan = s_polygon_spans; 822 i = s_minindex; 823 824 vvert = r_polydesc.pverts[i].v; 825 if (vvert < r_refdef.fvrecty_adj) 826 vvert = r_refdef.fvrecty_adj; 827 if (vvert > r_refdef.fvrectbottom_adj) 828 vvert = r_refdef.fvrectbottom_adj; 829 830 vtop = ceil (vvert); 831 832 do 833 { 834 pvert = &r_polydesc.pverts[i]; 835 pnext = pvert + 1; 836 837 vnext = pnext->v; 838 if (vnext < r_refdef.fvrecty_adj) 839 vnext = r_refdef.fvrecty_adj; 840 if (vnext > r_refdef.fvrectbottom_adj) 841 vnext = r_refdef.fvrectbottom_adj; 842 843 vbottom = ceil (vnext); 844 845 if (vtop < vbottom) 846 { 847 uvert = pvert->u; 848 if (uvert < r_refdef.fvrectx_adj) 849 uvert = r_refdef.fvrectx_adj; 850 if (uvert > r_refdef.fvrectright_adj) 851 uvert = r_refdef.fvrectright_adj; 852 853 unext = pnext->u; 854 if (unext < r_refdef.fvrectx_adj) 855 unext = r_refdef.fvrectx_adj; 856 if (unext > r_refdef.fvrectright_adj) 857 unext = r_refdef.fvrectright_adj; 858 859 du = unext - uvert; 860 dv = vnext - vvert; 861 slope = du / dv; 862 u_step = (int)(slope * 0x10000); 863 // adjust u to ceil the integer portion 864 u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + 865 (0x10000 - 1); 866 itop = (int)vtop; 867 ibottom = (int)vbottom; 868 869 for (v=itop ; v<ibottom ; v++) 870 { 871 pspan->count = (u >> 16) - pspan->u; 872 u += u_step; 873 pspan++; 874 } 875 } 876 877 vtop = vbottom; 878 vvert = vnext; 879 880 i++; 881 if (i == r_polydesc.nump) 882 i = 0; 883 884 } while (i != s_maxindex); 885 886 pspan->count = DS_SPAN_LIST_END; // mark the end of the span list 887 } 888 889 /* 890 ** R_ClipAndDrawPoly 891 */ 892 void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ) 893 { 894 emitpoint_t outverts[MAXWORKINGVERTS+3], *pout; 895 float *pv; 896 int i, nump; 897 float scale; 898 vec3_t transformed, local; 899 900 if ( !textured ) 901 { 902 r_polydesc.drawspanlet = R_DrawSpanletConstant33; 903 } 904 else 905 { 906 907 /* 908 ** choose the correct spanlet routine based on alpha 909 */ 910 if ( alpha == 1 ) 911 { 912 // isturbulent is ignored because we know that turbulent surfaces 913 // can't be opaque 914 r_polydesc.drawspanlet = R_DrawSpanletOpaque; 915 } 916 else 917 { 918 if ( sw_stipplealpha->value ) 919 { 920 if ( isturbulent ) 921 { 922 if ( alpha > 0.33 ) 923 r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66; 924 else 925 r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33; 926 } 927 else 928 { 929 if ( alpha > 0.33 ) 930 r_polydesc.drawspanlet = R_DrawSpanlet66Stipple; 931 else 932 r_polydesc.drawspanlet = R_DrawSpanlet33Stipple; 933 } 934 } 935 else 936 { 937 if ( isturbulent ) 938 { 939 if ( alpha > 0.33 ) 940 r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66; 941 else 942 r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33; 943 } 944 else 945 { 946 if ( alpha > 0.33 ) 947 r_polydesc.drawspanlet = R_DrawSpanlet66; 948 else 949 r_polydesc.drawspanlet = R_DrawSpanlet33; 950 } 951 } 952 } 953 } 954 955 // clip to the frustum in worldspace 956 nump = r_polydesc.nump; 957 clip_current = 0; 958 959 for (i=0 ; i<4 ; i++) 960 { 961 nump = R_ClipPolyFace (nump, &view_clipplanes[i]); 962 if (nump < 3) 963 return; 964 if (nump > MAXWORKINGVERTS) 965 ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump ); 966 } 967 968 // transform vertices into viewspace and project 969 pv = &r_clip_verts[clip_current][0][0]; 970 971 for (i=0 ; i<nump ; i++) 972 { 973 VectorSubtract (pv, r_origin, local); 974 TransformVector (local, transformed); 975 976 if (transformed[2] < NEAR_CLIP) 977 transformed[2] = NEAR_CLIP; 978 979 pout = &outverts[i]; 980 pout->zi = 1.0 / transformed[2]; 981 982 pout->s = pv[3]; 983 pout->t = pv[4]; 984 985 scale = xscale * pout->zi; 986 pout->u = (xcenter + scale * transformed[0]); 987 988 scale = yscale * pout->zi; 989 pout->v = (ycenter - scale * transformed[1]); 990 991 pv += sizeof (vec5_t) / sizeof (pv); 992 } 993 994 // draw it 995 r_polydesc.nump = nump; 996 r_polydesc.pverts = outverts; 997 998 R_DrawPoly( isturbulent ); 999 } 1000 1001 /* 1002 ** R_BuildPolygonFromSurface 1003 */ 1004 void R_BuildPolygonFromSurface(msurface_t *fa) 1005 { 1006 int i, lindex, lnumverts; 1007 medge_t *pedges, *r_pedge; 1008 int vertpage; 1009 float *vec; 1010 vec5_t *pverts; 1011 float tmins[2] = { 0, 0 }; 1012 1013 r_polydesc.nump = 0; 1014 1015 // reconstruct the polygon 1016 pedges = currentmodel->edges; 1017 lnumverts = fa->numedges; 1018 vertpage = 0; 1019 1020 pverts = r_clip_verts[0]; 1021 1022 for (i=0 ; i<lnumverts ; i++) 1023 { 1024 lindex = currentmodel->surfedges[fa->firstedge + i]; 1025 1026 if (lindex > 0) 1027 { 1028 r_pedge = &pedges[lindex]; 1029 vec = currentmodel->vertexes[r_pedge->v[0]].position; 1030 } 1031 else 1032 { 1033 r_pedge = &pedges[-lindex]; 1034 vec = currentmodel->vertexes[r_pedge->v[1]].position; 1035 } 1036 1037 VectorCopy (vec, pverts[i] ); 1038 } 1039 1040 VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright ); 1041 VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup ); 1042 VectorCopy( fa->plane->normal, r_polydesc.vpn ); 1043 VectorCopy( r_origin, r_polydesc.viewer_position ); 1044 1045 if ( fa->flags & SURF_PLANEBACK ) 1046 { 1047 VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn ); 1048 } 1049 1050 if ( fa->texinfo->flags & SURF_WARP ) 1051 { 1052 r_polydesc.pixels = fa->texinfo->image->pixels[0]; 1053 r_polydesc.pixel_width = fa->texinfo->image->width; 1054 r_polydesc.pixel_height = fa->texinfo->image->height; 1055 } 1056 else 1057 { 1058 surfcache_t *scache; 1059 1060 scache = D_CacheSurface( fa, 0 ); 1061 1062 r_polydesc.pixels = scache->data; 1063 r_polydesc.pixel_width = scache->width; 1064 r_polydesc.pixel_height = scache->height; 1065 1066 tmins[0] = fa->texturemins[0]; 1067 tmins[1] = fa->texturemins[1]; 1068 } 1069 1070 r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] ); 1071 1072 r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0]; 1073 r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1]; 1074 1075 // scrolling texture addition 1076 if (fa->texinfo->flags & SURF_FLOWING) 1077 { 1078 r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) ); 1079 } 1080 1081 r_polydesc.nump = lnumverts; 1082 } 1083 1084 /* 1085 ** R_PolygonCalculateGradients 1086 */ 1087 void R_PolygonCalculateGradients (void) 1088 { 1089 vec3_t p_normal, p_saxis, p_taxis; 1090 float distinv; 1091 1092 TransformVector (r_polydesc.vpn, p_normal); 1093 TransformVector (r_polydesc.vright, p_saxis); 1094 TransformVector (r_polydesc.vup, p_taxis); 1095 1096 distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist ); 1097 1098 d_sdivzstepu = p_saxis[0] * xscaleinv; 1099 d_sdivzstepv = -p_saxis[1] * yscaleinv; 1100 d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; 1101 1102 d_tdivzstepu = p_taxis[0] * xscaleinv; 1103 d_tdivzstepv = -p_taxis[1] * yscaleinv; 1104 d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; 1105 1106 d_zistepu = p_normal[0] * xscaleinv * distinv; 1107 d_zistepv = -p_normal[1] * yscaleinv * distinv; 1108 d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv; 1109 1110 sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 ); 1111 tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 ); 1112 1113 // -1 (-epsilon) so we never wander off the edge of the texture 1114 bbextents = (r_polydesc.pixel_width << 16) - 1; 1115 bbextentt = (r_polydesc.pixel_height << 16) - 1; 1116 } 1117 1118 /* 1119 ** R_DrawPoly 1120 ** 1121 ** Polygon drawing function. Uses the polygon described in r_polydesc 1122 ** to calculate edges and gradients, then renders the resultant spans. 1123 ** 1124 ** This should NOT be called externally since it doesn't do clipping! 1125 */ 1126 static void R_DrawPoly( qboolean iswater ) 1127 { 1128 int i, nump; 1129 float ymin, ymax; 1130 emitpoint_t *pverts; 1131 espan_t spans[MAXHEIGHT+1]; 1132 1133 s_polygon_spans = spans; 1134 1135 // find the top and bottom vertices, and make sure there's at least one scan to 1136 // draw 1137 ymin = 999999.9; 1138 ymax = -999999.9; 1139 pverts = r_polydesc.pverts; 1140 1141 for (i=0 ; i<r_polydesc.nump ; i++) 1142 { 1143 if (pverts->v < ymin) 1144 { 1145 ymin = pverts->v; 1146 s_minindex = i; 1147 } 1148 1149 if (pverts->v > ymax) 1150 { 1151 ymax = pverts->v; 1152 s_maxindex = i; 1153 } 1154 1155 pverts++; 1156 } 1157 1158 ymin = ceil (ymin); 1159 ymax = ceil (ymax); 1160 1161 if (ymin >= ymax) 1162 return; // doesn't cross any scans at all 1163 1164 cachewidth = r_polydesc.pixel_width; 1165 cacheblock = r_polydesc.pixels; 1166 1167 // copy the first vertex to the last vertex, so we don't have to deal with 1168 // wrapping 1169 nump = r_polydesc.nump; 1170 pverts = r_polydesc.pverts; 1171 pverts[nump] = pverts[0]; 1172 1173 R_PolygonCalculateGradients (); 1174 R_PolygonScanLeftEdge (); 1175 R_PolygonScanRightEdge (); 1176 1177 R_PolygonDrawSpans( s_polygon_spans, iswater ); 1178 } 1179 1180 /* 1181 ** R_DrawAlphaSurfaces 1182 */ 1183 void R_DrawAlphaSurfaces( void ) 1184 { 1185 msurface_t *s = r_alpha_surfaces; 1186 1187 currentmodel = r_worldmodel; 1188 1189 modelorg[0] = -r_origin[0]; 1190 modelorg[1] = -r_origin[1]; 1191 modelorg[2] = -r_origin[2]; 1192 1193 while ( s ) 1194 { 1195 R_BuildPolygonFromSurface( s ); 1196 1197 if (s->texinfo->flags & SURF_TRANS66) 1198 R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true ); 1199 else 1200 R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true ); 1201 1202 s = s->nextalphasurface; 1203 } 1204 1205 r_alpha_surfaces = NULL; 1206 } 1207 1208 /* 1209 ** R_IMFlatShadedQuad 1210 */ 1211 void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha ) 1212 { 1213 vec3_t s0, s1; 1214 1215 r_polydesc.nump = 4; 1216 VectorCopy( r_origin, r_polydesc.viewer_position ); 1217 1218 VectorCopy( a, r_clip_verts[0][0] ); 1219 VectorCopy( b, r_clip_verts[0][1] ); 1220 VectorCopy( c, r_clip_verts[0][2] ); 1221 VectorCopy( d, r_clip_verts[0][3] ); 1222 1223 r_clip_verts[0][0][3] = 0; 1224 r_clip_verts[0][1][3] = 0; 1225 r_clip_verts[0][2][3] = 0; 1226 r_clip_verts[0][3][3] = 0; 1227 1228 r_clip_verts[0][0][4] = 0; 1229 r_clip_verts[0][1][4] = 0; 1230 r_clip_verts[0][2][4] = 0; 1231 r_clip_verts[0][3][4] = 0; 1232 1233 VectorSubtract( d, c, s0 ); 1234 VectorSubtract( c, b, s1 ); 1235 CrossProduct( s0, s1, r_polydesc.vpn ); 1236 VectorNormalize( r_polydesc.vpn ); 1237 1238 r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] ); 1239 1240 r_polyblendcolor = color; 1241 1242 R_ClipAndDrawPoly( alpha, false, false ); 1243 } 1244