Subversion Repositories Kolibri OS

Rev

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.  
  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. //void R_DrawColumn (void);
  50. //void R_DrawFuzzColumn (void);
  51.  
  52.  
  53.  
  54. typedef struct
  55. {
  56.     int         x1;
  57.     int         x2;
  58.        
  59.     int         column;
  60.     int         topclip;
  61.     int         bottomclip;
  62.  
  63. } maskdraw_t;
  64.  
  65.  
  66.  
  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;
  76.  
  77. lighttable_t**  spritelights;
  78.  
  79. // constant arrays
  80. //  used for psprite clipping and initializing clipping
  81. short           negonearray[SCREENWIDTH];
  82. short           screenheightarray[SCREENWIDTH];
  83.  
  84.  
  85. //
  86. // INITIALIZATION FUNCTIONS
  87. //
  88.  
  89. // variables used to look up
  90. //  and range check thing_t sprites patches
  91. spritedef_t*    sprites;
  92. int             numsprites;
  93.  
  94. spriteframe_t   sprtemp[29];
  95. int             maxframe;
  96. char*           spritename;
  97.  
  98.  
  99.  
  100.  
  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);
  127.  
  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;
  157. }
  158.  
  159.  
  160.  
  161.  
  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;
  228.  
  229.                 R_InstallSpriteLump (patched, frame, rotation, false);
  230.  
  231.                 if (lumpinfo[l].name[6])
  232.                 {
  233.                     frame = lumpinfo[l].name[6] - 'A';
  234.                     rotation = lumpinfo[l].name[7] - '0';
  235.                     R_InstallSpriteLump (l, frame, rotation, true);
  236.                 }
  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.             }
  272.         }
  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.     }
  280.  
  281. }
  282.  
  283.  
  284.  
  285.  
  286. //
  287. // GAME FUNCTIONS
  288. //
  289. vissprite_t     vissprites[MAXVISSPRITES];
  290. vissprite_t*    vissprite_p;
  291. int             newvissprite;
  292.  
  293.  
  294.  
  295. //
  296. // R_InitSprites
  297. // Called at program start.
  298. //
  299. void R_InitSprites (char** namelist)
  300. {
  301.     int         i;
  302.        
  303.     for (i=0 ; i<SCREENWIDTH ; i++)
  304.     {
  305.         negonearray[i] = -1;
  306.     }
  307.        
  308.     R_InitSpriteDefs (namelist);
  309. }
  310.  
  311.  
  312.  
  313. //
  314. // R_ClearSprites
  315. // Called at frame start.
  316. //
  317. void R_ClearSprites (void)
  318. {
  319.     vissprite_p = vissprites;
  320. }
  321.  
  322.  
  323. //
  324. // R_NewVisSprite
  325. //
  326. vissprite_t     overflowsprite;
  327.  
  328. vissprite_t* R_NewVisSprite (void)
  329. {
  330.     if (vissprite_p == &vissprites[MAXVISSPRITES])
  331.         return &overflowsprite;
  332.    
  333.     vissprite_p++;
  334.     return vissprite_p-1;
  335. }
  336.  
  337.  
  338.  
  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.  
  348. fixed_t         spryscale;
  349. fixed_t         sprtopscreen;
  350.  
  351. void R_DrawMaskedColumn (column_t* column)
  352. {
  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 ();
  383.         }
  384.         column = (column_t *)(  (byte *)column + column->length + 4);
  385.     }
  386.        
  387.     dc_texturemid = basetexturemid;
  388. }
  389.  
  390.  
  391.  
  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 )
  401. {
  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);
  409.  
  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;
  433. #ifdef RANGECHECK
  434.         if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
  435.             I_Error ("R_DrawSpriteRange: bad texturecolumn");
  436. #endif
  437.         column = (column_t *) ((byte *)patch +
  438.                                LONG(patch->columnofs[texturecolumn]));
  439.         R_DrawMaskedColumn (column);
  440.     }
  441.  
  442.     colfunc = basecolfunc;
  443. }
  444.  
  445.  
  446.  
  447. //
  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;
  485.        
  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
  506. #ifdef RANGECHECK
  507.     if ((unsigned)thing->sprite >= numsprites)
  508.         I_Error ("R_ProjectSprite: invalid sprite number %i ",
  509.                  thing->sprite);
  510. #endif
  511.     sprdef = &sprites[thing->sprite];
  512. #ifdef RANGECHECK
  513.     if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
  514.         I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
  515.                  thing->sprite, thing->frame);
  516. #endif
  517.     sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
  518.  
  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.     }  
  604. }
  605.  
  606.  
  607.  
  608.  
  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;        
  624.  
  625.     // Well, now it will be done.
  626.     sec->validcount = validcount;
  627.        
  628.     lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
  629.  
  630.     if (lightnum < 0)          
  631.         spritelights = scalelight[0];
  632.     else if (lightnum >= LIGHTLEVELS)
  633.         spritelights = scalelight[LIGHTLEVELS-1];
  634.     else
  635.         spritelights = scalelight[lightnum];
  636.  
  637.     // Handle all things in sector.
  638.     for (thing = sec->thinglist ; thing ; thing = thing->snext)
  639.         R_ProjectSprite (thing);
  640. }
  641.  
  642.  
  643. //
  644. // R_DrawPSprite
  645. //
  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
  659. #ifdef RANGECHECK
  660.     if ( (unsigned)psp->state->sprite >= numsprites)
  661.         I_Error ("R_ProjectSprite: invalid sprite number %i ",
  662.                  psp->state->sprite);
  663. #endif
  664.     sprdef = &sprites[psp->state->sprite];
  665. #ifdef RANGECHECK
  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);
  669. #endif
  670.     sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
  671.  
  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;
  680.  
  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);
  739. }
  740.  
  741.  
  742.  
  743. //
  744. // R_DrawPlayerSprites
  745. //
  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.     }
  776. }
  777.  
  778.  
  779.  
  780.  
  781. //
  782. // R_SortVisSprites
  783. //
  784. vissprite_t     vsprsortedhead;
  785.  
  786.  
  787. void R_SortVisSprites (void)
  788. {
  789.     int                 i;
  790.     int                 count;
  791.     vissprite_t*        ds;
  792.     vissprite_t*        best;
  793.     vissprite_t         unsorted;
  794.     fixed_t             bestscale;
  795.  
  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. }
  836.  
  837.  
  838.  
  839. //
  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;
  874.  
  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;                  
  895.         }
  896.  
  897.        
  898.         // clip this piece of the sprite
  899.         silhouette = ds->silhouette;
  900.        
  901.         if (spr->gz >= ds->bsilheight)
  902.             silhouette &= ~SIL_BOTTOM;
  903.  
  904.         if (spr->gzt <= ds->tsilheight)
  905.             silhouette &= ~SIL_TOP;
  906.                        
  907.         if (silhouette == 1)
  908.         {
  909.             // bottom sil
  910.             for (x=r1 ; x<=r2 ; x++)
  911.                 if (clipbot[x] == -2)
  912.                     clipbot[x] = ds->sprbottomclip[x];
  913.         }
  914.         else if (silhouette == 2)
  915.         {
  916.             // top sil
  917.             for (x=r1 ; x<=r2 ; x++)
  918.                 if (cliptop[x] == -2)
  919.                     cliptop[x] = ds->sprtopclip[x];
  920.         }
  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
  936.  
  937.     // check for unclipped columns
  938.     for (x = spr->x1 ; x<=spr->x2 ; x++)
  939.     {
  940.         if (clipbot[x] == -2)          
  941.             clipbot[x] = viewheight;
  942.  
  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. }
  951.  
  952.  
  953.  
  954.  
  955. //
  956. // R_DrawMasked
  957. //
  958. void R_DrawMasked (void)
  959. {
  960.     vissprite_t*        spr;
  961.     drawseg_t*          ds;
  962.        
  963.     R_SortVisSprites ();
  964.  
  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 ();
  986. }
  987.  
  988.  
  989.  
  990.