r_scan.c (14695B)
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 // d_scan.c 21 // 22 // Portable C scan-level rasterization code, all pixel depths. 23 24 #include "r_local.h" 25 26 unsigned char *r_turb_pbase, *r_turb_pdest; 27 fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; 28 int *r_turb_turb; 29 int r_turb_spancount; 30 31 void D_DrawTurbulent8Span (void); 32 33 34 /* 35 ============= 36 D_WarpScreen 37 38 this performs a slight compression of the screen at the same time as 39 the sine warp, to keep the edges from wrapping 40 ============= 41 */ 42 void D_WarpScreen (void) 43 { 44 int w, h; 45 int u,v, u2, v2; 46 byte *dest; 47 int *turb; 48 int *col; 49 byte **row; 50 51 static int cached_width, cached_height; 52 static byte *rowptr[1200+AMP2*2]; 53 static int column[1600+AMP2*2]; 54 55 // 56 // these are constant over resolutions, and can be saved 57 // 58 w = r_newrefdef.width; 59 h = r_newrefdef.height; 60 if (w != cached_width || h != cached_height) 61 { 62 cached_width = w; 63 cached_height = h; 64 for (v=0 ; v<h+AMP2*2 ; v++) 65 { 66 v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height); 67 rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2); 68 } 69 70 for (u=0 ; u<w+AMP2*2 ; u++) 71 { 72 u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width); 73 column[u] = u2; 74 } 75 } 76 77 turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); 78 dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x; 79 80 for (v=0 ; v<h ; v++, dest += vid.rowbytes) 81 { 82 col = &column[turb[v]]; 83 row = &rowptr[v]; 84 for (u=0 ; u<w ; u+=4) 85 { 86 dest[u+0] = row[turb[u+0]][col[u+0]]; 87 dest[u+1] = row[turb[u+1]][col[u+1]]; 88 dest[u+2] = row[turb[u+2]][col[u+2]]; 89 dest[u+3] = row[turb[u+3]][col[u+3]]; 90 } 91 } 92 } 93 94 95 #if !id386 96 97 /* 98 ============= 99 D_DrawTurbulent8Span 100 ============= 101 */ 102 void D_DrawTurbulent8Span (void) 103 { 104 int sturb, tturb; 105 106 do 107 { 108 sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63; 109 tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; 110 *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb); 111 r_turb_s += r_turb_sstep; 112 r_turb_t += r_turb_tstep; 113 } while (--r_turb_spancount > 0); 114 } 115 116 #endif // !id386 117 118 119 /* 120 ============= 121 Turbulent8 122 ============= 123 */ 124 void Turbulent8 (espan_t *pspan) 125 { 126 int count; 127 fixed16_t snext, tnext; 128 float sdivz, tdivz, zi, z, du, dv, spancountminus1; 129 float sdivz16stepu, tdivz16stepu, zi16stepu; 130 131 r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); 132 133 r_turb_sstep = 0; // keep compiler happy 134 r_turb_tstep = 0; // ditto 135 136 r_turb_pbase = (unsigned char *)cacheblock; 137 138 sdivz16stepu = d_sdivzstepu * 16; 139 tdivz16stepu = d_tdivzstepu * 16; 140 zi16stepu = d_zistepu * 16; 141 142 do 143 { 144 r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + 145 (r_screenwidth * pspan->v) + pspan->u); 146 147 count = pspan->count; 148 149 // calculate the initial s/z, t/z, 1/z, s, and t and clamp 150 du = (float)pspan->u; 151 dv = (float)pspan->v; 152 153 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; 154 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; 155 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; 156 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 157 158 r_turb_s = (int)(sdivz * z) + sadjust; 159 if (r_turb_s > bbextents) 160 r_turb_s = bbextents; 161 else if (r_turb_s < 0) 162 r_turb_s = 0; 163 164 r_turb_t = (int)(tdivz * z) + tadjust; 165 if (r_turb_t > bbextentt) 166 r_turb_t = bbextentt; 167 else if (r_turb_t < 0) 168 r_turb_t = 0; 169 170 do 171 { 172 // calculate s and t at the far end of the span 173 if (count >= 16) 174 r_turb_spancount = 16; 175 else 176 r_turb_spancount = count; 177 178 count -= r_turb_spancount; 179 180 if (count) 181 { 182 // calculate s/z, t/z, zi->fixed s and t at far end of span, 183 // calculate s and t steps across span by shifting 184 sdivz += sdivz16stepu; 185 tdivz += tdivz16stepu; 186 zi += zi16stepu; 187 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 188 189 snext = (int)(sdivz * z) + sadjust; 190 if (snext > bbextents) 191 snext = bbextents; 192 else if (snext < 16) 193 snext = 16; // prevent round-off error on <0 steps from 194 // from causing overstepping & running off the 195 // edge of the texture 196 197 tnext = (int)(tdivz * z) + tadjust; 198 if (tnext > bbextentt) 199 tnext = bbextentt; 200 else if (tnext < 16) 201 tnext = 16; // guard against round-off error on <0 steps 202 203 r_turb_sstep = (snext - r_turb_s) >> 4; 204 r_turb_tstep = (tnext - r_turb_t) >> 4; 205 } 206 else 207 { 208 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so 209 // can't step off polygon), clamp, calculate s and t steps across 210 // span by division, biasing steps low so we don't run off the 211 // texture 212 spancountminus1 = (float)(r_turb_spancount - 1); 213 sdivz += d_sdivzstepu * spancountminus1; 214 tdivz += d_tdivzstepu * spancountminus1; 215 zi += d_zistepu * spancountminus1; 216 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 217 snext = (int)(sdivz * z) + sadjust; 218 if (snext > bbextents) 219 snext = bbextents; 220 else if (snext < 16) 221 snext = 16; // prevent round-off error on <0 steps from 222 // from causing overstepping & running off the 223 // edge of the texture 224 225 tnext = (int)(tdivz * z) + tadjust; 226 if (tnext > bbextentt) 227 tnext = bbextentt; 228 else if (tnext < 16) 229 tnext = 16; // guard against round-off error on <0 steps 230 231 if (r_turb_spancount > 1) 232 { 233 r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); 234 r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); 235 } 236 } 237 238 r_turb_s = r_turb_s & ((CYCLE<<16)-1); 239 r_turb_t = r_turb_t & ((CYCLE<<16)-1); 240 241 D_DrawTurbulent8Span (); 242 243 r_turb_s = snext; 244 r_turb_t = tnext; 245 246 } while (count > 0); 247 248 } while ((pspan = pspan->pnext) != NULL); 249 } 250 251 //==================== 252 //PGM 253 /* 254 ============= 255 NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures 256 but the turbulence is automatically 0. 257 ============= 258 */ 259 void NonTurbulent8 (espan_t *pspan) 260 { 261 int count; 262 fixed16_t snext, tnext; 263 float sdivz, tdivz, zi, z, du, dv, spancountminus1; 264 float sdivz16stepu, tdivz16stepu, zi16stepu; 265 266 // r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); 267 r_turb_turb = blanktable; 268 269 r_turb_sstep = 0; // keep compiler happy 270 r_turb_tstep = 0; // ditto 271 272 r_turb_pbase = (unsigned char *)cacheblock; 273 274 sdivz16stepu = d_sdivzstepu * 16; 275 tdivz16stepu = d_tdivzstepu * 16; 276 zi16stepu = d_zistepu * 16; 277 278 do 279 { 280 r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + 281 (r_screenwidth * pspan->v) + pspan->u); 282 283 count = pspan->count; 284 285 // calculate the initial s/z, t/z, 1/z, s, and t and clamp 286 du = (float)pspan->u; 287 dv = (float)pspan->v; 288 289 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; 290 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; 291 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; 292 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 293 294 r_turb_s = (int)(sdivz * z) + sadjust; 295 if (r_turb_s > bbextents) 296 r_turb_s = bbextents; 297 else if (r_turb_s < 0) 298 r_turb_s = 0; 299 300 r_turb_t = (int)(tdivz * z) + tadjust; 301 if (r_turb_t > bbextentt) 302 r_turb_t = bbextentt; 303 else if (r_turb_t < 0) 304 r_turb_t = 0; 305 306 do 307 { 308 // calculate s and t at the far end of the span 309 if (count >= 16) 310 r_turb_spancount = 16; 311 else 312 r_turb_spancount = count; 313 314 count -= r_turb_spancount; 315 316 if (count) 317 { 318 // calculate s/z, t/z, zi->fixed s and t at far end of span, 319 // calculate s and t steps across span by shifting 320 sdivz += sdivz16stepu; 321 tdivz += tdivz16stepu; 322 zi += zi16stepu; 323 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 324 325 snext = (int)(sdivz * z) + sadjust; 326 if (snext > bbextents) 327 snext = bbextents; 328 else if (snext < 16) 329 snext = 16; // prevent round-off error on <0 steps from 330 // from causing overstepping & running off the 331 // edge of the texture 332 333 tnext = (int)(tdivz * z) + tadjust; 334 if (tnext > bbextentt) 335 tnext = bbextentt; 336 else if (tnext < 16) 337 tnext = 16; // guard against round-off error on <0 steps 338 339 r_turb_sstep = (snext - r_turb_s) >> 4; 340 r_turb_tstep = (tnext - r_turb_t) >> 4; 341 } 342 else 343 { 344 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so 345 // can't step off polygon), clamp, calculate s and t steps across 346 // span by division, biasing steps low so we don't run off the 347 // texture 348 spancountminus1 = (float)(r_turb_spancount - 1); 349 sdivz += d_sdivzstepu * spancountminus1; 350 tdivz += d_tdivzstepu * spancountminus1; 351 zi += d_zistepu * spancountminus1; 352 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 353 snext = (int)(sdivz * z) + sadjust; 354 if (snext > bbextents) 355 snext = bbextents; 356 else if (snext < 16) 357 snext = 16; // prevent round-off error on <0 steps from 358 // from causing overstepping & running off the 359 // edge of the texture 360 361 tnext = (int)(tdivz * z) + tadjust; 362 if (tnext > bbextentt) 363 tnext = bbextentt; 364 else if (tnext < 16) 365 tnext = 16; // guard against round-off error on <0 steps 366 367 if (r_turb_spancount > 1) 368 { 369 r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); 370 r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); 371 } 372 } 373 374 r_turb_s = r_turb_s & ((CYCLE<<16)-1); 375 r_turb_t = r_turb_t & ((CYCLE<<16)-1); 376 377 D_DrawTurbulent8Span (); 378 379 r_turb_s = snext; 380 r_turb_t = tnext; 381 382 } while (count > 0); 383 384 } while ((pspan = pspan->pnext) != NULL); 385 } 386 //PGM 387 //==================== 388 389 390 #if !id386 391 392 /* 393 ============= 394 D_DrawSpans16 395 396 FIXME: actually make this subdivide by 16 instead of 8!!! 397 ============= 398 */ 399 void D_DrawSpans16 (espan_t *pspan) 400 { 401 int count, spancount; 402 unsigned char *pbase, *pdest; 403 fixed16_t s, t, snext, tnext, sstep, tstep; 404 float sdivz, tdivz, zi, z, du, dv, spancountminus1; 405 float sdivz8stepu, tdivz8stepu, zi8stepu; 406 407 sstep = 0; // keep compiler happy 408 tstep = 0; // ditto 409 410 pbase = (unsigned char *)cacheblock; 411 412 sdivz8stepu = d_sdivzstepu * 8; 413 tdivz8stepu = d_tdivzstepu * 8; 414 zi8stepu = d_zistepu * 8; 415 416 do 417 { 418 pdest = (unsigned char *)((byte *)d_viewbuffer + 419 (r_screenwidth * pspan->v) + pspan->u); 420 421 count = pspan->count; 422 423 // calculate the initial s/z, t/z, 1/z, s, and t and clamp 424 du = (float)pspan->u; 425 dv = (float)pspan->v; 426 427 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; 428 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; 429 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; 430 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 431 432 s = (int)(sdivz * z) + sadjust; 433 if (s > bbextents) 434 s = bbextents; 435 else if (s < 0) 436 s = 0; 437 438 t = (int)(tdivz * z) + tadjust; 439 if (t > bbextentt) 440 t = bbextentt; 441 else if (t < 0) 442 t = 0; 443 444 do 445 { 446 // calculate s and t at the far end of the span 447 if (count >= 8) 448 spancount = 8; 449 else 450 spancount = count; 451 452 count -= spancount; 453 454 if (count) 455 { 456 // calculate s/z, t/z, zi->fixed s and t at far end of span, 457 // calculate s and t steps across span by shifting 458 sdivz += sdivz8stepu; 459 tdivz += tdivz8stepu; 460 zi += zi8stepu; 461 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 462 463 snext = (int)(sdivz * z) + sadjust; 464 if (snext > bbextents) 465 snext = bbextents; 466 else if (snext < 8) 467 snext = 8; // prevent round-off error on <0 steps from 468 // from causing overstepping & running off the 469 // edge of the texture 470 471 tnext = (int)(tdivz * z) + tadjust; 472 if (tnext > bbextentt) 473 tnext = bbextentt; 474 else if (tnext < 8) 475 tnext = 8; // guard against round-off error on <0 steps 476 477 sstep = (snext - s) >> 3; 478 tstep = (tnext - t) >> 3; 479 } 480 else 481 { 482 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so 483 // can't step off polygon), clamp, calculate s and t steps across 484 // span by division, biasing steps low so we don't run off the 485 // texture 486 spancountminus1 = (float)(spancount - 1); 487 sdivz += d_sdivzstepu * spancountminus1; 488 tdivz += d_tdivzstepu * spancountminus1; 489 zi += d_zistepu * spancountminus1; 490 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point 491 snext = (int)(sdivz * z) + sadjust; 492 if (snext > bbextents) 493 snext = bbextents; 494 else if (snext < 8) 495 snext = 8; // prevent round-off error on <0 steps from 496 // from causing overstepping & running off the 497 // edge of the texture 498 499 tnext = (int)(tdivz * z) + tadjust; 500 if (tnext > bbextentt) 501 tnext = bbextentt; 502 else if (tnext < 8) 503 tnext = 8; // guard against round-off error on <0 steps 504 505 if (spancount > 1) 506 { 507 sstep = (snext - s) / (spancount - 1); 508 tstep = (tnext - t) / (spancount - 1); 509 } 510 } 511 512 do 513 { 514 *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); 515 s += sstep; 516 t += tstep; 517 } while (--spancount > 0); 518 519 s = snext; 520 t = tnext; 521 522 } while (count > 0); 523 524 } while ((pspan = pspan->pnext) != NULL); 525 } 526 527 #endif 528 529 530 #if !id386 531 532 /* 533 ============= 534 D_DrawZSpans 535 ============= 536 */ 537 void D_DrawZSpans (espan_t *pspan) 538 { 539 int count, doublecount, izistep; 540 int izi; 541 short *pdest; 542 unsigned ltemp; 543 float zi; 544 float du, dv; 545 546 // FIXME: check for clamping/range problems 547 // we count on FP exceptions being turned off to avoid range problems 548 izistep = (int)(d_zistepu * 0x8000 * 0x10000); 549 550 do 551 { 552 pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; 553 554 count = pspan->count; 555 556 // calculate the initial 1/z 557 du = (float)pspan->u; 558 dv = (float)pspan->v; 559 560 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; 561 // we count on FP exceptions being turned off to avoid range problems 562 izi = (int)(zi * 0x8000 * 0x10000); 563 564 if ((long)pdest & 0x02) 565 { 566 *pdest++ = (short)(izi >> 16); 567 izi += izistep; 568 count--; 569 } 570 571 if ((doublecount = count >> 1) > 0) 572 { 573 do 574 { 575 ltemp = izi >> 16; 576 izi += izistep; 577 ltemp |= izi & 0xFFFF0000; 578 izi += izistep; 579 *(int *)pdest = ltemp; 580 pdest += 2; 581 } while (--doublecount > 0); 582 } 583 584 if (count & 1) 585 *pdest = (short)(izi >> 16); 586 587 } while ((pspan = pspan->pnext) != NULL); 588 } 589 590 #endif 591