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// d_polyset.c: routines for drawing sets of polygons sharing the same 21// texture (used for Alias models) 22 23#include "quakedef.h" 24#include "r_local.h" 25#include "d_local.h" 26 27// TODO: put in span spilling to shrink list size 28// !!! if this is changed, it must be changed in d_polysa.s too !!! 29#define DPS_MAXSPANS MAXHEIGHT+1 30 // 1 extra for spanpackage that marks end 31 32// !!! if this is changed, it must be changed in asm_draw.h too !!! 33typedef struct { 34 void *pdest; 35 short *pz; 36 int count; 37 byte *ptex; 38 int sfrac, tfrac, light, zi; 39} spanpackage_t; 40 41typedef struct { 42 int isflattop; 43 int numleftedges; 44 int *pleftedgevert0; 45 int *pleftedgevert1; 46 int *pleftedgevert2; 47 int numrightedges; 48 int *prightedgevert0; 49 int *prightedgevert1; 50 int *prightedgevert2; 51} edgetable; 52 53int r_p0[6], r_p1[6], r_p2[6]; 54 55byte *d_pcolormap; 56 57int d_aflatcolor; 58int d_xdenom; 59 60edgetable *pedgetable; 61 62edgetable edgetables[12] = { 63 {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, 64 {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, 65 {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, 66 {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, 67 {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, 68 {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, 69 {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, 70 {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, 71 {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, 72 {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, 73 {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, 74 {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, 75}; 76 77// FIXME: some of these can become statics 78int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; 79int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; 80int r_zistepx, r_zistepy; 81int d_aspancount, d_countextrastep; 82 83spanpackage_t *a_spans; 84spanpackage_t *d_pedgespanpackage; 85static int ystart; 86byte *d_pdest, *d_ptex; 87short *d_pz; 88int d_sfrac, d_tfrac, d_light, d_zi; 89int d_ptexextrastep, d_sfracextrastep; 90int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; 91int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; 92int d_sfracbasestep, d_tfracbasestep; 93int d_ziextrastep, d_zibasestep; 94int d_pzextrastep, d_pzbasestep; 95 96typedef struct { 97 int quotient; 98 int remainder; 99} adivtab_t; 100 101static adivtab_t adivtab[32*32] = { 102#include "adivtab.h" 103}; 104 105byte *skintable[MAX_LBM_HEIGHT]; 106int skinwidth; 107byte *skinstart; 108 109void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage); 110void D_PolysetCalcGradients (int skinwidth); 111void D_DrawSubdiv (void); 112void D_DrawNonSubdiv (void); 113void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3); 114void D_PolysetSetEdgeTable (void); 115void D_RasterizeAliasPolySmooth (void); 116void D_PolysetScanLeftEdge (int height); 117 118#if !id386 119 120/* 121================ 122D_PolysetDraw 123================ 124*/ 125void D_PolysetDraw (void) 126{ 127 spanpackage_t spans[DPS_MAXSPANS + 1 + 128 ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1]; 129 // one extra because of cache line pretouching 130 131 a_spans = (spanpackage_t *) 132 (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); 133 134 if (r_affinetridesc.drawtype) 135 { 136 D_DrawSubdiv (); 137 } 138 else 139 { 140 D_DrawNonSubdiv (); 141 } 142} 143 144 145/* 146================ 147D_PolysetDrawFinalVerts 148================ 149*/ 150void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts) 151{ 152 int i, z; 153 short *zbuf; 154 155 for (i=0 ; i<numverts ; i++, fv++) 156 { 157 // valid triangle coordinates for filling can include the bottom and 158 // right clip edges, due to the fill rule; these shouldn't be drawn 159 if ((fv->v[0] < r_refdef.vrectright) && 160 (fv->v[1] < r_refdef.vrectbottom)) 161 { 162 z = fv->v[5]>>16; 163 zbuf = zspantable[fv->v[1]] + fv->v[0]; 164 if (z >= *zbuf) 165 { 166 int pix; 167 168 *zbuf = z; 169 pix = skintable[fv->v[3]>>16][fv->v[2]>>16]; 170 pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ]; 171 d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix; 172 } 173 } 174 } 175} 176 177 178/* 179================ 180D_DrawSubdiv 181================ 182*/ 183void D_DrawSubdiv (void) 184{ 185 mtriangle_t *ptri; 186 finalvert_t *pfv, *index0, *index1, *index2; 187 int i; 188 int lnumtriangles; 189 190 pfv = r_affinetridesc.pfinalverts; 191 ptri = r_affinetridesc.ptriangles; 192 lnumtriangles = r_affinetridesc.numtriangles; 193 194 for (i=0 ; i<lnumtriangles ; i++) 195 { 196 index0 = pfv + ptri[i].vertindex[0]; 197 index1 = pfv + ptri[i].vertindex[1]; 198 index2 = pfv + ptri[i].vertindex[2]; 199 200 if (((index0->v[1]-index1->v[1]) * 201 (index0->v[0]-index2->v[0]) - 202 (index0->v[0]-index1->v[0]) * 203 (index0->v[1]-index2->v[1])) >= 0) 204 { 205 continue; 206 } 207 208 d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00]; 209 210 if (ptri[i].facesfront) 211 { 212 D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); 213 } 214 else 215 { 216 int s0, s1, s2; 217 218 s0 = index0->v[2]; 219 s1 = index1->v[2]; 220 s2 = index2->v[2]; 221 222 if (index0->flags & ALIAS_ONSEAM) 223 index0->v[2] += r_affinetridesc.seamfixupX16; 224 if (index1->flags & ALIAS_ONSEAM) 225 index1->v[2] += r_affinetridesc.seamfixupX16; 226 if (index2->flags & ALIAS_ONSEAM) 227 index2->v[2] += r_affinetridesc.seamfixupX16; 228 229 D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v); 230 231 index0->v[2] = s0; 232 index1->v[2] = s1; 233 index2->v[2] = s2; 234 } 235 } 236} 237 238 239/* 240================ 241D_DrawNonSubdiv 242================ 243*/ 244void D_DrawNonSubdiv (void) 245{ 246 mtriangle_t *ptri; 247 finalvert_t *pfv, *index0, *index1, *index2; 248 int i; 249 int lnumtriangles; 250 251 pfv = r_affinetridesc.pfinalverts; 252 ptri = r_affinetridesc.ptriangles; 253 lnumtriangles = r_affinetridesc.numtriangles; 254 255 for (i=0 ; i<lnumtriangles ; i++, ptri++) 256 { 257 index0 = pfv + ptri->vertindex[0]; 258 index1 = pfv + ptri->vertindex[1]; 259 index2 = pfv + ptri->vertindex[2]; 260 261 d_xdenom = (index0->v[1]-index1->v[1]) * 262 (index0->v[0]-index2->v[0]) - 263 (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]); 264 265 if (d_xdenom >= 0) 266 { 267 continue; 268 } 269 270 r_p0[0] = index0->v[0]; // u 271 r_p0[1] = index0->v[1]; // v 272 r_p0[2] = index0->v[2]; // s 273 r_p0[3] = index0->v[3]; // t 274 r_p0[4] = index0->v[4]; // light 275 r_p0[5] = index0->v[5]; // iz 276 277 r_p1[0] = index1->v[0]; 278 r_p1[1] = index1->v[1]; 279 r_p1[2] = index1->v[2]; 280 r_p1[3] = index1->v[3]; 281 r_p1[4] = index1->v[4]; 282 r_p1[5] = index1->v[5]; 283 284 r_p2[0] = index2->v[0]; 285 r_p2[1] = index2->v[1]; 286 r_p2[2] = index2->v[2]; 287 r_p2[3] = index2->v[3]; 288 r_p2[4] = index2->v[4]; 289 r_p2[5] = index2->v[5]; 290 291 if (!ptri->facesfront) 292 { 293 if (index0->flags & ALIAS_ONSEAM) 294 r_p0[2] += r_affinetridesc.seamfixupX16; 295 if (index1->flags & ALIAS_ONSEAM) 296 r_p1[2] += r_affinetridesc.seamfixupX16; 297 if (index2->flags & ALIAS_ONSEAM) 298 r_p2[2] += r_affinetridesc.seamfixupX16; 299 } 300 301 D_PolysetSetEdgeTable (); 302 D_RasterizeAliasPolySmooth (); 303 } 304} 305 306 307/* 308================ 309D_PolysetRecursiveTriangle 310================ 311*/ 312void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3) 313{ 314 int *temp; 315 int d; 316 int new[6]; 317 int z; 318 short *zbuf; 319 320 d = lp2[0] - lp1[0]; 321 if (d < -1 || d > 1) 322 goto split; 323 d = lp2[1] - lp1[1]; 324 if (d < -1 || d > 1) 325 goto split; 326 327 d = lp3[0] - lp2[0]; 328 if (d < -1 || d > 1) 329 goto split2; 330 d = lp3[1] - lp2[1]; 331 if (d < -1 || d > 1) 332 goto split2; 333 334 d = lp1[0] - lp3[0]; 335 if (d < -1 || d > 1) 336 goto split3; 337 d = lp1[1] - lp3[1]; 338 if (d < -1 || d > 1) 339 { 340split3: 341 temp = lp1; 342 lp1 = lp3; 343 lp3 = lp2; 344 lp2 = temp; 345 346 goto split; 347 } 348 349 return; // entire tri is filled 350 351split2: 352 temp = lp1; 353 lp1 = lp2; 354 lp2 = lp3; 355 lp3 = temp; 356 357split: 358// split this edge 359 new[0] = (lp1[0] + lp2[0]) >> 1; 360 new[1] = (lp1[1] + lp2[1]) >> 1; 361 new[2] = (lp1[2] + lp2[2]) >> 1; 362 new[3] = (lp1[3] + lp2[3]) >> 1; 363 new[5] = (lp1[5] + lp2[5]) >> 1; 364 365// draw the point if splitting a leading edge 366 if (lp2[1] > lp1[1]) 367 goto nodraw; 368 if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0])) 369 goto nodraw; 370 371 372 z = new[5]>>16; 373 zbuf = zspantable[new[1]] + new[0]; 374 if (z >= *zbuf) 375 { 376 int pix; 377 378 *zbuf = z; 379 pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]]; 380 d_viewbuffer[d_scantable[new[1]] + new[0]] = pix; 381 } 382 383nodraw: 384// recursively continue 385 D_PolysetRecursiveTriangle (lp3, lp1, new); 386 D_PolysetRecursiveTriangle (lp3, new, lp2); 387} 388 389#endif // !id386 390 391 392/* 393================ 394D_PolysetUpdateTables 395================ 396*/ 397void D_PolysetUpdateTables (void) 398{ 399 int i; 400 byte *s; 401 402 if (r_affinetridesc.skinwidth != skinwidth || 403 r_affinetridesc.pskin != skinstart) 404 { 405 skinwidth = r_affinetridesc.skinwidth; 406 skinstart = r_affinetridesc.pskin; 407 s = skinstart; 408 for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth) 409 skintable[i] = s; 410 } 411} 412 413 414#if !id386 415 416/* 417=================== 418D_PolysetScanLeftEdge 419==================== 420*/ 421void D_PolysetScanLeftEdge (int height) 422{ 423 424 do 425 { 426 d_pedgespanpackage->pdest = d_pdest; 427 d_pedgespanpackage->pz = d_pz; 428 d_pedgespanpackage->count = d_aspancount; 429 d_pedgespanpackage->ptex = d_ptex; 430 431 d_pedgespanpackage->sfrac = d_sfrac; 432 d_pedgespanpackage->tfrac = d_tfrac; 433 434 // FIXME: need to clamp l, s, t, at both ends? 435 d_pedgespanpackage->light = d_light; 436 d_pedgespanpackage->zi = d_zi; 437 438 d_pedgespanpackage++; 439 440 errorterm += erroradjustup; 441 if (errorterm >= 0) 442 { 443 d_pdest += d_pdestextrastep; 444 d_pz += d_pzextrastep; 445 d_aspancount += d_countextrastep; 446 d_ptex += d_ptexextrastep; 447 d_sfrac += d_sfracextrastep; 448 d_ptex += d_sfrac >> 16; 449 450 d_sfrac &= 0xFFFF; 451 d_tfrac += d_tfracextrastep; 452 if (d_tfrac & 0x10000) 453 { 454 d_ptex += r_affinetridesc.skinwidth; 455 d_tfrac &= 0xFFFF; 456 } 457 d_light += d_lightextrastep; 458 d_zi += d_ziextrastep; 459 errorterm -= erroradjustdown; 460 } 461 else 462 { 463 d_pdest += d_pdestbasestep; 464 d_pz += d_pzbasestep; 465 d_aspancount += ubasestep; 466 d_ptex += d_ptexbasestep; 467 d_sfrac += d_sfracbasestep; 468 d_ptex += d_sfrac >> 16; 469 d_sfrac &= 0xFFFF; 470 d_tfrac += d_tfracbasestep; 471 if (d_tfrac & 0x10000) 472 { 473 d_ptex += r_affinetridesc.skinwidth; 474 d_tfrac &= 0xFFFF; 475 } 476 d_light += d_lightbasestep; 477 d_zi += d_zibasestep; 478 } 479 } while (--height); 480} 481 482#endif // !id386 483 484 485/* 486=================== 487D_PolysetSetUpForLineScan 488==================== 489*/ 490void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, 491 fixed8_t endvertu, fixed8_t endvertv) 492{ 493 double dm, dn; 494 int tm, tn; 495 adivtab_t *ptemp; 496 497// TODO: implement x86 version 498 499 errorterm = -1; 500 501 tm = endvertu - startvertu; 502 tn = endvertv - startvertv; 503 504 if (((tm <= 16) && (tm >= -15)) && 505 ((tn <= 16) && (tn >= -15))) 506 { 507 ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; 508 ubasestep = ptemp->quotient; 509 erroradjustup = ptemp->remainder; 510 erroradjustdown = tn; 511 } 512 else 513 { 514 dm = (double)tm; 515 dn = (double)tn; 516 517 FloorDivMod (dm, dn, &ubasestep, &erroradjustup); 518 519 erroradjustdown = dn; 520 } 521} 522 523 524#if !id386 525 526/* 527================ 528D_PolysetCalcGradients 529================ 530*/ 531void D_PolysetCalcGradients (int skinwidth) 532{ 533 float xstepdenominv, ystepdenominv, t0, t1; 534 float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; 535 536 p00_minus_p20 = r_p0[0] - r_p2[0]; 537 p01_minus_p21 = r_p0[1] - r_p2[1]; 538 p10_minus_p20 = r_p1[0] - r_p2[0]; 539 p11_minus_p21 = r_p1[1] - r_p2[1]; 540 541 xstepdenominv = 1.0 / (float)d_xdenom; 542 543 ystepdenominv = -xstepdenominv; 544 545// ceil () for light so positive steps are exaggerated, negative steps 546// diminished, pushing us away from underflow toward overflow. Underflow is 547// very visible, overflow is very unlikely, because of ambient lighting 548 t0 = r_p0[4] - r_p2[4]; 549 t1 = r_p1[4] - r_p2[4]; 550 r_lstepx = (int) 551 ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); 552 r_lstepy = (int) 553 ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); 554 555 t0 = r_p0[2] - r_p2[2]; 556 t1 = r_p1[2] - r_p2[2]; 557 r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * 558 xstepdenominv); 559 r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * 560 ystepdenominv); 561 562 t0 = r_p0[3] - r_p2[3]; 563 t1 = r_p1[3] - r_p2[3]; 564 r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * 565 xstepdenominv); 566 r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * 567 ystepdenominv); 568 569 t0 = r_p0[5] - r_p2[5]; 570 t1 = r_p1[5] - r_p2[5]; 571 r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * 572 xstepdenominv); 573 r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * 574 ystepdenominv); 575 576#if id386 577 a_sstepxfrac = r_sstepx << 16; 578 a_tstepxfrac = r_tstepx << 16; 579#else 580 a_sstepxfrac = r_sstepx & 0xFFFF; 581 a_tstepxfrac = r_tstepx & 0xFFFF; 582#endif 583 584 a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); 585} 586 587#endif // !id386 588 589 590#if 0 591byte gelmap[256]; 592void InitGel (byte *palette) 593{ 594 int i; 595 int r; 596 597 for (i=0 ; i<256 ; i++) 598 { 599// r = (palette[i*3]>>4); 600 r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3); 601 gelmap[i] = /* 64 */ 0 + r; 602 } 603} 604#endif 605 606 607#if !id386 608 609/* 610================ 611D_PolysetDrawSpans8 612================ 613*/ 614void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage) 615{ 616 int lcount; 617 byte *lpdest; 618 byte *lptex; 619 int lsfrac, ltfrac; 620 int llight; 621 int lzi; 622 short *lpz; 623 624 do 625 { 626 lcount = d_aspancount - pspanpackage->count; 627 628 errorterm += erroradjustup; 629 if (errorterm >= 0) 630 { 631 d_aspancount += d_countextrastep; 632 errorterm -= erroradjustdown; 633 } 634 else 635 { 636 d_aspancount += ubasestep; 637 } 638 639 if (lcount) 640 { 641 lpdest = pspanpackage->pdest; 642 lptex = pspanpackage->ptex; 643 lpz = pspanpackage->pz; 644 lsfrac = pspanpackage->sfrac; 645 ltfrac = pspanpackage->tfrac; 646 llight = pspanpackage->light; 647 lzi = pspanpackage->zi; 648 649 do 650 { 651 if ((lzi >> 16) >= *lpz) 652 { 653 *lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)]; 654// gel mapping *lpdest = gelmap[*lpdest]; 655 *lpz = lzi >> 16; 656 } 657 lpdest++; 658 lzi += r_zistepx; 659 lpz++; 660 llight += r_lstepx; 661 lptex += a_ststepxwhole; 662 lsfrac += a_sstepxfrac; 663 lptex += lsfrac >> 16; 664 lsfrac &= 0xFFFF; 665 ltfrac += a_tstepxfrac; 666 if (ltfrac & 0x10000) 667 { 668 lptex += r_affinetridesc.skinwidth; 669 ltfrac &= 0xFFFF; 670 } 671 } while (--lcount); 672 } 673 674 pspanpackage++; 675 } while (pspanpackage->count != -999999); 676} 677#endif // !id386 678 679 680/* 681================ 682D_PolysetFillSpans8 683================ 684*/ 685void D_PolysetFillSpans8 (spanpackage_t *pspanpackage) 686{ 687 int color; 688 689// FIXME: do z buffering 690 691 color = d_aflatcolor++; 692 693 while (1) 694 { 695 int lcount; 696 byte *lpdest; 697 698 lcount = pspanpackage->count; 699 700 if (lcount == -1) 701 return; 702 703 if (lcount) 704 { 705 lpdest = pspanpackage->pdest; 706 707 do 708 { 709 *lpdest++ = color; 710 } while (--lcount); 711 } 712 713 pspanpackage++; 714 } 715} 716 717/* 718================ 719D_RasterizeAliasPolySmooth 720================ 721*/ 722void D_RasterizeAliasPolySmooth (void) 723{ 724 int initialleftheight, initialrightheight; 725 int *plefttop, *prighttop, *pleftbottom, *prightbottom; 726 int working_lstepx, originalcount; 727 728 plefttop = pedgetable->pleftedgevert0; 729 prighttop = pedgetable->prightedgevert0; 730 731 pleftbottom = pedgetable->pleftedgevert1; 732 prightbottom = pedgetable->prightedgevert1; 733 734 initialleftheight = pleftbottom[1] - plefttop[1]; 735 initialrightheight = prightbottom[1] - prighttop[1]; 736 737// 738// set the s, t, and light gradients, which are consistent across the triangle 739// because being a triangle, things are affine 740// 741 D_PolysetCalcGradients (r_affinetridesc.skinwidth); 742 743// 744// rasterize the polygon 745// 746 747// 748// scan out the top (and possibly only) part of the left edge 749// 750 d_pedgespanpackage = a_spans; 751 752 ystart = plefttop[1]; 753 d_aspancount = plefttop[0] - prighttop[0]; 754 755 d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + 756 (plefttop[3] >> 16) * r_affinetridesc.skinwidth; 757#if id386 758 d_sfrac = (plefttop[2] & 0xFFFF) << 16; 759 d_tfrac = (plefttop[3] & 0xFFFF) << 16; 760#else 761 d_sfrac = plefttop[2] & 0xFFFF; 762 d_tfrac = plefttop[3] & 0xFFFF; 763#endif 764 d_light = plefttop[4]; 765 d_zi = plefttop[5]; 766 767 d_pdest = (byte *)d_viewbuffer + 768 ystart * screenwidth + plefttop[0]; 769 d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; 770 771 if (initialleftheight == 1) 772 { 773 d_pedgespanpackage->pdest = d_pdest; 774 d_pedgespanpackage->pz = d_pz; 775 d_pedgespanpackage->count = d_aspancount; 776 d_pedgespanpackage->ptex = d_ptex; 777 778 d_pedgespanpackage->sfrac = d_sfrac; 779 d_pedgespanpackage->tfrac = d_tfrac; 780 781 // FIXME: need to clamp l, s, t, at both ends? 782 d_pedgespanpackage->light = d_light; 783 d_pedgespanpackage->zi = d_zi; 784 785 d_pedgespanpackage++; 786 } 787 else 788 { 789 D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], 790 pleftbottom[0], pleftbottom[1]); 791 792 #if id386 793 d_pzbasestep = (d_zwidth + ubasestep) << 1; 794 d_pzextrastep = d_pzbasestep + 2; 795 #else 796 d_pzbasestep = d_zwidth + ubasestep; 797 d_pzextrastep = d_pzbasestep + 1; 798 #endif 799 800 d_pdestbasestep = screenwidth + ubasestep; 801 d_pdestextrastep = d_pdestbasestep + 1; 802 803 // TODO: can reuse partial expressions here 804 805 // for negative steps in x along left edge, bias toward overflow rather than 806 // underflow (sort of turning the floor () we did in the gradient calcs into 807 // ceil (), but plus a little bit) 808 if (ubasestep < 0) 809 working_lstepx = r_lstepx - 1; 810 else 811 working_lstepx = r_lstepx; 812 813 d_countextrastep = ubasestep + 1; 814 d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + 815 ((r_tstepy + r_tstepx * ubasestep) >> 16) * 816 r_affinetridesc.skinwidth; 817 #if id386 818 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; 819 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; 820 #else 821 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; 822 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; 823 #endif 824 d_lightbasestep = r_lstepy + working_lstepx * ubasestep; 825 d_zibasestep = r_zistepy + r_zistepx * ubasestep; 826 827 d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + 828 ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * 829 r_affinetridesc.skinwidth; 830 #if id386 831 d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; 832 d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; 833 #else 834 d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; 835 d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; 836 #endif 837 d_lightextrastep = d_lightbasestep + working_lstepx; 838 d_ziextrastep = d_zibasestep + r_zistepx; 839 840 D_PolysetScanLeftEdge (initialleftheight); 841 } 842 843// 844// scan out the bottom part of the left edge, if it exists 845// 846 if (pedgetable->numleftedges == 2) 847 { 848 int height; 849 850 plefttop = pleftbottom; 851 pleftbottom = pedgetable->pleftedgevert2; 852 853 height = pleftbottom[1] - plefttop[1]; 854 855// TODO: make this a function; modularize this function in general 856 857 ystart = plefttop[1]; 858 d_aspancount = plefttop[0] - prighttop[0]; 859 d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + 860 (plefttop[3] >> 16) * r_affinetridesc.skinwidth; 861 d_sfrac = 0; 862 d_tfrac = 0; 863 d_light = plefttop[4]; 864 d_zi = plefttop[5]; 865 866 d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0]; 867 d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; 868 869 if (height == 1) 870 { 871 d_pedgespanpackage->pdest = d_pdest; 872 d_pedgespanpackage->pz = d_pz; 873 d_pedgespanpackage->count = d_aspancount; 874 d_pedgespanpackage->ptex = d_ptex; 875 876 d_pedgespanpackage->sfrac = d_sfrac; 877 d_pedgespanpackage->tfrac = d_tfrac; 878 879 // FIXME: need to clamp l, s, t, at both ends? 880 d_pedgespanpackage->light = d_light; 881 d_pedgespanpackage->zi = d_zi; 882 883 d_pedgespanpackage++; 884 } 885 else 886 { 887 D_PolysetSetUpForLineScan(plefttop[0], plefttop[1], 888 pleftbottom[0], pleftbottom[1]); 889 890 d_pdestbasestep = screenwidth + ubasestep; 891 d_pdestextrastep = d_pdestbasestep + 1; 892 893 #if id386 894 d_pzbasestep = (d_zwidth + ubasestep) << 1; 895 d_pzextrastep = d_pzbasestep + 2; 896 #else 897 d_pzbasestep = d_zwidth + ubasestep; 898 d_pzextrastep = d_pzbasestep + 1; 899 #endif 900 901 if (ubasestep < 0) 902 working_lstepx = r_lstepx - 1; 903 else 904 working_lstepx = r_lstepx; 905 906 d_countextrastep = ubasestep + 1; 907 d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + 908 ((r_tstepy + r_tstepx * ubasestep) >> 16) * 909 r_affinetridesc.skinwidth; 910 #if id386 911 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; 912 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; 913 #else 914 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; 915 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; 916 #endif 917 d_lightbasestep = r_lstepy + working_lstepx * ubasestep; 918 d_zibasestep = r_zistepy + r_zistepx * ubasestep; 919 920 d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + 921 ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * 922 r_affinetridesc.skinwidth; 923 #if id386 924 d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; 925 d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; 926 #else 927 d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; 928 d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; 929 #endif 930 d_lightextrastep = d_lightbasestep + working_lstepx; 931 d_ziextrastep = d_zibasestep + r_zistepx; 932 933 D_PolysetScanLeftEdge (height); 934 } 935 } 936 937// scan out the top (and possibly only) part of the right edge, updating the 938// count field 939 d_pedgespanpackage = a_spans; 940 941 D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], 942 prightbottom[0], prightbottom[1]); 943 d_aspancount = 0; 944 d_countextrastep = ubasestep + 1; 945 originalcount = a_spans[initialrightheight].count; 946 a_spans[initialrightheight].count = -999999; // mark end of the spanpackages 947 D_PolysetDrawSpans8 (a_spans); 948 949// scan out the bottom part of the right edge, if it exists 950 if (pedgetable->numrightedges == 2) 951 { 952 int height; 953 spanpackage_t *pstart; 954 955 pstart = a_spans + initialrightheight; 956 pstart->count = originalcount; 957 958 d_aspancount = prightbottom[0] - prighttop[0]; 959 960 prighttop = prightbottom; 961 prightbottom = pedgetable->prightedgevert2; 962 963 height = prightbottom[1] - prighttop[1]; 964 965 D_PolysetSetUpForLineScan(prighttop[0], prighttop[1], 966 prightbottom[0], prightbottom[1]); 967 968 d_countextrastep = ubasestep + 1; 969 a_spans[initialrightheight + height].count = -999999; 970 // mark end of the spanpackages 971 D_PolysetDrawSpans8 (pstart); 972 } 973} 974 975 976/* 977================ 978D_PolysetSetEdgeTable 979================ 980*/ 981void D_PolysetSetEdgeTable (void) 982{ 983 int edgetableindex; 984 985 edgetableindex = 0; // assume the vertices are already in 986 // top to bottom order 987 988// 989// determine which edges are right & left, and the order in which 990// to rasterize them 991// 992 if (r_p0[1] >= r_p1[1]) 993 { 994 if (r_p0[1] == r_p1[1]) 995 { 996 if (r_p0[1] < r_p2[1]) 997 pedgetable = &edgetables[2]; 998 else 999 pedgetable = &edgetables[5]; 1000 1001 return; 1002 } 1003 else 1004 { 1005 edgetableindex = 1; 1006 } 1007 } 1008 1009 if (r_p0[1] == r_p2[1]) 1010 { 1011 if (edgetableindex) 1012 pedgetable = &edgetables[8]; 1013 else 1014 pedgetable = &edgetables[9]; 1015 1016 return; 1017 } 1018 else if (r_p1[1] == r_p2[1]) 1019 { 1020 if (edgetableindex) 1021 pedgetable = &edgetables[10]; 1022 else 1023 pedgetable = &edgetables[11]; 1024 1025 return; 1026 } 1027 1028 if (r_p0[1] > r_p2[1]) 1029 edgetableindex += 2; 1030 1031 if (r_p1[1] > r_p2[1]) 1032 edgetableindex += 4; 1033 1034 pedgetable = &edgetables[edgetableindex]; 1035} 1036 1037 1038#if 0 1039 1040void D_PolysetRecursiveDrawLine (int *lp1, int *lp2) 1041{ 1042 int d; 1043 int new[6]; 1044 int ofs; 1045 1046 d = lp2[0] - lp1[0]; 1047 if (d < -1 || d > 1) 1048 goto split; 1049 d = lp2[1] - lp1[1]; 1050 if (d < -1 || d > 1) 1051 goto split; 1052 1053 return; // line is completed 1054 1055split: 1056// split this edge 1057 new[0] = (lp1[0] + lp2[0]) >> 1; 1058 new[1] = (lp1[1] + lp2[1]) >> 1; 1059 new[5] = (lp1[5] + lp2[5]) >> 1; 1060 new[2] = (lp1[2] + lp2[2]) >> 1; 1061 new[3] = (lp1[3] + lp2[3]) >> 1; 1062 new[4] = (lp1[4] + lp2[4]) >> 1; 1063 1064// draw the point 1065 ofs = d_scantable[new[1]] + new[0]; 1066 if (new[5] > d_pzbuffer[ofs]) 1067 { 1068 int pix; 1069 1070 d_pzbuffer[ofs] = new[5]; 1071 pix = skintable[new[3]>>16][new[2]>>16]; 1072// pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)]; 1073 d_viewbuffer[ofs] = pix; 1074 } 1075 1076// recursively continue 1077 D_PolysetRecursiveDrawLine (lp1, new); 1078 D_PolysetRecursiveDrawLine (new, lp2); 1079} 1080 1081void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3) 1082{ 1083 int d; 1084 int new[4]; 1085 1086 d = lp2[0] - lp1[0]; 1087 if (d < -1 || d > 1) 1088 goto split; 1089 d = lp2[1] - lp1[1]; 1090 if (d < -1 || d > 1) 1091 goto split; 1092 return; 1093 1094split: 1095// split this edge 1096 new[0] = (lp1[0] + lp2[0]) >> 1; 1097 new[1] = (lp1[1] + lp2[1]) >> 1; 1098 new[5] = (lp1[5] + lp2[5]) >> 1; 1099 new[2] = (lp1[2] + lp2[2]) >> 1; 1100 new[3] = (lp1[3] + lp2[3]) >> 1; 1101 new[4] = (lp1[4] + lp2[4]) >> 1; 1102 1103 D_PolysetRecursiveDrawLine (new, lp3); 1104 1105// recursively continue 1106 D_PolysetRecursiveTriangle (lp1, new, lp3); 1107 D_PolysetRecursiveTriangle (new, lp2, lp3); 1108} 1109 1110#endif 1111 1112