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