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