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