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