* Change the order of operations such that linkdraw sprites aren't ever used for ordering comparisons with non-linkdraw sprites.

* Refactor of the unbundling to not involve modifying the next/prev links.
* Make the booleans in vissprite_t use flags stored in sprite->cut instead.
* Make the linkdrawn sprites much more linked - ie, same brightness (unless independently fullbright), same colormap, and don't draw if the tracer isn't being drawn.
* Other minor corrections.
This commit is contained in:
toasterbabe 2017-06-26 14:44:10 +01:00
parent 93dce12fce
commit 59ea08ee11
2 changed files with 95 additions and 86 deletions

View file

@ -887,12 +887,12 @@ static void R_DrawVisSprite(vissprite_t *vis)
this_scale = 1; this_scale = 1;
if (this_scale != FRACUNIT) if (this_scale != FRACUNIT)
{ {
if (!vis->isScaled) if (!(vis->cut & SC_ISSCALED))
{ {
vis->scale = FixedMul(vis->scale, this_scale); vis->scale = FixedMul(vis->scale, this_scale);
vis->scalestep = FixedMul(vis->scalestep, this_scale); vis->scalestep = FixedMul(vis->scalestep, this_scale);
vis->xiscale = FixedDiv(vis->xiscale,this_scale); vis->xiscale = FixedDiv(vis->xiscale,this_scale);
vis->isScaled = true; vis->cut |= SC_ISSCALED;
} }
dc_texturemid = FixedDiv(dc_texturemid,this_scale); dc_texturemid = FixedDiv(dc_texturemid,this_scale);
} }
@ -934,7 +934,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
dc_iscale = (0xffffffffu / (unsigned)spryscale); dc_iscale = (0xffffffffu / (unsigned)spryscale);
} }
if (vis->vflip) if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height); R_DrawFlippedMaskedColumn(column, patch->height);
else else
R_DrawMaskedColumn(column); R_DrawMaskedColumn(column);
@ -1013,7 +1013,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
// //
// R_SplitSprite // R_SplitSprite
// runs through a sector's lightlist and // runs through a sector's lightlist and
static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing) static void R_SplitSprite(vissprite_t *sprite)
{ {
INT32 i, lightnum, lindex; INT32 i, lightnum, lindex;
INT16 cutfrac; INT16 cutfrac;
@ -1049,7 +1049,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
// adjust the heights. // adjust the heights.
newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t)); newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t));
newsprite->cut |= (sprite->cut & SC_LINKDRAW); newsprite->cut |= (sprite->cut & SC_FLAGMASK);
sprite->cut |= SC_BOTTOM; sprite->cut |= SC_BOTTOM;
sprite->gz = testheight; sprite->gz = testheight;
@ -1083,15 +1083,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
newsprite->extra_colormap = sector->lightlist[i].extra_colormap; newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
/* if (!(newsprite->cut & SC_FULLBRIGHT))
if (thing->frame & FF_TRANSMASK)
;
else if (thing->flags2 & MF2_SHADOW)
;
else
*/
if (!((thing->frame & (FF_FULLBRIGHT|FF_TRANSMASK) || thing->flags2 & MF2_SHADOW)
&& (!newsprite->extra_colormap || !newsprite->extra_colormap->fog)))
{ {
lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
@ -1333,6 +1325,10 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t linkscale; fixed_t linkscale;
thing = thing->tracer; thing = thing->tracer;
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)
return;
tr_x = thing->x - viewx; tr_x = thing->x - viewx;
tr_y = thing->y - viewy; tr_y = thing->y - viewy;
gxt = FixedMul(tr_x, viewcos); gxt = FixedMul(tr_x, viewcos);
@ -1377,7 +1373,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (thing->subsector->sector->cullheight) if (thing->subsector->sector->cullheight)
{ {
if (R_DoCulling(oldthing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt))
return; return;
} }
@ -1508,6 +1504,7 @@ static void R_ProjectSprite(mobj_t *thing)
{ {
// full bright: goggles // full bright: goggles
vis->colormap = colormaps; vis->colormap = colormaps;
vis->cut |= SC_FULLBRIGHT;
} }
else else
{ {
@ -1520,14 +1517,11 @@ static void R_ProjectSprite(mobj_t *thing)
vis->colormap = spritelights[lindex]; vis->colormap = spritelights[lindex];
} }
vis->precip = false; if (vflip)
vis->cut |= SC_VFLIP;
vis->vflip = vflip;
vis->isScaled = false;
if (thing->subsector->sector->numlights) if (thing->subsector->sector->numlights)
R_SplitSprite(vis, oldthing); R_SplitSprite(vis);
// Debug // Debug
++objectsdrawn; ++objectsdrawn;
@ -1688,15 +1682,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->transmap = NULL; vis->transmap = NULL;
vis->mobjflags = 0; vis->mobjflags = 0;
vis->cut = SC_NONE; vis->cut = SC_PRECIP;
vis->extra_colormap = thing->subsector->sector->extra_colormap; vis->extra_colormap = thing->subsector->sector->extra_colormap;
vis->heightsec = thing->subsector->sector->heightsec; vis->heightsec = thing->subsector->sector->heightsec;
// Fullbright // Fullbright
vis->colormap = colormaps; vis->colormap = colormaps;
vis->precip = true;
vis->vflip = false;
vis->isScaled = false;
} }
// R_AddSprites // R_AddSprites
@ -1789,7 +1780,7 @@ static vissprite_t vsprsortedhead;
void R_SortVisSprites(void) void R_SortVisSprites(void)
{ {
UINT32 i; UINT32 i, linkedvissprites = 0;
vissprite_t *ds, *dsprev, *dsnext, *dsfirst; vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
vissprite_t *best = NULL; vissprite_t *best = NULL;
vissprite_t unsorted; vissprite_t unsorted;
@ -1826,42 +1817,14 @@ void R_SortVisSprites(void)
} }
unsorted.prev = ds; unsorted.prev = ds;
// pull the vissprites out by scale
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
for (i = 0; i < visspritecount; i++)
{
bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
{
if (ds->sortscale < bestscale)
{
bestscale = ds->sortscale;
bestdispoffset = ds->dispoffset;
best = ds;
}
// order visprites of same scale by dispoffset, smallest first
else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset)
{
bestdispoffset = ds->dispoffset;
best = ds;
}
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
}
// bundle linkdraw // bundle linkdraw
for (ds = vsprsortedhead.prev; ds != &vsprsortedhead; ds = ds->prev) for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev)
{ {
if (!(ds->cut & SC_LINKDRAW)) if (!(ds->cut & SC_LINKDRAW))
continue; continue;
// reuse dsfirst... // reuse dsfirst...
for (dsfirst = vsprsortedhead.prev; dsfirst != &vsprsortedhead; dsfirst = dsfirst->prev) for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev)
{ {
// don't connect if it's also a link // don't connect if it's also a link
if (dsfirst->cut & SC_LINKDRAW) if (dsfirst->cut & SC_LINKDRAW)
@ -1881,18 +1844,65 @@ void R_SortVisSprites(void)
&& dsfirst->sz < ds->sz) && dsfirst->sz < ds->sz)
continue; continue;
// remove from chain
ds->next->prev = ds->prev;
ds->prev->next = ds->next;
linkedvissprites++;
if (!(ds->cut & SC_FULLBRIGHT))
ds->colormap = dsfirst->colormap;
ds->extra_colormap = dsfirst->extra_colormap;
// reusing dsnext...
dsnext = dsfirst->linkdraw;
if (!dsnext || ds->dispoffset < dsnext->dispoffset)
{
ds->next = dsnext;
dsfirst->linkdraw = ds;
}
else
{
for (; dsnext->next != NULL; dsnext = dsnext->next)
if (ds->dispoffset < dsnext->next->dispoffset)
break;
ds->next = dsnext->next;
dsnext->next = ds;
}
break; break;
} }
}
// remove from chain // pull the vissprites out by scale
ds->next->prev = ds->prev; vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
ds->prev->next = ds->next; for (i = 0; i < visspritecount-linkedvissprites; i++)
{
if (dsfirst != &vsprsortedhead) bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
{ {
ds->next = dsfirst->linkdraw; if (ds->cut & SC_LINKDRAW)
dsfirst->linkdraw = ds; I_Error("No link made!"); // testing
if (ds->sortscale < bestscale)
{
bestscale = ds->sortscale;
bestdispoffset = ds->dispoffset;
best = ds;
}
// order visprites of same scale by dispoffset, smallest first
else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset)
{
bestdispoffset = ds->dispoffset;
best = ds;
}
} }
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
} }
} }
@ -2267,7 +2277,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
void R_ClipSprites(void) void R_ClipSprites(void)
{ {
vissprite_t *spr; vissprite_t *spr;
for (;clippedvissprites < visspritecount; clippedvissprites++) for (; clippedvissprites < visspritecount; clippedvissprites++)
{ {
drawseg_t *ds; drawseg_t *ds;
INT32 x; INT32 x;
@ -2488,29 +2498,22 @@ void R_DrawMasked(void)
next = r2->prev; next = r2->prev;
// Tails 08-18-2002 // Tails 08-18-2002
if (r2->sprite->precip == true) if (r2->sprite->cut & SC_PRECIP)
R_DrawPrecipitationSprite(r2->sprite); R_DrawPrecipitationSprite(r2->sprite);
else if (!r2->sprite->linkdraw) else if (!r2->sprite->linkdraw)
R_DrawSprite(r2->sprite); R_DrawSprite(r2->sprite);
else // unbundle linkdraw else // unbundle linkdraw
{ {
vissprite_t *ds = ds = r2->sprite->linkdraw; vissprite_t *ds = r2->sprite->linkdraw;
if (r2->sprite->dispoffset < ds->dispoffset) for (;
{ (ds != NULL && r2->sprite->dispoffset > ds->dispoffset);
r2->sprite->next = r2->sprite->linkdraw; ds = ds->next)
r2->sprite->linkdraw = r2->sprite; R_DrawSprite(ds);
}
else
{
for (; ds->next != NULL; ds = ds->next)
if (r2->sprite->dispoffset < ds->next->dispoffset)
break;
r2->sprite->next = ds->next;
ds->next = r2->sprite;
}
for (ds = r2->sprite->linkdraw; ds != NULL; ds = ds->next) R_DrawSprite(r2->sprite);
for (; ds != NULL; ds = ds->next)
R_DrawSprite(ds); R_DrawSprite(ds);
} }

View file

@ -127,10 +127,19 @@ typedef struct
// ----------- // -----------
typedef enum typedef enum
{ {
// actual cuts
SC_NONE = 0, SC_NONE = 0,
SC_TOP = 1, SC_TOP = 1,
SC_BOTTOM = 2, SC_BOTTOM = 1<<1,
SC_LINKDRAW = 4 // other flags
SC_PRECIP = 1<<2,
SC_LINKDRAW = 1<<3,
SC_FULLBRIGHT = 1<<4,
SC_VFLIP = 1<<5,
SC_ISSCALED = 1>>6,
// masks
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e; } spritecut_e;
// A vissprite_t is a thing that will be drawn during a refresh, // A vissprite_t is a thing that will be drawn during a refresh,
@ -141,7 +150,7 @@ typedef struct vissprite_s
struct vissprite_s *prev; struct vissprite_s *prev;
struct vissprite_s *next; struct vissprite_s *next;
// Bonus Linkdraw pointer. // Bonus linkdraw pointer.
struct vissprite_s *linkdraw; struct vissprite_s *linkdraw;
mobj_t *mobj; // for easy access mobj_t *mobj; // for easy access
@ -182,9 +191,6 @@ typedef struct vissprite_s
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
boolean precip;
boolean vflip; // Flip vertically
boolean isScaled;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} vissprite_t; } vissprite_t;