r_things.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:22k
源码类别:

射击游戏

开发平台:

Visual C++

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