Fix dancing sprites due to texture coordinate calculations not taking pixel centers into account

Merge R_DrawMaskedColumn and R_DrawMaskedColumnHoriz into one function to remove code duplication
This commit is contained in:
Magnus Norddahl 2016-10-29 05:35:41 +02:00
commit 837ed7bd80
6 changed files with 61 additions and 181 deletions

View file

@ -250,19 +250,17 @@ double sprtopscreen;
bool sprflipvert;
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span)
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span, bool useRt)
{
const fixed_t centeryfrac = FLOAT2FIXED(CenterY);
const fixed_t texturemid = FLOAT2FIXED(dc_texturemid);
while (span->Length != 0)
{
const int length = span->Length;
const int top = span->TopOffset;
// calculate unclipped screen coordinates for post
dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top);
dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1;
dc_yl = (int)(sprtopscreen + spryscale * top);
dc_yh = (int)(sprtopscreen + spryscale * (top + length)) - 1;
if (sprflipvert)
{
swapvalues (dc_yl, dc_yh);
@ -279,56 +277,20 @@ void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span)
if (dc_yl <= dc_yh)
{
if (sprflipvert)
{
dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
- FixedMul (centeryfrac, dc_iscale) - texturemid;
const fixed_t maxfrac = length << FRACBITS;
while (dc_texturefrac >= maxfrac)
{
if (++dc_yl > dc_yh)
goto nextpost;
dc_texturefrac += dc_iscale;
}
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
while (endfrac < 0)
{
if (--dc_yh < dc_yl)
goto nextpost;
endfrac -= dc_iscale;
}
}
else
{
dc_texturefrac = texturemid - (top << FRACBITS)
+ (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
while (dc_texturefrac < 0)
{
if (++dc_yl > dc_yh)
goto nextpost;
dc_texturefrac += dc_iscale;
}
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
const fixed_t maxfrac = length << FRACBITS;
if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale)
{
dc_yh++;
}
else while (endfrac >= maxfrac)
{
if (--dc_yh < dc_yl)
goto nextpost;
endfrac -= dc_iscale;
}
}
dc_source = column + top;
dc_dest = ylookup[dc_yl] + dc_x + dc_destorg;
dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale);
dc_source = column;
dc_dest = (ylookup[dc_yl] + dc_x) + dc_destorg;
dc_count = dc_yh - dc_yl + 1;
colfunc ();
if (useRt)
hcolfunc_pre();
else
colfunc ();
}
nextpost:
span++;
}
if (sprflipvert && useRt)
rt_flip_posts();
}
// [ZZ]
@ -470,7 +432,7 @@ void R_DrawVisSprite (vissprite_t *vis)
{
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
R_DrawMaskedColumn (pixels, spans);
R_DrawMaskedColumn (pixels, spans, false);
dc_x++;
frac += xiscale;
}
@ -482,7 +444,7 @@ void R_DrawVisSprite (vissprite_t *vis)
{
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
R_DrawMaskedColumnHoriz (pixels, spans);
R_DrawMaskedColumn (pixels, spans, true);
dc_x++;
frac += xiscale;
}
@ -493,7 +455,7 @@ void R_DrawVisSprite (vissprite_t *vis)
{
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
R_DrawMaskedColumn (pixels, spans);
R_DrawMaskedColumn (pixels, spans, false);
dc_x++;
frac += xiscale;
}
@ -603,7 +565,7 @@ void R_DrawWallSprite(vissprite_t *spr)
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
}
if (!R_ClipSpriteColumnWithPortals(spr))
R_WallSpriteColumn(R_DrawMaskedColumn);
R_WallSpriteColumn(false);
dc_x++;
}
@ -617,7 +579,7 @@ void R_DrawWallSprite(vissprite_t *spr)
for (int zz = 4; zz; --zz)
{
if (!R_ClipSpriteColumnWithPortals(spr))
R_WallSpriteColumn(R_DrawMaskedColumnHoriz);
R_WallSpriteColumn(true);
dc_x++;
}
rt_draw4cols(dc_x - 4);
@ -630,14 +592,14 @@ void R_DrawWallSprite(vissprite_t *spr)
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
}
if (!R_ClipSpriteColumnWithPortals(spr))
R_WallSpriteColumn(R_DrawMaskedColumn);
R_WallSpriteColumn(false);
dc_x++;
}
}
R_FinishSetPatchStyle();
}
void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans))
void R_WallSpriteColumn (bool useRt)
{
float iscale = swall[dc_x] * MaskedScaleY;
dc_iscale = FLOAT2FIXED(iscale);
@ -651,7 +613,7 @@ void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Sp
const FTexture::Span *spans;
column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans);
dc_texturefrac = 0;
drawfunc (column, spans);
R_DrawMaskedColumn(column, spans, useRt);
rw_light += rw_lightstep;
}
@ -984,21 +946,23 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
const double thingxscalemul = spriteScale.X / tex->Scale.X;
tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->LeftOffset - 1) : tex->LeftOffset) * thingxscalemul;
x1 = centerx + xs_RoundToInt(tx * xscale);
double dtx1 = tx * xscale;
x1 = centerx + xs_RoundToInt(dtx1);
// off the right side?
if (x1 >= WindowRight)
return;
tx += tex->GetWidth() * thingxscalemul;
x2 = centerx + xs_RoundToInt(tx * xscale);
double dtx2 = tx * xscale;
x2 = centerx + xs_RoundToInt(dtx2);
// off the left side or too small?
if ((x2 < WindowLeft || x2 <= x1))
return;
xscale = spriteScale.X * xscale / tex->Scale.X;
iscale = (tex->GetWidth() << FRACBITS) / (x2 - x1);
iscale = (fixed_t)(tex->GetWidth() / (dtx2 - dtx1) * FRACUNIT);
double yscale = spriteScale.Y / tex->Scale.Y;
@ -1026,8 +990,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
vis->xiscale = iscale;
}
if (vis->x1 > x1)
vis->startfrac += vis->xiscale * (vis->x1 - x1);
vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - centerx - dtx1 + 0.5 * thingxscalemul));
}
else
{