r_things.c
1 // 2 // Copyright(C) 1993-1996 Id Software, Inc. 3 // Copyright(C) 2005-2014 Simon Howard 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // DESCRIPTION: 16 // Refresh of things, i.e. objects represented by sprites. 17 // 18 19 20 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 25 26 #include "deh_main.h" 27 #include "doomdef.h" 28 29 #include "i_swap.h" 30 #include "i_system.h" 31 #include "z_zone.h" 32 #include "w_wad.h" 33 34 #include "r_local.h" 35 36 #include "doomstat.h" 37 38 39 40 #define MINZ (FRACUNIT*4) 41 #define BASEYCENTER 100 42 43 //void R_DrawColumn (void); 44 //void R_DrawFuzzColumn (void); 45 46 47 48 typedef struct 49 { 50 int x1; 51 int x2; 52 53 int column; 54 int topclip; 55 int bottomclip; 56 57 } maskdraw_t; 58 59 60 61 // 62 // Sprite rotation 0 is facing the viewer, 63 // rotation 1 is one angle turn CLOCKWISE around the axis. 64 // This is not the same as the angle, 65 // which increases counter clockwise (protractor). 66 // There was a lot of stuff grabbed wrong, so I changed it... 67 // 68 fixed_t pspritescale; 69 fixed_t pspriteiscale; 70 71 lighttable_t** spritelights; 72 73 // constant arrays 74 // used for psprite clipping and initializing clipping 75 short negonearray[SCREENWIDTH]; 76 short screenheightarray[SCREENWIDTH]; 77 78 79 // 80 // INITIALIZATION FUNCTIONS 81 // 82 83 // variables used to look up 84 // and range check thing_t sprites patches 85 spritedef_t* sprites; 86 int numsprites; 87 88 spriteframe_t sprtemp[29]; 89 int maxframe; 90 char* spritename; 91 92 93 94 95 // 96 // R_InstallSpriteLump 97 // Local function for R_InitSprites. 98 // 99 void 100 R_InstallSpriteLump 101 ( int lump, 102 unsigned frame, 103 unsigned rotation, 104 boolean flipped ) 105 { 106 int r; 107 108 if (frame >= 29 || rotation > 8) 109 I_Error("R_InstallSpriteLump: " 110 "Bad frame characters in lump %i", lump); 111 112 if ((int)frame > maxframe) 113 maxframe = frame; 114 115 if (rotation == 0) 116 { 117 // the lump should be used for all rotations 118 if (sprtemp[frame].rotate == false) 119 I_Error ("R_InitSprites: Sprite %s frame %c has " 120 "multip rot=0 lump", spritename, 'A'+frame); 121 122 if (sprtemp[frame].rotate == true) 123 I_Error ("R_InitSprites: Sprite %s frame %c has rotations " 124 "and a rot=0 lump", spritename, 'A'+frame); 125 126 sprtemp[frame].rotate = false; 127 for (r=0 ; r<8 ; r++) 128 { 129 sprtemp[frame].lump[r] = lump - firstspritelump; 130 sprtemp[frame].flip[r] = (byte)flipped; 131 } 132 return; 133 } 134 135 // the lump is only used for one rotation 136 if (sprtemp[frame].rotate == false) 137 I_Error ("R_InitSprites: Sprite %s frame %c has rotations " 138 "and a rot=0 lump", spritename, 'A'+frame); 139 140 sprtemp[frame].rotate = true; 141 142 // make 0 based 143 rotation--; 144 if (sprtemp[frame].lump[rotation] != -1) 145 I_Error ("R_InitSprites: Sprite %s : %c : %c " 146 "has two lumps mapped to it", 147 spritename, 'A'+frame, '1'+rotation); 148 149 sprtemp[frame].lump[rotation] = lump - firstspritelump; 150 sprtemp[frame].flip[rotation] = (byte)flipped; 151 } 152 153 154 155 156 // 157 // R_InitSpriteDefs 158 // Pass a null terminated list of sprite names 159 // (4 chars exactly) to be used. 160 // Builds the sprite rotation matrixes to account 161 // for horizontally flipped sprites. 162 // Will report an error if the lumps are inconsistant. 163 // Only called at startup. 164 // 165 // Sprite lump names are 4 characters for the actor, 166 // a letter for the frame, and a number for the rotation. 167 // A sprite that is flippable will have an additional 168 // letter/number appended. 169 // The rotation character can be 0 to signify no rotations. 170 // 171 void R_InitSpriteDefs (char** namelist) 172 { 173 char** check; 174 int i; 175 int l; 176 int frame; 177 int rotation; 178 int start; 179 int end; 180 int patched; 181 182 // count the number of sprite names 183 check = namelist; 184 while (*check != NULL) 185 check++; 186 187 numsprites = check-namelist; 188 189 if (!numsprites) 190 return; 191 192 sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); 193 194 start = firstspritelump-1; 195 end = lastspritelump+1; 196 197 // scan all the lump names for each of the names, 198 // noting the highest frame letter. 199 // Just compare 4 characters as ints 200 for (i=0 ; i<numsprites ; i++) 201 { 202 spritename = DEH_String(namelist[i]); 203 memset (sprtemp,-1, sizeof(sprtemp)); 204 205 maxframe = -1; 206 207 // scan the lumps, 208 // filling in the frames for whatever is found 209 for (l=start+1 ; l<end ; l++) 210 { 211 if (!strncasecmp(lumpinfo[l].name, spritename, 4)) 212 { 213 frame = lumpinfo[l].name[4] - 'A'; 214 rotation = lumpinfo[l].name[5] - '0'; 215 216 if (modifiedgame) 217 patched = W_GetNumForName (lumpinfo[l].name); 218 else 219 patched = l; 220 221 R_InstallSpriteLump (patched, frame, rotation, false); 222 223 if (lumpinfo[l].name[6]) 224 { 225 frame = lumpinfo[l].name[6] - 'A'; 226 rotation = lumpinfo[l].name[7] - '0'; 227 R_InstallSpriteLump (l, frame, rotation, true); 228 } 229 } 230 } 231 232 // check the frames that were found for completeness 233 if (maxframe == -1) 234 { 235 sprites[i].numframes = 0; 236 continue; 237 } 238 239 maxframe++; 240 241 for (frame = 0 ; frame < maxframe ; frame++) 242 { 243 switch ((int)sprtemp[frame].rotate) 244 { 245 case -1: 246 // no rotations were found for that frame at all 247 I_Error ("R_InitSprites: No patches found " 248 "for %s frame %c", spritename, frame+'A'); 249 break; 250 251 case 0: 252 // only the first rotation is needed 253 break; 254 255 case 1: 256 // must have all 8 frames 257 for (rotation=0 ; rotation<8 ; rotation++) 258 if (sprtemp[frame].lump[rotation] == -1) 259 I_Error ("R_InitSprites: Sprite %s frame %c " 260 "is missing rotations", 261 spritename, frame+'A'); 262 break; 263 } 264 } 265 266 // allocate space for the frames present and copy sprtemp to it 267 sprites[i].numframes = maxframe; 268 sprites[i].spriteframes = 269 Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); 270 memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); 271 } 272 273 } 274 275 276 277 278 // 279 // GAME FUNCTIONS 280 // 281 vissprite_t vissprites[MAXVISSPRITES]; 282 vissprite_t* vissprite_p; 283 int newvissprite; 284 285 286 287 // 288 // R_InitSprites 289 // Called at program start. 290 // 291 void R_InitSprites (char** namelist) 292 { 293 int i; 294 295 for (i=0 ; i<SCREENWIDTH ; i++) 296 { 297 negonearray[i] = -1; 298 } 299 300 R_InitSpriteDefs (namelist); 301 } 302 303 304 305 // 306 // R_ClearSprites 307 // Called at frame start. 308 // 309 void R_ClearSprites (void) 310 { 311 vissprite_p = vissprites; 312 } 313 314 315 // 316 // R_NewVisSprite 317 // 318 vissprite_t overflowsprite; 319 320 vissprite_t* R_NewVisSprite (void) 321 { 322 if (vissprite_p == &vissprites[MAXVISSPRITES]) 323 return &overflowsprite; 324 325 vissprite_p++; 326 return vissprite_p-1; 327 } 328 329 330 331 // 332 // R_DrawMaskedColumn 333 // Used for sprites and masked mid textures. 334 // Masked means: partly transparent, i.e. stored 335 // in posts/runs of opaque pixels. 336 // 337 short* mfloorclip; 338 short* mceilingclip; 339 340 fixed_t spryscale; 341 fixed_t sprtopscreen; 342 343 void R_DrawMaskedColumn (column_t* column) 344 { 345 int topscreen; 346 int bottomscreen; 347 fixed_t basetexturemid; 348 349 basetexturemid = dc_texturemid; 350 351 for ( ; column->topdelta != 0xff ; ) 352 { 353 // calculate unclipped screen coordinates 354 // for post 355 topscreen = sprtopscreen + spryscale*column->topdelta; 356 bottomscreen = topscreen + spryscale*column->length; 357 358 dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; 359 dc_yh = (bottomscreen-1)>>FRACBITS; 360 361 if (dc_yh >= mfloorclip[dc_x]) 362 dc_yh = mfloorclip[dc_x]-1; 363 if (dc_yl <= mceilingclip[dc_x]) 364 dc_yl = mceilingclip[dc_x]+1; 365 366 if (dc_yl <= dc_yh) 367 { 368 dc_source = (byte *)column + 3; 369 dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS); 370 // dc_source = (byte *)column + 3 - column->topdelta; 371 372 // Drawn by either R_DrawColumn 373 // or (SHADOW) R_DrawFuzzColumn. 374 colfunc (); 375 } 376 column = (column_t *)( (byte *)column + column->length + 4); 377 } 378 379 dc_texturemid = basetexturemid; 380 } 381 382 383 384 // 385 // R_DrawVisSprite 386 // mfloorclip and mceilingclip should also be set. 387 // 388 void 389 R_DrawVisSprite 390 ( vissprite_t* vis, 391 int x1, 392 int x2 ) 393 { 394 column_t* column; 395 int texturecolumn; 396 fixed_t frac; 397 patch_t* patch; 398 399 400 patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); 401 402 dc_colormap = vis->colormap; 403 404 if (!dc_colormap) 405 { 406 // NULL colormap = shadow draw 407 colfunc = fuzzcolfunc; 408 } 409 else if (vis->mobjflags & MF_TRANSLATION) 410 { 411 colfunc = transcolfunc; 412 dc_translation = translationtables - 256 + 413 ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) ); 414 } 415 416 dc_iscale = abs(vis->xiscale)>>detailshift; 417 dc_texturemid = vis->texturemid; 418 frac = vis->startfrac; 419 spryscale = vis->scale; 420 sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); 421 422 for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) 423 { 424 texturecolumn = frac>>FRACBITS; 425 #ifdef RANGECHECK 426 if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) 427 I_Error ("R_DrawSpriteRange: bad texturecolumn"); 428 #endif 429 column = (column_t *) ((byte *)patch + 430 LONG(patch->columnofs[texturecolumn])); 431 R_DrawMaskedColumn (column); 432 } 433 434 colfunc = basecolfunc; 435 } 436 437 438 439 // 440 // R_ProjectSprite 441 // Generates a vissprite for a thing 442 // if it might be visible. 443 // 444 void R_ProjectSprite (mobj_t* thing) 445 { 446 fixed_t tr_x; 447 fixed_t tr_y; 448 449 fixed_t gxt; 450 fixed_t gyt; 451 452 fixed_t tx; 453 fixed_t tz; 454 455 fixed_t xscale; 456 457 int x1; 458 int x2; 459 460 spritedef_t* sprdef; 461 spriteframe_t* sprframe; 462 int lump; 463 464 unsigned rot; 465 boolean flip; 466 467 int index; 468 469 vissprite_t* vis; 470 471 angle_t ang; 472 fixed_t iscale; 473 474 // transform the origin point 475 tr_x = thing->x - viewx; 476 tr_y = thing->y - viewy; 477 478 gxt = FixedMul(tr_x,viewcos); 479 gyt = -FixedMul(tr_y,viewsin); 480 481 tz = gxt-gyt; 482 483 // thing is behind view plane? 484 if (tz < MINZ) 485 return; 486 487 xscale = FixedDiv(projection, tz); 488 489 gxt = -FixedMul(tr_x,viewsin); 490 gyt = FixedMul(tr_y,viewcos); 491 tx = -(gyt+gxt); 492 493 // too far off the side? 494 if (abs(tx)>(tz<<2)) 495 return; 496 497 // decide which patch to use for sprite relative to player 498 #ifdef RANGECHECK 499 if ((unsigned int) thing->sprite >= (unsigned int) numsprites) 500 I_Error ("R_ProjectSprite: invalid sprite number %i ", 501 thing->sprite); 502 #endif 503 sprdef = &sprites[thing->sprite]; 504 #ifdef RANGECHECK 505 if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) 506 I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", 507 thing->sprite, thing->frame); 508 #endif 509 sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; 510 511 if (sprframe->rotate) 512 { 513 // choose a different rotation based on player view 514 ang = R_PointToAngle (thing->x, thing->y); 515 rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; 516 lump = sprframe->lump[rot]; 517 flip = (boolean)sprframe->flip[rot]; 518 } 519 else 520 { 521 // use single rotation for all views 522 lump = sprframe->lump[0]; 523 flip = (boolean)sprframe->flip[0]; 524 } 525 526 // calculate edges of the shape 527 tx -= spriteoffset[lump]; 528 x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; 529 530 // off the right side? 531 if (x1 > viewwidth) 532 return; 533 534 tx += spritewidth[lump]; 535 x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; 536 537 // off the left side 538 if (x2 < 0) 539 return; 540 541 // store information in a vissprite 542 vis = R_NewVisSprite (); 543 vis->mobjflags = thing->flags; 544 vis->scale = xscale<<detailshift; 545 vis->gx = thing->x; 546 vis->gy = thing->y; 547 vis->gz = thing->z; 548 vis->gzt = thing->z + spritetopoffset[lump]; 549 vis->texturemid = vis->gzt - viewz; 550 vis->x1 = x1 < 0 ? 0 : x1; 551 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; 552 iscale = FixedDiv (FRACUNIT, xscale); 553 554 if (flip) 555 { 556 vis->startfrac = spritewidth[lump]-1; 557 vis->xiscale = -iscale; 558 } 559 else 560 { 561 vis->startfrac = 0; 562 vis->xiscale = iscale; 563 } 564 565 if (vis->x1 > x1) 566 vis->startfrac += vis->xiscale*(vis->x1-x1); 567 vis->patch = lump; 568 569 // get light level 570 if (thing->flags & MF_SHADOW) 571 { 572 // shadow draw 573 vis->colormap = NULL; 574 } 575 else if (fixedcolormap) 576 { 577 // fixed map 578 vis->colormap = fixedcolormap; 579 } 580 else if (thing->frame & FF_FULLBRIGHT) 581 { 582 // full bright 583 vis->colormap = colormaps; 584 } 585 586 else 587 { 588 // diminished light 589 index = xscale>>(LIGHTSCALESHIFT-detailshift); 590 591 if (index >= MAXLIGHTSCALE) 592 index = MAXLIGHTSCALE-1; 593 594 vis->colormap = spritelights[index]; 595 } 596 } 597 598 599 600 601 // 602 // R_AddSprites 603 // During BSP traversal, this adds sprites by sector. 604 // 605 void R_AddSprites (sector_t* sec) 606 { 607 mobj_t* thing; 608 int lightnum; 609 610 // BSP is traversed by subsector. 611 // A sector might have been split into several 612 // subsectors during BSP building. 613 // Thus we check whether its already added. 614 if (sec->validcount == validcount) 615 return; 616 617 // Well, now it will be done. 618 sec->validcount = validcount; 619 620 lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; 621 622 if (lightnum < 0) 623 spritelights = scalelight[0]; 624 else if (lightnum >= LIGHTLEVELS) 625 spritelights = scalelight[LIGHTLEVELS-1]; 626 else 627 spritelights = scalelight[lightnum]; 628 629 // Handle all things in sector. 630 for (thing = sec->thinglist ; thing ; thing = thing->snext) 631 R_ProjectSprite (thing); 632 } 633 634 635 // 636 // R_DrawPSprite 637 // 638 void R_DrawPSprite (pspdef_t* psp) 639 { 640 fixed_t tx; 641 int x1; 642 int x2; 643 spritedef_t* sprdef; 644 spriteframe_t* sprframe; 645 int lump; 646 boolean flip; 647 vissprite_t* vis; 648 vissprite_t avis; 649 650 // decide which patch to use 651 #ifdef RANGECHECK 652 if ( (unsigned)psp->state->sprite >= (unsigned int) numsprites) 653 I_Error ("R_ProjectSprite: invalid sprite number %i ", 654 psp->state->sprite); 655 #endif 656 sprdef = &sprites[psp->state->sprite]; 657 #ifdef RANGECHECK 658 if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) 659 I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", 660 psp->state->sprite, psp->state->frame); 661 #endif 662 sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; 663 664 lump = sprframe->lump[0]; 665 flip = (boolean)sprframe->flip[0]; 666 667 // calculate edges of the shape 668 tx = psp->sx-160*FRACUNIT; 669 670 tx -= spriteoffset[lump]; 671 x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; 672 673 // off the right side 674 if (x1 > viewwidth) 675 return; 676 677 tx += spritewidth[lump]; 678 x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; 679 680 // off the left side 681 if (x2 < 0) 682 return; 683 684 // store information in a vissprite 685 vis = &avis; 686 vis->mobjflags = 0; 687 vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]); 688 vis->x1 = x1 < 0 ? 0 : x1; 689 vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; 690 vis->scale = pspritescale<<detailshift; 691 692 if (flip) 693 { 694 vis->xiscale = -pspriteiscale; 695 vis->startfrac = spritewidth[lump]-1; 696 } 697 else 698 { 699 vis->xiscale = pspriteiscale; 700 vis->startfrac = 0; 701 } 702 703 if (vis->x1 > x1) 704 vis->startfrac += vis->xiscale*(vis->x1-x1); 705 706 vis->patch = lump; 707 708 if (viewplayer->powers[pw_invisibility] > 4*32 709 || viewplayer->powers[pw_invisibility] & 8) 710 { 711 // shadow draw 712 vis->colormap = NULL; 713 } 714 else if (fixedcolormap) 715 { 716 // fixed color 717 vis->colormap = fixedcolormap; 718 } 719 else if (psp->state->frame & FF_FULLBRIGHT) 720 { 721 // full bright 722 vis->colormap = colormaps; 723 } 724 else 725 { 726 // local light 727 vis->colormap = spritelights[MAXLIGHTSCALE-1]; 728 } 729 730 R_DrawVisSprite (vis, vis->x1, vis->x2); 731 } 732 733 734 735 // 736 // R_DrawPlayerSprites 737 // 738 void R_DrawPlayerSprites (void) 739 { 740 int i; 741 int lightnum; 742 pspdef_t* psp; 743 744 // get light level 745 lightnum = 746 (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) 747 +extralight; 748 749 if (lightnum < 0) 750 spritelights = scalelight[0]; 751 else if (lightnum >= LIGHTLEVELS) 752 spritelights = scalelight[LIGHTLEVELS-1]; 753 else 754 spritelights = scalelight[lightnum]; 755 756 // clip to screen bounds 757 mfloorclip = screenheightarray; 758 mceilingclip = negonearray; 759 760 // add all active psprites 761 for (i=0, psp=viewplayer->psprites; 762 i<NUMPSPRITES; 763 i++,psp++) 764 { 765 if (psp->state) 766 R_DrawPSprite (psp); 767 } 768 } 769 770 771 772 773 // 774 // R_SortVisSprites 775 // 776 vissprite_t vsprsortedhead; 777 778 779 void R_SortVisSprites (void) 780 { 781 int i; 782 int count; 783 vissprite_t* ds; 784 vissprite_t* best; 785 vissprite_t unsorted; 786 fixed_t bestscale; 787 788 count = vissprite_p - vissprites; 789 790 unsorted.next = unsorted.prev = &unsorted; 791 792 if (!count) 793 return; 794 795 for (ds=vissprites ; ds<vissprite_p ; ds++) 796 { 797 ds->next = ds+1; 798 ds->prev = ds-1; 799 } 800 801 vissprites[0].prev = &unsorted; 802 unsorted.next = &vissprites[0]; 803 (vissprite_p-1)->next = &unsorted; 804 unsorted.prev = vissprite_p-1; 805 806 // pull the vissprites out by scale 807 808 vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; 809 for (i=0 ; i<count ; i++) 810 { 811 bestscale = INT_MAX; 812 best = unsorted.next; 813 for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next) 814 { 815 if (ds->scale < bestscale) 816 { 817 bestscale = ds->scale; 818 best = ds; 819 } 820 } 821 best->next->prev = best->prev; 822 best->prev->next = best->next; 823 best->next = &vsprsortedhead; 824 best->prev = vsprsortedhead.prev; 825 vsprsortedhead.prev->next = best; 826 vsprsortedhead.prev = best; 827 } 828 } 829 830 831 832 // 833 // R_DrawSprite 834 // 835 void R_DrawSprite (vissprite_t* spr) 836 { 837 drawseg_t* ds; 838 short clipbot[SCREENWIDTH]; 839 short cliptop[SCREENWIDTH]; 840 int x; 841 int r1; 842 int r2; 843 fixed_t scale; 844 fixed_t lowscale; 845 int silhouette; 846 847 for (x = spr->x1 ; x<=spr->x2 ; x++) 848 clipbot[x] = cliptop[x] = -2; 849 850 // Scan drawsegs from end to start for obscuring segs. 851 // The first drawseg that has a greater scale 852 // is the clip seg. 853 for (ds=ds_p-1 ; ds >= drawsegs ; ds--) 854 { 855 // determine if the drawseg obscures the sprite 856 if (ds->x1 > spr->x2 857 || ds->x2 < spr->x1 858 || (!ds->silhouette 859 && !ds->maskedtexturecol) ) 860 { 861 // does not cover sprite 862 continue; 863 } 864 865 r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; 866 r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; 867 868 if (ds->scale1 > ds->scale2) 869 { 870 lowscale = ds->scale2; 871 scale = ds->scale1; 872 } 873 else 874 { 875 lowscale = ds->scale1; 876 scale = ds->scale2; 877 } 878 879 if (scale < spr->scale 880 || ( lowscale < spr->scale 881 && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) 882 { 883 // masked mid texture? 884 if (ds->maskedtexturecol) 885 R_RenderMaskedSegRange (ds, r1, r2); 886 // seg is behind sprite 887 continue; 888 } 889 890 891 // clip this piece of the sprite 892 silhouette = ds->silhouette; 893 894 if (spr->gz >= ds->bsilheight) 895 silhouette &= ~SIL_BOTTOM; 896 897 if (spr->gzt <= ds->tsilheight) 898 silhouette &= ~SIL_TOP; 899 900 if (silhouette == 1) 901 { 902 // bottom sil 903 for (x=r1 ; x<=r2 ; x++) 904 if (clipbot[x] == -2) 905 clipbot[x] = ds->sprbottomclip[x]; 906 } 907 else if (silhouette == 2) 908 { 909 // top sil 910 for (x=r1 ; x<=r2 ; x++) 911 if (cliptop[x] == -2) 912 cliptop[x] = ds->sprtopclip[x]; 913 } 914 else if (silhouette == 3) 915 { 916 // both 917 for (x=r1 ; x<=r2 ; x++) 918 { 919 if (clipbot[x] == -2) 920 clipbot[x] = ds->sprbottomclip[x]; 921 if (cliptop[x] == -2) 922 cliptop[x] = ds->sprtopclip[x]; 923 } 924 } 925 926 } 927 928 // all clipping has been performed, so draw the sprite 929 930 // check for unclipped columns 931 for (x = spr->x1 ; x<=spr->x2 ; x++) 932 { 933 if (clipbot[x] == -2) 934 clipbot[x] = viewheight; 935 936 if (cliptop[x] == -2) 937 cliptop[x] = -1; 938 } 939 940 mfloorclip = clipbot; 941 mceilingclip = cliptop; 942 R_DrawVisSprite (spr, spr->x1, spr->x2); 943 } 944 945 946 947 948 // 949 // R_DrawMasked 950 // 951 void R_DrawMasked (void) 952 { 953 vissprite_t* spr; 954 drawseg_t* ds; 955 956 R_SortVisSprites (); 957 958 if (vissprite_p > vissprites) 959 { 960 // draw all vissprites back to front 961 for (spr = vsprsortedhead.next ; 962 spr != &vsprsortedhead ; 963 spr=spr->next) 964 { 965 966 R_DrawSprite (spr); 967 } 968 } 969 970 // render any remaining masked mid textures 971 for (ds=ds_p-1 ; ds >= drawsegs ; ds--) 972 if (ds->maskedtexturecol) 973 R_RenderMaskedSegRange (ds, ds->x1, ds->x2); 974 975 // draw the psprites on top of everything 976 // but does not draw on side views 977 if (!viewangleoffset) 978 R_DrawPlayerSprites (); 979 } 980 981 982