home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / r_things.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  21.9 KB  |  988 lines

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