Subversion Repositories Kolibri OS

Rev

Rev 298 | Blame | Last modification | View Log | Download | RSS feed

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