DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

r_things.cpp (22121B)


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