|
|
1.1 ! root 1: // r_edge.c ! 2: ! 3: #include "r_local.h" ! 4: ! 5: #ifndef id386 ! 6: void R_SurfacePatch (void) ! 7: { ! 8: } ! 9: ! 10: void R_EdgeCodeStart (void) ! 11: { ! 12: } ! 13: ! 14: void R_EdgeCodeEnd (void) ! 15: { ! 16: } ! 17: #endif ! 18: ! 19: ! 20: #if 0 ! 21: the complex cases add new polys on most lines, so dont optimize for keeping them the same ! 22: have multiple free span lists to try to get better coherence? ! 23: low depth complexity -- 1 to 3 or so ! 24: ! 25: have a sentinal at both ends? ! 26: #endif ! 27: ! 28: ! 29: edge_t *auxedges; ! 30: edge_t *r_edges, *edge_p, *edge_max; ! 31: ! 32: surf_t *surfaces, *surface_p, *surf_max; ! 33: ! 34: // surfaces are generated in back to front order by the bsp, so if a surf ! 35: // pointer is greater than another one, it should be drawn in front ! 36: // surfaces[1] is the background, and is used as the active surface stack ! 37: ! 38: edge_t *newedges[MAXHEIGHT]; ! 39: edge_t *removeedges[MAXHEIGHT]; ! 40: ! 41: espan_t *span_p, *max_span_p; ! 42: ! 43: int r_currentkey; ! 44: ! 45: int current_iv; ! 46: ! 47: int edge_head_u_shift20, edge_tail_u_shift20; ! 48: ! 49: static void (*pdrawfunc)(void); ! 50: ! 51: edge_t edge_head; ! 52: edge_t edge_tail; ! 53: edge_t edge_aftertail; ! 54: edge_t edge_sentinel; ! 55: ! 56: float fv; ! 57: ! 58: static int miplevel; ! 59: ! 60: float scale_for_mip; ! 61: int ubasestep, errorterm, erroradjustup, erroradjustdown; ! 62: ! 63: // FIXME: should go away ! 64: extern void R_RotateBmodel (void); ! 65: extern void R_TransformFrustum (void); ! 66: ! 67: ! 68: ! 69: void R_GenerateSpans (void); ! 70: void R_GenerateSpansBackward (void); ! 71: ! 72: void R_LeadingEdge (edge_t *edge); ! 73: void R_LeadingEdgeBackwards (edge_t *edge); ! 74: void R_TrailingEdge (surf_t *surf, edge_t *edge); ! 75: ! 76: ! 77: /* ! 78: =============================================================================== ! 79: ! 80: EDGE SCANNING ! 81: ! 82: =============================================================================== ! 83: */ ! 84: ! 85: /* ! 86: ============== ! 87: R_BeginEdgeFrame ! 88: ============== ! 89: */ ! 90: void R_BeginEdgeFrame (void) ! 91: { ! 92: int v; ! 93: ! 94: edge_p = r_edges; ! 95: edge_max = &r_edges[r_numallocatededges]; ! 96: ! 97: surface_p = &surfaces[2]; // background is surface 1, ! 98: // surface 0 is a dummy ! 99: surfaces[1].spans = NULL; // no background spans yet ! 100: surfaces[1].flags = SURF_DRAWBACKGROUND; ! 101: ! 102: // put the background behind everything in the world ! 103: if (sw_draworder->value) ! 104: { ! 105: pdrawfunc = R_GenerateSpansBackward; ! 106: surfaces[1].key = 0; ! 107: r_currentkey = 1; ! 108: } ! 109: else ! 110: { ! 111: pdrawfunc = R_GenerateSpans; ! 112: surfaces[1].key = 0x7FFfFFFF; ! 113: r_currentkey = 0; ! 114: } ! 115: ! 116: // FIXME: set with memset ! 117: for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++) ! 118: { ! 119: newedges[v] = removeedges[v] = NULL; ! 120: } ! 121: } ! 122: ! 123: ! 124: #if !id386 ! 125: ! 126: /* ! 127: ============== ! 128: R_InsertNewEdges ! 129: ! 130: Adds the edges in the linked list edgestoadd, adding them to the edges in the ! 131: linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a ! 132: sentinel at the end (actually, this is the active edge table starting at ! 133: edge_head.next). ! 134: ============== ! 135: */ ! 136: void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) ! 137: { ! 138: edge_t *next_edge; ! 139: ! 140: do ! 141: { ! 142: next_edge = edgestoadd->next; ! 143: edgesearch: ! 144: if (edgelist->u >= edgestoadd->u) ! 145: goto addedge; ! 146: edgelist=edgelist->next; ! 147: if (edgelist->u >= edgestoadd->u) ! 148: goto addedge; ! 149: edgelist=edgelist->next; ! 150: if (edgelist->u >= edgestoadd->u) ! 151: goto addedge; ! 152: edgelist=edgelist->next; ! 153: if (edgelist->u >= edgestoadd->u) ! 154: goto addedge; ! 155: edgelist=edgelist->next; ! 156: goto edgesearch; ! 157: ! 158: // insert edgestoadd before edgelist ! 159: addedge: ! 160: edgestoadd->next = edgelist; ! 161: edgestoadd->prev = edgelist->prev; ! 162: edgelist->prev->next = edgestoadd; ! 163: edgelist->prev = edgestoadd; ! 164: } while ((edgestoadd = next_edge) != NULL); ! 165: } ! 166: ! 167: #endif // !id386 ! 168: ! 169: ! 170: #if !id386 ! 171: ! 172: /* ! 173: ============== ! 174: R_RemoveEdges ! 175: ============== ! 176: */ ! 177: void R_RemoveEdges (edge_t *pedge) ! 178: { ! 179: ! 180: do ! 181: { ! 182: pedge->next->prev = pedge->prev; ! 183: pedge->prev->next = pedge->next; ! 184: } while ((pedge = pedge->nextremove) != NULL); ! 185: } ! 186: ! 187: #endif // !id386 ! 188: ! 189: ! 190: #if !id386 ! 191: ! 192: /* ! 193: ============== ! 194: R_StepActiveU ! 195: ============== ! 196: */ ! 197: void R_StepActiveU (edge_t *pedge) ! 198: { ! 199: edge_t *pnext_edge, *pwedge; ! 200: ! 201: while (1) ! 202: { ! 203: nextedge: ! 204: pedge->u += pedge->u_step; ! 205: if (pedge->u < pedge->prev->u) ! 206: goto pushback; ! 207: pedge = pedge->next; ! 208: ! 209: pedge->u += pedge->u_step; ! 210: if (pedge->u < pedge->prev->u) ! 211: goto pushback; ! 212: pedge = pedge->next; ! 213: ! 214: pedge->u += pedge->u_step; ! 215: if (pedge->u < pedge->prev->u) ! 216: goto pushback; ! 217: pedge = pedge->next; ! 218: ! 219: pedge->u += pedge->u_step; ! 220: if (pedge->u < pedge->prev->u) ! 221: goto pushback; ! 222: pedge = pedge->next; ! 223: ! 224: goto nextedge; ! 225: ! 226: pushback: ! 227: if (pedge == &edge_aftertail) ! 228: return; ! 229: ! 230: // push it back to keep it sorted ! 231: pnext_edge = pedge->next; ! 232: ! 233: // pull the edge out of the edge list ! 234: pedge->next->prev = pedge->prev; ! 235: pedge->prev->next = pedge->next; ! 236: ! 237: // find out where the edge goes in the edge list ! 238: pwedge = pedge->prev->prev; ! 239: ! 240: while (pwedge->u > pedge->u) ! 241: { ! 242: pwedge = pwedge->prev; ! 243: } ! 244: ! 245: // put the edge back into the edge list ! 246: pedge->next = pwedge->next; ! 247: pedge->prev = pwedge; ! 248: pedge->next->prev = pedge; ! 249: pwedge->next = pedge; ! 250: ! 251: pedge = pnext_edge; ! 252: if (pedge == &edge_tail) ! 253: return; ! 254: } ! 255: } ! 256: ! 257: #endif // !id386 ! 258: ! 259: ! 260: /* ! 261: ============== ! 262: R_CleanupSpan ! 263: ============== ! 264: */ ! 265: void R_CleanupSpan (void) ! 266: { ! 267: surf_t *surf; ! 268: int iu; ! 269: espan_t *span; ! 270: ! 271: // now that we've reached the right edge of the screen, we're done with any ! 272: // unfinished surfaces, so emit a span for whatever's on top ! 273: surf = surfaces[1].next; ! 274: iu = edge_tail_u_shift20; ! 275: if (iu > surf->last_u) ! 276: { ! 277: span = span_p++; ! 278: span->u = surf->last_u; ! 279: span->count = iu - span->u; ! 280: span->v = current_iv; ! 281: span->pnext = surf->spans; ! 282: surf->spans = span; ! 283: } ! 284: ! 285: // reset spanstate for all surfaces in the surface stack ! 286: do ! 287: { ! 288: surf->spanstate = 0; ! 289: surf = surf->next; ! 290: } while (surf != &surfaces[1]); ! 291: } ! 292: ! 293: ! 294: /* ! 295: ============== ! 296: R_LeadingEdgeBackwards ! 297: ============== ! 298: */ ! 299: void R_LeadingEdgeBackwards (edge_t *edge) ! 300: { ! 301: espan_t *span; ! 302: surf_t *surf, *surf2; ! 303: int iu; ! 304: ! 305: // it's adding a new surface in, so find the correct place ! 306: surf = &surfaces[edge->surfs[1]]; ! 307: ! 308: // don't start a span if this is an inverted span, with the end ! 309: // edge preceding the start edge (that is, we've already seen the ! 310: // end edge) ! 311: if (++surf->spanstate == 1) ! 312: { ! 313: surf2 = surfaces[1].next; ! 314: ! 315: if (surf->key > surf2->key) ! 316: goto newtop; ! 317: ! 318: // if it's two surfaces on the same plane, the one that's already ! 319: // active is in front, so keep going unless it's a bmodel ! 320: if (surf->insubmodel && (surf->key == surf2->key)) ! 321: { ! 322: // must be two bmodels in the same leaf; don't care, because they'll ! 323: // never be farthest anyway ! 324: goto newtop; ! 325: } ! 326: ! 327: continue_search: ! 328: ! 329: do ! 330: { ! 331: surf2 = surf2->next; ! 332: } while (surf->key < surf2->key); ! 333: ! 334: if (surf->key == surf2->key) ! 335: { ! 336: // if it's two surfaces on the same plane, the one that's already ! 337: // active is in front, so keep going unless it's a bmodel ! 338: if (!surf->insubmodel) ! 339: goto continue_search; ! 340: ! 341: // must be two bmodels in the same leaf; don't care which is really ! 342: // in front, because they'll never be farthest anyway ! 343: } ! 344: ! 345: goto gotposition; ! 346: ! 347: newtop: ! 348: // emit a span (obscures current top) ! 349: iu = edge->u >> 20; ! 350: ! 351: if (iu > surf2->last_u) ! 352: { ! 353: span = span_p++; ! 354: span->u = surf2->last_u; ! 355: span->count = iu - span->u; ! 356: span->v = current_iv; ! 357: span->pnext = surf2->spans; ! 358: surf2->spans = span; ! 359: } ! 360: ! 361: // set last_u on the new span ! 362: surf->last_u = iu; ! 363: ! 364: gotposition: ! 365: // insert before surf2 ! 366: surf->next = surf2; ! 367: surf->prev = surf2->prev; ! 368: surf2->prev->next = surf; ! 369: surf2->prev = surf; ! 370: } ! 371: } ! 372: ! 373: ! 374: /* ! 375: ============== ! 376: R_TrailingEdge ! 377: ============== ! 378: */ ! 379: void R_TrailingEdge (surf_t *surf, edge_t *edge) ! 380: { ! 381: espan_t *span; ! 382: int iu; ! 383: ! 384: // don't generate a span if this is an inverted span, with the end ! 385: // edge preceding the start edge (that is, we haven't seen the ! 386: // start edge yet) ! 387: if (--surf->spanstate == 0) ! 388: { ! 389: if (surf == surfaces[1].next) ! 390: { ! 391: // emit a span (current top going away) ! 392: iu = edge->u >> 20; ! 393: if (iu > surf->last_u) ! 394: { ! 395: span = span_p++; ! 396: span->u = surf->last_u; ! 397: span->count = iu - span->u; ! 398: span->v = current_iv; ! 399: span->pnext = surf->spans; ! 400: surf->spans = span; ! 401: } ! 402: ! 403: // set last_u on the surface below ! 404: surf->next->last_u = iu; ! 405: } ! 406: ! 407: surf->prev->next = surf->next; ! 408: surf->next->prev = surf->prev; ! 409: } ! 410: } ! 411: ! 412: ! 413: #if !id386 ! 414: ! 415: /* ! 416: ============== ! 417: R_LeadingEdge ! 418: ============== ! 419: */ ! 420: void R_LeadingEdge (edge_t *edge) ! 421: { ! 422: espan_t *span; ! 423: surf_t *surf, *surf2; ! 424: int iu; ! 425: float fu, newzi, testzi, newzitop, newzibottom; ! 426: ! 427: if (edge->surfs[1]) ! 428: { ! 429: // it's adding a new surface in, so find the correct place ! 430: surf = &surfaces[edge->surfs[1]]; ! 431: ! 432: // don't start a span if this is an inverted span, with the end ! 433: // edge preceding the start edge (that is, we've already seen the ! 434: // end edge) ! 435: if (++surf->spanstate == 1) ! 436: { ! 437: surf2 = surfaces[1].next; ! 438: ! 439: if (surf->key < surf2->key) ! 440: goto newtop; ! 441: ! 442: // if it's two surfaces on the same plane, the one that's already ! 443: // active is in front, so keep going unless it's a bmodel ! 444: if (surf->insubmodel && (surf->key == surf2->key)) ! 445: { ! 446: // must be two bmodels in the same leaf; sort on 1/z ! 447: fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); ! 448: newzi = surf->d_ziorigin + fv*surf->d_zistepv + ! 449: fu*surf->d_zistepu; ! 450: newzibottom = newzi * 0.99; ! 451: ! 452: testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + ! 453: fu*surf2->d_zistepu; ! 454: ! 455: if (newzibottom >= testzi) ! 456: { ! 457: goto newtop; ! 458: } ! 459: ! 460: newzitop = newzi * 1.01; ! 461: if (newzitop >= testzi) ! 462: { ! 463: if (surf->d_zistepu >= surf2->d_zistepu) ! 464: { ! 465: goto newtop; ! 466: } ! 467: } ! 468: } ! 469: ! 470: continue_search: ! 471: ! 472: do ! 473: { ! 474: surf2 = surf2->next; ! 475: } while (surf->key > surf2->key); ! 476: ! 477: if (surf->key == surf2->key) ! 478: { ! 479: // if it's two surfaces on the same plane, the one that's already ! 480: // active is in front, so keep going unless it's a bmodel ! 481: if (!surf->insubmodel) ! 482: goto continue_search; ! 483: ! 484: // must be two bmodels in the same leaf; sort on 1/z ! 485: fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); ! 486: newzi = surf->d_ziorigin + fv*surf->d_zistepv + ! 487: fu*surf->d_zistepu; ! 488: newzibottom = newzi * 0.99; ! 489: ! 490: testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + ! 491: fu*surf2->d_zistepu; ! 492: ! 493: if (newzibottom >= testzi) ! 494: { ! 495: goto gotposition; ! 496: } ! 497: ! 498: newzitop = newzi * 1.01; ! 499: if (newzitop >= testzi) ! 500: { ! 501: if (surf->d_zistepu >= surf2->d_zistepu) ! 502: { ! 503: goto gotposition; ! 504: } ! 505: } ! 506: ! 507: goto continue_search; ! 508: } ! 509: ! 510: goto gotposition; ! 511: ! 512: newtop: ! 513: // emit a span (obscures current top) ! 514: iu = edge->u >> 20; ! 515: ! 516: if (iu > surf2->last_u) ! 517: { ! 518: span = span_p++; ! 519: span->u = surf2->last_u; ! 520: span->count = iu - span->u; ! 521: span->v = current_iv; ! 522: span->pnext = surf2->spans; ! 523: surf2->spans = span; ! 524: } ! 525: ! 526: // set last_u on the new span ! 527: surf->last_u = iu; ! 528: ! 529: gotposition: ! 530: // insert before surf2 ! 531: surf->next = surf2; ! 532: surf->prev = surf2->prev; ! 533: surf2->prev->next = surf; ! 534: surf2->prev = surf; ! 535: } ! 536: } ! 537: } ! 538: ! 539: ! 540: /* ! 541: ============== ! 542: R_GenerateSpans ! 543: ============== ! 544: */ ! 545: void R_GenerateSpans (void) ! 546: { ! 547: edge_t *edge; ! 548: surf_t *surf; ! 549: ! 550: // clear active surfaces to just the background surface ! 551: surfaces[1].next = surfaces[1].prev = &surfaces[1]; ! 552: surfaces[1].last_u = edge_head_u_shift20; ! 553: ! 554: // generate spans ! 555: for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) ! 556: { ! 557: if (edge->surfs[0]) ! 558: { ! 559: // it has a left surface, so a surface is going away for this span ! 560: surf = &surfaces[edge->surfs[0]]; ! 561: ! 562: R_TrailingEdge (surf, edge); ! 563: ! 564: if (!edge->surfs[1]) ! 565: continue; ! 566: } ! 567: ! 568: R_LeadingEdge (edge); ! 569: } ! 570: ! 571: R_CleanupSpan (); ! 572: } ! 573: ! 574: #endif // !id386 ! 575: ! 576: ! 577: /* ! 578: ============== ! 579: R_GenerateSpansBackward ! 580: ============== ! 581: */ ! 582: void R_GenerateSpansBackward (void) ! 583: { ! 584: edge_t *edge; ! 585: ! 586: // clear active surfaces to just the background surface ! 587: surfaces[1].next = surfaces[1].prev = &surfaces[1]; ! 588: surfaces[1].last_u = edge_head_u_shift20; ! 589: ! 590: // generate spans ! 591: for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) ! 592: { ! 593: if (edge->surfs[0]) ! 594: R_TrailingEdge (&surfaces[edge->surfs[0]], edge); ! 595: ! 596: if (edge->surfs[1]) ! 597: R_LeadingEdgeBackwards (edge); ! 598: } ! 599: ! 600: R_CleanupSpan (); ! 601: } ! 602: ! 603: ! 604: /* ! 605: ============== ! 606: R_ScanEdges ! 607: ! 608: Input: ! 609: newedges[] array ! 610: this has links to edges, which have links to surfaces ! 611: ! 612: Output: ! 613: Each surface has a linked list of its visible spans ! 614: ============== ! 615: */ ! 616: void R_ScanEdges (void) ! 617: { ! 618: int iv, bottom; ! 619: byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE]; ! 620: espan_t *basespan_p; ! 621: surf_t *s; ! 622: ! 623: basespan_p = (espan_t *) ! 624: ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); ! 625: max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; ! 626: ! 627: span_p = basespan_p; ! 628: ! 629: // clear active edges to just the background edges around the whole screen ! 630: // FIXME: most of this only needs to be set up once ! 631: edge_head.u = r_refdef.vrect.x << 20; ! 632: edge_head_u_shift20 = edge_head.u >> 20; ! 633: edge_head.u_step = 0; ! 634: edge_head.prev = NULL; ! 635: edge_head.next = &edge_tail; ! 636: edge_head.surfs[0] = 0; ! 637: edge_head.surfs[1] = 1; ! 638: ! 639: edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; ! 640: edge_tail_u_shift20 = edge_tail.u >> 20; ! 641: edge_tail.u_step = 0; ! 642: edge_tail.prev = &edge_head; ! 643: edge_tail.next = &edge_aftertail; ! 644: edge_tail.surfs[0] = 1; ! 645: edge_tail.surfs[1] = 0; ! 646: ! 647: edge_aftertail.u = -1; // force a move ! 648: edge_aftertail.u_step = 0; ! 649: edge_aftertail.next = &edge_sentinel; ! 650: edge_aftertail.prev = &edge_tail; ! 651: ! 652: // FIXME: do we need this now that we clamp x in r_draw.c? ! 653: edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this ! 654: edge_sentinel.prev = &edge_aftertail; ! 655: ! 656: // ! 657: // process all scan lines ! 658: // ! 659: bottom = r_refdef.vrectbottom - 1; ! 660: ! 661: for (iv=r_refdef.vrect.y ; iv<bottom ; iv++) ! 662: { ! 663: current_iv = iv; ! 664: fv = (float)iv; ! 665: ! 666: // mark that the head (background start) span is pre-included ! 667: surfaces[1].spanstate = 1; ! 668: ! 669: if (newedges[iv]) ! 670: { ! 671: R_InsertNewEdges (newedges[iv], edge_head.next); ! 672: } ! 673: ! 674: (*pdrawfunc) (); ! 675: ! 676: // flush the span list if we can't be sure we have enough spans left for ! 677: // the next scan ! 678: if (span_p > max_span_p) ! 679: { ! 680: D_DrawSurfaces (); ! 681: ! 682: // clear the surface span pointers ! 683: for (s = &surfaces[1] ; s<surface_p ; s++) ! 684: s->spans = NULL; ! 685: ! 686: span_p = basespan_p; ! 687: } ! 688: ! 689: if (removeedges[iv]) ! 690: R_RemoveEdges (removeedges[iv]); ! 691: ! 692: if (edge_head.next != &edge_tail) ! 693: R_StepActiveU (edge_head.next); ! 694: } ! 695: ! 696: // do the last scan (no need to step or sort or remove on the last scan) ! 697: ! 698: current_iv = iv; ! 699: fv = (float)iv; ! 700: ! 701: // mark that the head (background start) span is pre-included ! 702: surfaces[1].spanstate = 1; ! 703: ! 704: if (newedges[iv]) ! 705: R_InsertNewEdges (newedges[iv], edge_head.next); ! 706: ! 707: (*pdrawfunc) (); ! 708: ! 709: // draw whatever's left in the span list ! 710: D_DrawSurfaces (); ! 711: } ! 712: ! 713: ! 714: /* ! 715: ========================================================================= ! 716: ! 717: SURFACE FILLING ! 718: ! 719: ========================================================================= ! 720: */ ! 721: ! 722: msurface_t *pface; ! 723: surfcache_t *pcurrentcache; ! 724: vec3_t transformed_modelorg; ! 725: vec3_t world_transformed_modelorg; ! 726: vec3_t local_modelorg; ! 727: ! 728: /* ! 729: ============= ! 730: D_MipLevelForScale ! 731: ============= ! 732: */ ! 733: int D_MipLevelForScale (float scale) ! 734: { ! 735: int lmiplevel; ! 736: ! 737: if (scale >= d_scalemip[0] ) ! 738: lmiplevel = 0; ! 739: else if (scale >= d_scalemip[1] ) ! 740: lmiplevel = 1; ! 741: else if (scale >= d_scalemip[2] ) ! 742: lmiplevel = 2; ! 743: else ! 744: lmiplevel = 3; ! 745: ! 746: if (lmiplevel < d_minmip) ! 747: lmiplevel = d_minmip; ! 748: ! 749: return lmiplevel; ! 750: } ! 751: ! 752: ! 753: /* ! 754: ============== ! 755: D_FlatFillSurface ! 756: ! 757: Simple single color fill with no texture mapping ! 758: ============== ! 759: */ ! 760: void D_FlatFillSurface (surf_t *surf, int color) ! 761: { ! 762: espan_t *span; ! 763: byte *pdest; ! 764: int u, u2; ! 765: ! 766: for (span=surf->spans ; span ; span=span->pnext) ! 767: { ! 768: pdest = (byte *)d_viewbuffer + r_screenwidth*span->v; ! 769: u = span->u; ! 770: u2 = span->u + span->count - 1; ! 771: for ( ; u <= u2 ; u++) ! 772: pdest[u] = color; ! 773: } ! 774: } ! 775: ! 776: ! 777: /* ! 778: ============== ! 779: D_CalcGradients ! 780: ============== ! 781: */ ! 782: void D_CalcGradients (msurface_t *pface) ! 783: { ! 784: mplane_t *pplane; ! 785: float mipscale; ! 786: vec3_t p_temp1; ! 787: vec3_t p_saxis, p_taxis; ! 788: float t; ! 789: ! 790: pplane = pface->plane; ! 791: ! 792: mipscale = 1.0 / (float)(1 << miplevel); ! 793: ! 794: TransformVector (pface->texinfo->vecs[0], p_saxis); ! 795: TransformVector (pface->texinfo->vecs[1], p_taxis); ! 796: ! 797: t = xscaleinv * mipscale; ! 798: d_sdivzstepu = p_saxis[0] * t; ! 799: d_tdivzstepu = p_taxis[0] * t; ! 800: ! 801: t = yscaleinv * mipscale; ! 802: d_sdivzstepv = -p_saxis[1] * t; ! 803: d_tdivzstepv = -p_taxis[1] * t; ! 804: ! 805: d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - ! 806: ycenter * d_sdivzstepv; ! 807: d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - ! 808: ycenter * d_tdivzstepv; ! 809: ! 810: VectorScale (transformed_modelorg, mipscale, p_temp1); ! 811: ! 812: t = 0x10000*mipscale; ! 813: sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - ! 814: ((pface->texturemins[0] << 16) >> miplevel) ! 815: + pface->texinfo->vecs[0][3]*t; ! 816: tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - ! 817: ((pface->texturemins[1] << 16) >> miplevel) ! 818: + pface->texinfo->vecs[1][3]*t; ! 819: ! 820: if (pface->texinfo->flags & SURF_FLOWING) ! 821: sadjust += 0x10000 * (-128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) )); ! 822: ! 823: // ! 824: // -1 (-epsilon) so we never wander off the edge of the texture ! 825: // ! 826: bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; ! 827: bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; ! 828: } ! 829: ! 830: ! 831: /* ! 832: ============== ! 833: D_BackgroundSurf ! 834: ! 835: The grey background filler seen when there is a hole in the map ! 836: ============== ! 837: */ ! 838: void D_BackgroundSurf (surf_t *s) ! 839: { ! 840: // set up a gradient for the background surface that places it ! 841: // effectively at infinity distance from the viewpoint ! 842: d_zistepu = 0; ! 843: d_zistepv = 0; ! 844: d_ziorigin = -0.9; ! 845: ! 846: D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF); ! 847: D_DrawZSpans (s->spans); ! 848: } ! 849: ! 850: /* ! 851: ================= ! 852: D_TurbulentSurf ! 853: ================= ! 854: */ ! 855: void D_TurbulentSurf (surf_t *s) ! 856: { ! 857: d_zistepu = s->d_zistepu; ! 858: d_zistepv = s->d_zistepv; ! 859: d_ziorigin = s->d_ziorigin; ! 860: ! 861: pface = s->msurf; ! 862: miplevel = 0; ! 863: cacheblock = pface->texinfo->image->pixels[0]; ! 864: cachewidth = 64; ! 865: ! 866: if (s->insubmodel) ! 867: { ! 868: // FIXME: we don't want to do all this for every polygon! ! 869: // TODO: store once at start of frame ! 870: currententity = s->entity; //FIXME: make this passed in to ! 871: // R_RotateBmodel () ! 872: VectorSubtract (r_origin, currententity->origin, ! 873: local_modelorg); ! 874: TransformVector (local_modelorg, transformed_modelorg); ! 875: ! 876: R_RotateBmodel (); // FIXME: don't mess with the frustum, ! 877: // make entity passed in ! 878: } ! 879: ! 880: D_CalcGradients (pface); ! 881: Turbulent8 (s->spans); ! 882: D_DrawZSpans (s->spans); ! 883: ! 884: if (s->insubmodel) ! 885: { ! 886: // ! 887: // restore the old drawing state ! 888: // FIXME: we don't want to do this every time! ! 889: // TODO: speed up ! 890: // ! 891: currententity = NULL; // &r_worldentity; ! 892: VectorCopy (world_transformed_modelorg, ! 893: transformed_modelorg); ! 894: VectorCopy (base_vpn, vpn); ! 895: VectorCopy (base_vup, vup); ! 896: VectorCopy (base_vright, vright); ! 897: R_TransformFrustum (); ! 898: } ! 899: } ! 900: ! 901: /* ! 902: ============== ! 903: D_SkySurf ! 904: ============== ! 905: */ ! 906: void D_SkySurf (surf_t *s) ! 907: { ! 908: pface = s->msurf; ! 909: miplevel = 0; ! 910: if (!pface->texinfo->image) ! 911: return; ! 912: cacheblock = pface->texinfo->image->pixels[0]; ! 913: cachewidth = 256; ! 914: ! 915: d_zistepu = s->d_zistepu; ! 916: d_zistepv = s->d_zistepv; ! 917: d_ziorigin = s->d_ziorigin; ! 918: ! 919: D_CalcGradients (pface); ! 920: ! 921: D_DrawSpans16 (s->spans); ! 922: ! 923: // set up a gradient for the background surface that places it ! 924: // effectively at infinity distance from the viewpoint ! 925: d_zistepu = 0; ! 926: d_zistepv = 0; ! 927: d_ziorigin = -0.9; ! 928: ! 929: D_DrawZSpans (s->spans); ! 930: } ! 931: ! 932: /* ! 933: ============== ! 934: D_SolidSurf ! 935: ! 936: Normal surface cached, texture mapped surface ! 937: ============== ! 938: */ ! 939: void D_SolidSurf (surf_t *s) ! 940: { ! 941: d_zistepu = s->d_zistepu; ! 942: d_zistepv = s->d_zistepv; ! 943: d_ziorigin = s->d_ziorigin; ! 944: ! 945: if (s->insubmodel) ! 946: { ! 947: // FIXME: we don't want to do all this for every polygon! ! 948: // TODO: store once at start of frame ! 949: currententity = s->entity; //FIXME: make this passed in to ! 950: // R_RotateBmodel () ! 951: VectorSubtract (r_origin, currententity->origin, local_modelorg); ! 952: TransformVector (local_modelorg, transformed_modelorg); ! 953: ! 954: R_RotateBmodel (); // FIXME: don't mess with the frustum, ! 955: // make entity passed in ! 956: } ! 957: else ! 958: currententity = &r_worldentity; ! 959: ! 960: pface = s->msurf; ! 961: #if 1 ! 962: miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); ! 963: #else ! 964: { ! 965: float dot; ! 966: float normal[3]; ! 967: ! 968: if ( s->insubmodel ) ! 969: { ! 970: VectorCopy( pface->plane->normal, normal ); ! 971: // TransformVector( pface->plane->normal, normal); ! 972: dot = DotProduct( normal, vpn ); ! 973: } ! 974: else ! 975: { ! 976: VectorCopy( pface->plane->normal, normal ); ! 977: dot = DotProduct( normal, vpn ); ! 978: } ! 979: ! 980: if ( pface->flags & SURF_PLANEBACK ) ! 981: dot = -dot; ! 982: ! 983: if ( dot > 0 ) ! 984: printf( "blah" ); ! 985: ! 986: miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); ! 987: } ! 988: #endif ! 989: ! 990: // FIXME: make this passed in to D_CacheSurface ! 991: pcurrentcache = D_CacheSurface (pface, miplevel); ! 992: ! 993: cacheblock = (pixel_t *)pcurrentcache->data; ! 994: cachewidth = pcurrentcache->width; ! 995: ! 996: D_CalcGradients (pface); ! 997: ! 998: D_DrawSpans16 (s->spans); ! 999: ! 1000: D_DrawZSpans (s->spans); ! 1001: ! 1002: if (s->insubmodel) ! 1003: { ! 1004: // ! 1005: // restore the old drawing state ! 1006: // FIXME: we don't want to do this every time! ! 1007: // TODO: speed up ! 1008: // ! 1009: VectorCopy (world_transformed_modelorg, ! 1010: transformed_modelorg); ! 1011: VectorCopy (base_vpn, vpn); ! 1012: VectorCopy (base_vup, vup); ! 1013: VectorCopy (base_vright, vright); ! 1014: R_TransformFrustum (); ! 1015: currententity = NULL; //&r_worldentity; ! 1016: } ! 1017: } ! 1018: ! 1019: /* ! 1020: ============= ! 1021: D_DrawflatSurfaces ! 1022: ! 1023: To allow developers to see the polygon carving of the world ! 1024: ============= ! 1025: */ ! 1026: void D_DrawflatSurfaces (void) ! 1027: { ! 1028: surf_t *s; ! 1029: ! 1030: for (s = &surfaces[1] ; s<surface_p ; s++) ! 1031: { ! 1032: if (!s->spans) ! 1033: continue; ! 1034: ! 1035: d_zistepu = s->d_zistepu; ! 1036: d_zistepv = s->d_zistepv; ! 1037: d_ziorigin = s->d_ziorigin; ! 1038: ! 1039: // make a stable color for each surface by taking the low ! 1040: // bits of the msurface pointer ! 1041: D_FlatFillSurface (s, (int)s->msurf & 0xFF); ! 1042: D_DrawZSpans (s->spans); ! 1043: } ! 1044: } ! 1045: ! 1046: /* ! 1047: ============== ! 1048: D_DrawSurfaces ! 1049: ! 1050: Rasterize all the span lists. Guaranteed zero overdraw. ! 1051: May be called more than once a frame if the surf list overflows (higher res) ! 1052: ============== ! 1053: */ ! 1054: void D_DrawSurfaces (void) ! 1055: { ! 1056: surf_t *s; ! 1057: ! 1058: // currententity = NULL; //&r_worldentity; ! 1059: VectorSubtract (r_origin, vec3_origin, modelorg); ! 1060: TransformVector (modelorg, transformed_modelorg); ! 1061: VectorCopy (transformed_modelorg, world_transformed_modelorg); ! 1062: ! 1063: if (!sw_drawflat->value) ! 1064: { ! 1065: for (s = &surfaces[1] ; s<surface_p ; s++) ! 1066: { ! 1067: if (!s->spans) ! 1068: continue; ! 1069: ! 1070: r_drawnpolycount++; ! 1071: ! 1072: if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) ) ! 1073: D_SolidSurf (s); ! 1074: else if (s->flags & SURF_DRAWSKYBOX) ! 1075: D_SkySurf (s); ! 1076: else if (s->flags & SURF_DRAWBACKGROUND) ! 1077: D_BackgroundSurf (s); ! 1078: else if (s->flags & SURF_DRAWTURB) ! 1079: D_TurbulentSurf (s); ! 1080: } ! 1081: } ! 1082: else ! 1083: D_DrawflatSurfaces (); ! 1084: ! 1085: currententity = NULL; //&r_worldentity; ! 1086: VectorSubtract (r_origin, vec3_origin, modelorg); ! 1087: R_TransformFrustum (); ! 1088: } ! 1089:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.