1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * Refresh of things, i.e. objects represented by sprites.
30 *-----------------------------------------------------------------------------*/
43 //#include "lprintf.h"
44 #include "rockmacros.h"
46 #define MINZ (FRACUNIT*4)
47 #define BASEYCENTER 100
59 // Sprite rotation 0 is facing the viewer,
60 // rotation 1 is one angle turn CLOCKWISE around the axis.
61 // This is not the same as the angle,
62 // which increases counter clockwise (protractor).
63 // There was a lot of stuff grabbed wrong, so I changed it...
66 fixed_t pspriteiscale
;
67 // proff 11/06/98: Added for high-res
68 fixed_t pspriteyscale
;
70 static lighttable_t
** spritelights
;
73 // used for psprite clipping and initializing clipping
74 short negonearray
[MAX_SCREENWIDTH
];
75 short screenheightarray
[MAX_SCREENWIDTH
];
79 // INITIALIZATION FUNCTIONS
82 // variables used to look up and range check thing_t sprites patches
87 #define MAX_SPRITE_FRAMES 29 /* Macroized -- killough 1/25/98 */
89 static spriteframe_t sprtemp
[MAX_SPRITE_FRAMES
];
93 // R_InstallSpriteLump
94 // Local function for R_InitSprites.
97 static void R_InstallSpriteLump(int lump
, unsigned frame
,
98 unsigned rotation
, boolean flipped
)
101 if (frame
>= MAX_SPRITE_FRAMES
|| rotation
> 8)
102 I_Error("R_InstallSpriteLump: Bad frame characters in lump %i", lump
);
104 if ((int)frame
> maxframe
)
108 { // the lump should be used for all rotations
110 for (r
=0 ; r
<8 ; r
++)
111 if (sprtemp
[frame
].lump
[r
]==-1)
113 sprtemp
[frame
].lump
[r
] = lump
- firstspritelump
;
114 sprtemp
[frame
].flip
[r
] = (byte
) flipped
;
115 sprtemp
[frame
].rotate
= false; //jff 4/24/98 if any subbed, rotless
120 // the lump is only used for one rotation
122 if (sprtemp
[frame
].lump
[--rotation
] == -1)
124 sprtemp
[frame
].lump
[rotation
] = lump
- firstspritelump
;
125 sprtemp
[frame
].flip
[rotation
] = (byte
) flipped
;
126 sprtemp
[frame
].rotate
= true; //jff 4/24/98 only change if rot used
132 // Pass a null terminated list of sprite names
133 // (4 chars exactly) to be used.
135 // Builds the sprite rotation matrixes to account
136 // for horizontally flipped sprites.
138 // Will report an error if the lumps are inconsistent.
139 // Only called at startup.
141 // Sprite lump names are 4 characters for the actor,
142 // a letter for the frame, and a number for the rotation.
144 // A sprite that is flippable will have an additional
145 // letter/number appended.
147 // The rotation character can be 0 to signify no rotations.
149 // 1/25/98, 1/31/98 killough : Rewritten for performance
151 // Empirically verified to have excellent hash
152 // properties across standard Doom sprites:
154 #define R_SpriteNameHash(s) ((unsigned)((s)[0]-((s)[1]*3-(s)[3]*2-(s)[2])*2))
156 void R_InitSpriteDefs(const char * const * namelist
)
158 size_t numentries
= lastspritelump
-firstspritelump
+1;
165 if (!numentries
|| !*namelist
)
168 // count the number of sprite names
169 for (i
=0; namelist
[i
]; i
++)
174 sprites
= Z_Malloc(numsprites
*sizeof(*sprites
), PU_STATIC
, NULL
);
176 // Create hash table based on just the first four letters of each sprite
179 hash
= malloc(sizeof(*hash
)*numentries
); // allocate hash table
181 for (i
=0; (size_t)i
<numentries
; i
++) // initialize hash table as empty
184 for (i
=0; (size_t)i
<numentries
; i
++) // Prepend each sprite to hash chain
185 { // prepend so that later ones win
186 int j
= R_SpriteNameHash(lumpinfo
[i
+firstspritelump
].name
) % numentries
;
187 hash
[i
].next
= hash
[j
].index
;
191 // scan all the lump names for each of the names,
192 // noting the highest frame letter.
194 for (i
=0 ; i
<numsprites
; i
++)
196 const char *spritename
= namelist
[i
];
197 int j
= hash
[R_SpriteNameHash(spritename
) % numentries
].index
;
201 memset(sprtemp
, -1, sizeof(sprtemp
));
205 register lumpinfo_t
*lump
= lumpinfo
+ j
+ firstspritelump
;
207 // Fast portable comparison -- killough
208 // (using int pointer cast is nonportable):
210 if (!((lump
->name
[0] ^ spritename
[0]) |
211 (lump
->name
[1] ^ spritename
[1]) |
212 (lump
->name
[2] ^ spritename
[2]) |
213 (lump
->name
[3] ^ spritename
[3])))
215 R_InstallSpriteLump(j
+firstspritelump
,
220 R_InstallSpriteLump(j
+firstspritelump
,
226 while ((j
= hash
[j
].next
) >= 0)
229 // check the frames that were found for completeness
230 if ((sprites
[i
].numframes
= ++maxframe
)) // killough 1/31/98
233 for (frame
= 0; frame
< maxframe
; frame
++)
234 switch ((int) sprtemp
[frame
].rotate
)
237 // no rotations were found for that frame at all
238 I_Error ("R_InitSprites: No patches found "
239 "for %.8s frame %c", namelist
[i
], frame
+'A');
243 // only the first rotation is needed
247 // must have all 8 frames
250 for (rotation
=0 ; rotation
<8 ; rotation
++)
251 if (sprtemp
[frame
].lump
[rotation
] == -1)
252 I_Error ("R_InitSprites: Sprite %.8s frame %c "
253 "is missing rotations",
254 namelist
[i
], frame
+'A');
258 // allocate space for the frames present and copy sprtemp to it
259 sprites
[i
].spriteframes
=
260 Z_Malloc (maxframe
* sizeof(spriteframe_t
), PU_STATIC
, NULL
);
261 memcpy (sprites
[i
].spriteframes
, sprtemp
,
262 maxframe
*sizeof(spriteframe_t
));
266 free(hash
); // free hash table
273 static vissprite_t
*vissprites
, **vissprite_ptrs
; // killough
274 static size_t num_vissprite
, num_vissprite_alloc
, num_vissprite_ptrs
;
279 // Called at program start.
281 void R_InitSprites(const char * const *namelist
)
285 for (i
=0 ; i
<MAX_SCREENWIDTH
; i
++)
287 R_InitSpriteDefs (namelist
);
290 void R_ClearSprites (void)
292 num_vissprite
= 0; // killough
299 vissprite_t
*R_NewVisSprite(void)
301 if (num_vissprite
>= num_vissprite_alloc
) // killough
303 num_vissprite_alloc
= num_vissprite_alloc
? num_vissprite_alloc
*2 : 128;
304 vissprites
= realloc(vissprites
,num_vissprite_alloc
*sizeof(*vissprites
));
306 return vissprites
+ num_vissprite
++;
310 // R_DrawMaskedColumn
311 // Used for sprites and masked mid textures.
312 // Masked means: partly transparent, i.e. stored
313 // in posts/runs of opaque pixels.
319 fixed_t sprtopscreen
;
321 void R_DrawMaskedColumn(const column_t
*column
)
325 fixed_t basetexturemid
= dc_texturemid
;
327 dc_texheight
= 0; // killough 11/98
328 while (column
->topdelta
!= 0xff)
330 // calculate unclipped screen coordinates for post
331 topscreen
= sprtopscreen
+ spryscale
*column
->topdelta
;
332 bottomscreen
= topscreen
+ spryscale
*column
->length
;
334 dc_yl
= (topscreen
+FRACUNIT
-1)>>FRACBITS
;
335 dc_yh
= (bottomscreen
-1)>>FRACBITS
;
337 if (dc_yh
>= mfloorclip
[dc_x
])
338 dc_yh
= mfloorclip
[dc_x
]-1;
340 if (dc_yl
<= mceilingclip
[dc_x
])
341 dc_yl
= mceilingclip
[dc_x
]+1;
343 // killough 3/2/98, 3/27/98: Failsafe against overflow/crash:
344 if (dc_yl
<= dc_yh
&& dc_yh
< viewheight
)
346 dc_source
= (byte
*)column
+ 3;
347 dc_texturemid
= basetexturemid
- (column
->topdelta
<<FRACBITS
);
349 // Drawn by either R_DrawColumn
350 // or (SHADOW) R_DrawFuzzColumn.
353 column
= (const column_t
*)( (byte
*)column
+ column
->length
+ 4);
355 dc_texturemid
= basetexturemid
;
360 // mfloorclip and mceilingclip should also be set.
362 // CPhipps - new wad lump handling, *'s to const*'s
363 void R_DrawVisSprite(vissprite_t
*vis
, int x1
, int x2
)
367 const column_t
*column
;
370 const patch_t
*patch
= W_CacheLumpNum (vis
->patch
+firstspritelump
);
372 dc_colormap
= vis
->colormap
;
374 // killough 4/11/98: rearrange and handle translucent sprites
375 // mixed with translucent/non-translucenct 2s normals
377 if (!dc_colormap
) // NULL colormap = shadow draw
378 colfunc
= R_DrawFuzzColumn
; // killough 3/14/98
380 if (vis
->mobjflags
& MF_TRANSLATION
)
382 colfunc
= R_DrawTranslatedColumn
;
383 dc_translation
= translationtables
- 256 +
384 ((vis
->mobjflags
& MF_TRANSLATION
) >> (MF_TRANSSHIFT
-8) );
387 if (vis
->mobjflags
& MF_TRANSLUCENT
&& general_translucency
) // phares
389 colfunc
= R_DrawTLColumn
;
390 tranmap
= main_tranmap
; // killough 4/11/98
393 colfunc
= R_DrawColumn
; // killough 3/14/98, 4/11/98
396 // proff 11/06/98: Changed for high-res
397 dc_iscale
= FixedDiv (FRACUNIT
, vis
->scale
);
398 dc_texturemid
= vis
->texturemid
;
399 frac
= vis
->startfrac
;
400 spryscale
= vis
->scale
;
401 sprtopscreen
= centeryfrac
- FixedMul(dc_texturemid
,spryscale
);
403 for (dc_x
=vis
->x1
; dc_x
<=vis
->x2
; dc_x
++, frac
+= vis
->xiscale
)
405 texturecolumn
= frac
>>FRACBITS
;
409 if (texturecolumn
< 0 || texturecolumn
>= SHORT(patch
->width
))
410 I_Error ("R_DrawSpriteRange: Bad texturecolumn");
413 column
= (const column_t
*)((const byte
*) patch
+
414 LONG(patch
->columnofs
[texturecolumn
]));
415 R_DrawMaskedColumn (column
);
417 colfunc
= R_DrawColumn
; // killough 3/14/98
418 W_UnlockLumpNum(vis
->patch
+firstspritelump
); // cph - release lump
423 // Generates a vissprite for a thing if it might be visible.
426 void R_ProjectSprite (mobj_t
* thing
)
428 fixed_t gzt
; // killough 3/27/98
434 spriteframe_t
*sprframe
;
443 int heightsec
; // killough 3/27/98
445 // transform the origin point
446 fixed_t tr_x
= thing
->x
- viewx
;
447 fixed_t tr_y
= thing
->y
- viewy
;
449 fixed_t gxt
= FixedMul(tr_x
,viewcos
);
450 fixed_t gyt
= -FixedMul(tr_y
,viewsin
);
452 fixed_t tz
= gxt
-gyt
;
454 // thing is behind view plane?
458 xscale
= FixedDiv(projection
, tz
);
460 gxt
= -FixedMul(tr_x
,viewsin
);
461 gyt
= FixedMul(tr_y
,viewcos
);
464 // too far off the side?
465 if (D_abs(tx
)>(tz
<<2))
468 // decide which patch to use for sprite relative to player
471 if ((unsigned) thing
->sprite
>= (unsigned)numsprites
)
472 I_Error ("R_ProjectSprite: Invalid sprite number %i", thing
->sprite
);
475 sprdef
= &sprites
[thing
->sprite
];
479 if ((thing
->frame
&FF_FRAMEMASK
) >= sprdef
->numframes
)
480 I_Error ("R_ProjectSprite: Invalid sprite frame %i : %i", thing
->sprite
,
484 sprframe
= &sprdef
->spriteframes
[thing
->frame
& FF_FRAMEMASK
];
486 if (sprframe
->rotate
)
488 // choose a different rotation based on player view
489 angle_t ang
= R_PointToAngle(thing
->x
, thing
->y
);
490 unsigned rot
= (ang
-thing
->angle
+(unsigned)(ANG45
/2)*9)>>29;
491 lump
= sprframe
->lump
[rot
];
492 flip
= (boolean
) sprframe
->flip
[rot
];
496 // use single rotation for all views
497 lump
= sprframe
->lump
[0];
498 flip
= (boolean
) sprframe
->flip
[0];
501 /* calculate edges of the shape
502 * cph 2003/08/1 - fraggle points out that this offset must be flipped if the
503 * sprite is flipped; e.g. FreeDoom imp is messed up by this. */
504 tx
-= flip
? spritewidth
[lump
] - spriteoffset
[lump
] : spriteoffset
[lump
];
505 x1
= (centerxfrac
+ FixedMul(tx
,xscale
)) >>FRACBITS
;
507 // off the right side?
511 tx
+= spritewidth
[lump
];
512 x2
= ((centerxfrac
+ FixedMul (tx
,xscale
) ) >>FRACBITS
) - 1;
518 gzt
= thing
->z
+ spritetopoffset
[lump
];
520 // killough 4/9/98: clip things which are out of view due to height
521 if (thing
->z
> viewz
+ FixedDiv(centeryfrac
, xscale
) ||
522 gzt
< viewz
- FixedDiv(centeryfrac
-viewheight
, xscale
))
525 // killough 3/27/98: exclude things totally separated
526 // from the viewer, by either water or fake ceilings
527 // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
529 heightsec
= thing
->subsector
->sector
->heightsec
;
531 if (heightsec
!= -1) // only clip things which are in special sectors
533 int phs
= viewplayer
->mo
->subsector
->sector
->heightsec
;
534 if (phs
!= -1 && viewz
< sectors
[phs
].floorheight
?
535 thing
->z
>= sectors
[heightsec
].floorheight
:
536 gzt
< sectors
[heightsec
].floorheight
)
538 if (phs
!= -1 && viewz
> sectors
[phs
].ceilingheight
?
539 gzt
< sectors
[heightsec
].ceilingheight
&&
540 viewz
>= sectors
[heightsec
].ceilingheight
:
541 thing
->z
>= sectors
[heightsec
].ceilingheight
)
545 // store information in a vissprite
546 vis
= R_NewVisSprite ();
548 // killough 3/27/98: save sector for special clipping later
549 vis
->heightsec
= heightsec
;
551 vis
->mobjflags
= thing
->flags
;
552 // proff 11/06/98: Changed for high-res
553 vis
->scale
= FixedDiv(projectiony
, tz
);
557 vis
->gzt
= gzt
; // killough 3/27/98
558 vis
->texturemid
= vis
->gzt
- viewz
;
559 vis
->x1
= x1
< 0 ? 0 : x1
;
560 vis
->x2
= x2
>= viewwidth
? viewwidth
-1 : x2
;
561 iscale
= FixedDiv (FRACUNIT
, xscale
);
565 vis
->startfrac
= spritewidth
[lump
]-1;
566 vis
->xiscale
= -iscale
;
571 vis
->xiscale
= iscale
;
575 vis
->startfrac
+= vis
->xiscale
*(vis
->x1
-x1
);
579 if (thing
->flags
& MF_SHADOW
)
580 vis
->colormap
= NULL
; // shadow draw
581 else if (fixedcolormap
)
582 vis
->colormap
= fixedcolormap
; // fixed map
583 else if (thing
->frame
& FF_FULLBRIGHT
)
584 vis
->colormap
= fullcolormap
; // full bright // killough 3/20/98
586 { // diminished light
587 int index
= xscale
>>LIGHTSCALESHIFT
;
588 if (index
>= MAXLIGHTSCALE
)
589 index
= MAXLIGHTSCALE
-1;
590 vis
->colormap
= spritelights
[index
];
596 // During BSP traversal, this adds sprites by sector.
598 // killough 9/18/98: add lightlevel as parameter, fixing underwater lighting
599 void R_AddSprites(subsector_t
* subsec
, int lightlevel
)
601 sector_t
* sec
=subsec
->sector
;
605 // BSP is traversed by subsector.
606 // A sector might have been split into several
607 // subsectors during BSP building.
608 // Thus we check whether its already added.
610 if (sec
->validcount
== validcount
)
613 // Well, now it will be done.
614 sec
->validcount
= validcount
;
616 lightnum
= (lightlevel
>> LIGHTSEGSHIFT
)+extralight
;
619 spritelights
= scalelight
[0];
620 else if (lightnum
>= LIGHTLEVELS
)
621 spritelights
= scalelight
[LIGHTLEVELS
-1];
623 spritelights
= scalelight
[lightnum
];
625 // Handle all things in sector.
627 for (thing
= sec
->thinglist
; thing
; thing
= thing
->snext
)
628 R_ProjectSprite(thing
);
635 void R_DrawPSprite (pspdef_t
*psp
)
640 spriteframe_t
*sprframe
;
646 // decide which patch to use
650 if ( (unsigned)psp
->state
->sprite
>= (unsigned)numsprites
)
651 I_Error ("R_ProjectSprite: Invalid sprite number %i", psp
->state
->sprite
);
654 sprdef
= &sprites
[psp
->state
->sprite
];
658 if ( (psp
->state
->frame
& FF_FRAMEMASK
) >= sprdef
->numframes
)
659 I_Error ("R_ProjectSprite: Invalid sprite frame %i : %li",
660 psp
->state
->sprite
, psp
->state
->frame
);
663 sprframe
= &sprdef
->spriteframes
[psp
->state
->frame
& FF_FRAMEMASK
];
665 lump
= sprframe
->lump
[0];
666 flip
= (boolean
) sprframe
->flip
[0];
668 // calculate edges of the shape
669 tx
= psp
->sx
-160*FRACUNIT
;
671 tx
-= spriteoffset
[lump
];
672 x1
= (centerxfrac
+ FixedMul (tx
,pspritescale
))>>FRACBITS
;
674 // off the right side
678 tx
+= spritewidth
[lump
];
679 x2
= ((centerxfrac
+ FixedMul (tx
, pspritescale
) ) >>FRACBITS
) - 1;
685 // store information in a vissprite
688 // killough 12/98: fix psprite positioning problem
689 vis
->texturemid
= (BASEYCENTER
<<FRACBITS
) /* + FRACUNIT/2 */ -
690 (psp
->sy
-spritetopoffset
[lump
]);
691 vis
->x1
= x1
< 0 ? 0 : x1
;
692 vis
->x2
= x2
>= viewwidth
? viewwidth
-1 : x2
;
693 // proff 11/06/98: Added for high-res
694 vis
->scale
= pspriteyscale
;
698 vis
->xiscale
= -pspriteiscale
;
699 vis
->startfrac
= spritewidth
[lump
]-1;
703 vis
->xiscale
= pspriteiscale
;
708 vis
->startfrac
+= vis
->xiscale
*(vis
->x1
-x1
);
712 if (viewplayer
->powers
[pw_invisibility
] > 4*32
713 || viewplayer
->powers
[pw_invisibility
] & 8)
714 vis
->colormap
= NULL
; // shadow draw
715 else if (fixedcolormap
)
716 vis
->colormap
= fixedcolormap
; // fixed color
717 else if (psp
->state
->frame
& FF_FULLBRIGHT
)
718 vis
->colormap
= fullcolormap
; // full bright // killough 3/20/98
720 vis
->colormap
= spritelights
[MAXLIGHTSCALE
-1]; // local light
722 R_DrawVisSprite(vis
, vis
->x1
, vis
->x2
);
726 // R_DrawPlayerSprites
729 void R_DrawPlayerSprites(void)
735 lightnum
= (viewplayer
->mo
->subsector
->sector
->lightlevel
>> LIGHTSEGSHIFT
)
739 spritelights
= scalelight
[0];
740 else if (lightnum
>= LIGHTLEVELS
)
741 spritelights
= scalelight
[LIGHTLEVELS
-1];
743 spritelights
= scalelight
[lightnum
];
745 // clip to screen bounds
746 mfloorclip
= screenheightarray
;
747 mceilingclip
= negonearray
;
749 // add all active psprites
750 for (i
=0, psp
=viewplayer
->psprites
; i
<NUMPSPRITES
; i
++,psp
++)
758 // Rewritten by Lee Killough to avoid using unnecessary
759 // linked lists, and to use faster sorting algorithm.
762 #define bcopyp(d, s, n) memcpy(d, s, (n) * sizeof(void *))
764 // killough 9/2/98: merge sort
766 static void msort(vissprite_t
**s
, vissprite_t
**t
, int n
)
770 int n1
= n
/2, n2
= n
- n1
;
771 vissprite_t
**s1
= s
, **s2
= s
+ n1
, **d
= t
;
776 while ((*s1
)->scale
> (*s2
)->scale
?
777 (*d
++ = *s1
++, --n1
) : (*d
++ = *s2
++, --n2
))
790 for (i
= 1; i
< n
; i
++)
792 vissprite_t
*temp
= s
[i
];
793 if (s
[i
-1]->scale
< temp
->scale
)
796 while ((s
[j
] = s
[j
-1])->scale
< temp
->scale
&& --j
)
804 void R_SortVisSprites (void)
808 int i
= num_vissprite
;
810 // If we need to allocate more pointers for the vissprites,
811 // allocate as many as were allocated for sprites -- killough
812 // killough 9/22/98: allocate twice as many
814 if (num_vissprite_ptrs
< num_vissprite
*2)
816 free(vissprite_ptrs
); // better than realloc -- no preserving needed
817 vissprite_ptrs
= malloc((num_vissprite_ptrs
= num_vissprite_alloc
*2)
818 * sizeof *vissprite_ptrs
);
822 vissprite_ptrs
[i
] = vissprites
+i
;
824 // killough 9/22/98: replace qsort with merge sort, since the keys
825 // are roughly in order to begin with, due to BSP rendering.
827 msort(vissprite_ptrs
, vissprite_ptrs
+ num_vissprite
, num_vissprite
);
835 void R_DrawSprite (vissprite_t
* spr
)
838 short clipbot
[MAX_SCREENWIDTH
]; // killough 2/8/98:
839 short cliptop
[MAX_SCREENWIDTH
]; // change to MAX_*
846 for (x
= spr
->x1
; x
<=spr
->x2
; x
++)
847 clipbot
[x
] = cliptop
[x
] = -2;
849 // Scan drawsegs from end to start for obscuring segs.
850 // The first drawseg that has a greater scale is the clip seg.
852 // Modified by Lee Killough:
853 // (pointer check was originally nonportable
854 // and buggy, by going past LEFT end of array):
856 // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
858 for (ds
=ds_p
; ds
-- > drawsegs
; ) // new -- killough
859 { // determine if the drawseg obscures the sprite
860 if (ds
->x1
> spr
->x2
|| ds
->x2
< spr
->x1
||
861 (!ds
->silhouette
&& !ds
->maskedtexturecol
))
862 continue; // does not cover sprite
864 r1
= ds
->x1
< spr
->x1
? spr
->x1
: ds
->x1
;
865 r2
= ds
->x2
> spr
->x2
? spr
->x2
: ds
->x2
;
867 if (ds
->scale1
> ds
->scale2
)
869 lowscale
= ds
->scale2
;
874 lowscale
= ds
->scale1
;
878 if (scale
< spr
->scale
|| (lowscale
< spr
->scale
&&
879 !R_PointOnSegSide (spr
->gx
, spr
->gy
, ds
->curline
)))
881 if (ds
->maskedtexturecol
) // masked mid texture?
882 R_RenderMaskedSegRange(ds
, r1
, r2
);
883 continue; // seg is behind sprite
886 // clip this piece of the sprite
887 // killough 3/27/98: optimized and made much shorter
889 if (ds
->silhouette
&SIL_BOTTOM
&& spr
->gz
< ds
->bsilheight
) //bottom sil
890 for (x
=r1
; x
<=r2
; x
++)
891 if (clipbot
[x
] == -2)
892 clipbot
[x
] = ds
->sprbottomclip
[x
];
894 if (ds
->silhouette
&SIL_TOP
&& spr
->gzt
> ds
->tsilheight
) // top sil
895 for (x
=r1
; x
<=r2
; x
++)
896 if (cliptop
[x
] == -2)
897 cliptop
[x
] = ds
->sprtopclip
[x
];
901 // Clip the sprite against deep water and/or fake ceilings.
902 // killough 4/9/98: optimize by adding mh
903 // killough 4/11/98: improve sprite clipping for underwater/fake ceilings
904 // killough 11/98: fix disappearing sprites
906 if (spr
->heightsec
!= -1) // only things in specially marked sectors
909 int phs
= viewplayer
->mo
->subsector
->sector
->heightsec
;
910 if ((mh
= sectors
[spr
->heightsec
].floorheight
) > spr
->gz
&&
911 (h
= centeryfrac
- FixedMul(mh
-=viewz
, spr
->scale
)) >= 0 &&
912 (h
>>= FRACBITS
) < viewheight
)
914 if (mh
<= 0 || (phs
!= -1 && viewz
> sectors
[phs
].floorheight
))
916 for (x
=spr
->x1
; x
<=spr
->x2
; x
++)
917 if (clipbot
[x
] == -2 || h
< clipbot
[x
])
921 if (phs
!= -1 && viewz
<= sectors
[phs
].floorheight
) // killough 11/98
922 for (x
=spr
->x1
; x
<=spr
->x2
; x
++)
923 if (cliptop
[x
] == -2 || h
> cliptop
[x
])
927 if ((mh
= sectors
[spr
->heightsec
].ceilingheight
) < spr
->gzt
&&
928 (h
= centeryfrac
- FixedMul(mh
-viewz
, spr
->scale
)) >= 0 &&
929 (h
>>= FRACBITS
) < viewheight
)
931 if (phs
!= -1 && viewz
>= sectors
[phs
].ceilingheight
)
933 for (x
=spr
->x1
; x
<=spr
->x2
; x
++)
934 if (clipbot
[x
] == -2 || h
< clipbot
[x
])
938 for (x
=spr
->x1
; x
<=spr
->x2
; x
++)
939 if (cliptop
[x
] == -2 || h
> cliptop
[x
])
943 // killough 3/27/98: end special clipping for deep water / fake ceilings
945 // all clipping has been performed, so draw the sprite
946 // check for unclipped columns
948 for (x
= spr
->x1
; x
<=spr
->x2
; x
++)
950 if (clipbot
[x
] == -2)
951 clipbot
[x
] = viewheight
;
953 if (cliptop
[x
] == -2)
957 mfloorclip
= clipbot
;
958 mceilingclip
= cliptop
;
959 R_DrawVisSprite (spr
, spr
->x1
, spr
->x2
);
966 void R_DrawMasked(void)
973 // draw all vissprites back to front
975 // rendered_vissprites = num_vissprite;
976 for (i
= num_vissprite
;--i
>=0; )
977 R_DrawSprite(vissprite_ptrs
[i
]); // killough
979 // render any remaining masked mid textures
981 // Modified by Lee Killough:
982 // (pointer check was originally nonportable
983 // and buggy, by going past LEFT end of array):
985 // for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
987 for (ds
=ds_p
; ds
-- > drawsegs
; ) // new -- killough
988 if (ds
->maskedtexturecol
)
989 R_RenderMaskedSegRange(ds
, ds
->x1
, ds
->x2
);
991 // draw the psprites on top of everything
992 // but does not draw on side views
993 if (!viewangleoffset
)
994 R_DrawPlayerSprites ();