- Changed all coordinates for DrawTexture() to floating point so that the

player sprites will retain the same precision they had when they were
  rendered as part of the 3D view. (needed for propery alignment of flashes
  on top of weapon sprites) It worked just fine for D3D, but software
  rendering was another matter. I consequently did battle with imprecisions
  in the whole masked texture drawing routines that had previously been
  partially masked by only drawing on whole pixel boundaries. Particularly,
  the tops of posts are calculated by multiplying by spryscale, and the
  texture mapping coordinates are calculated by multiplying by dc_iscale
  (where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point
  values, there is a significant variance. For best results, the drawing
  routines should only use one of these values, but that would mean
  introducing division into the inner loop. If the division removed the
  necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it?
  Or would the divide be slower than the fudging? Or would I be better off
  doing it like Build and using transparent pixel checks instead, not
  bothering with skipping transparent areas? For now, I chop off the
  fractional part of the top coordinate for software drawing, since it was
  the easiest thing to do (even if it wasn't the most correct thing to do).


SVN r1955 (trunk)
This commit is contained in:
Randy Heit 2009-11-01 01:27:33 +00:00
parent a4f4994e18
commit 4ebfdac887
10 changed files with 657 additions and 551 deletions

View file

@ -1,3 +1,24 @@
October 31, 2009
- Changed all coordinates for DrawTexture() to floating point so that the
player sprites will retain the same precision they had when they were
rendered as part of the 3D view. (needed for propery alignment of flashes
on top of weapon sprites) It worked just fine for D3D, but software
rendering was another matter. I consequently did battle with imprecisions
in the whole masked texture drawing routines that had previously been
partially masked by only drawing on whole pixel boundaries. Particularly,
the tops of posts are calculated by multiplying by spryscale, and the
texture mapping coordinates are calculated by multiplying by dc_iscale
(where dc_iscale = 1 / spryscale). Since these are both 16.16 fixed point
values, there is a significant variance. For best results, the drawing
routines should only use one of these values, but that would mean
introducing division into the inner loop. If the division removed the
necessity for the fudge code in R_DrawMaskedColumn(), would it be worth it?
Or would the divide be slower than the fudging? Or would I be better off
doing it like Build and using transparent pixel checks instead, not
bothering with skipping transparent areas? For now, I chop off the
fractional part of the top coordinate for software drawing, since it was
the easiest thing to do (even if it wasn't the most correct thing to do).
October 29, 2009
- Fixed: Sprites and decals that are drawn with addition must fade to black.
- Make TranslateToStartSpot() set the new sector references for a polyobj's

View file

@ -960,7 +960,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a
h = fg->GetScaledHeight() << FRACBITS;
if (Scaled)
{
screen->VirtualToRealCoords(x, y, w, h, 320, 200, true);
screen->VirtualToRealCoordsFixed(x, y, w, h, 320, 200, true);
}
x >>= FRACBITS;
y >>= FRACBITS;
@ -1018,7 +1018,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a
ch = (fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2) << FRACBITS;
if (Scaled)
{
screen->VirtualToRealCoords(cx, cy, cw, ch, 320, 200, true);
screen->VirtualToRealCoordsFixed(cx, cy, cw, ch, 320, 200, true);
}
cx >>= FRACBITS;
cy >>= FRACBITS;
@ -1480,7 +1480,7 @@ void DSBarInfo::DrawGraphic(FTexture* texture, SBarInfoCoordinate x, SBarInfoCoo
fixed_t fw = texture->GetScaledWidth() << FRACBITS;
fixed_t fh = texture->GetScaledHeight() << FRACBITS;
if(Scaled)
screen->VirtualToRealCoords(fx, fy, fw, fh, 320, 200, true);
screen->VirtualToRealCoordsFixed(fx, fy, fw, fh, 320, 200, true);
// Round to nearest
w = (fw + (FRACUNIT>>1)) >> FRACBITS;
h = (fh + (FRACUNIT>>1)) >> FRACBITS;

View file

@ -1848,9 +1848,9 @@ void R_DrawRemainingPlayerSprites()
}
screen->DrawTexture(vis->pic,
viewwindowx + VisPSpritesX1[i],
viewwindowy + viewheight/2 - MulScale32(vis->texturemid, vis->yscale) - 1,
DTA_DestWidth, FixedMul(vis->pic->GetWidth(), vis->xscale),
DTA_DestHeight, FixedMul(vis->pic->GetHeight(), vis->yscale),
viewwindowy + viewheight/2 - (vis->texturemid / 65536.0) * (vis->yscale / 65536.0) - 1,
DTA_DestWidthF, FIXED2FLOAT(vis->pic->GetWidth() * vis->xscale),
DTA_DestHeightF, FIXED2FLOAT(vis->pic->GetHeight() * vis->yscale),
DTA_Translation, TranslationToTable(vis->Translation),
DTA_FlipX, flip,
DTA_TopOffset, 0,

View file

@ -178,9 +178,13 @@ public:
int GetScaledWidth () { int foo = (Width << 17) / xScale; return (foo >> 1) + (foo & 1); }
int GetScaledHeight () { int foo = (Height << 17) / yScale; return (foo >> 1) + (foo & 1); }
double GetScaledWidthDouble () { return (Width * 65536.f) / xScale; }
double GetScaledHeightDouble () { return (Height * 65536.f) / yScale; }
int GetScaledLeftOffset () { int foo = (LeftOffset << 17) / xScale; return (foo >> 1) + (foo & 1); }
int GetScaledTopOffset () { int foo = (TopOffset << 17) / yScale; return (foo >> 1) + (foo & 1); }
double GetScaledLeftOffsetDouble() { return (LeftOffset * 65536.f) / xScale; }
double GetScaledTopOffsetDouble() { return (TopOffset * 65536.f) / yScale; }
virtual void SetFrontSkyLayer();

View file

@ -89,14 +89,14 @@ static int PalFromRGB(uint32 rgb)
return LastPal;
}
void STACK_ARGS DCanvas::DrawTexture (FTexture *img, int x, int y, int tags_first, ...)
void STACK_ARGS DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ...)
{
va_list tags;
va_start(tags, tags_first);
DrawTextureV(img, x, y, tags_first, tags);
}
void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, va_list tags)
void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, double x, double y, uint32 tag, va_list tags)
{
FTexture::Span unmaskedSpan[2];
const FTexture::Span **spanptr, *spans;
@ -154,8 +154,8 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
BYTE *destorgsave = dc_destorg;
dc_destorg = screen->GetBuffer();
fixed_t x0 = parms.x - Scale (parms.left, parms.destwidth, parms.texwidth);
fixed_t y0 = parms.y - Scale (parms.top, parms.destheight, parms.texheight);
double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth;
double y0 = parms.y - parms.top * parms.destheight / parms.texheight;
if (mode != DontDraw)
{
@ -174,31 +174,43 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
fixed_t centeryback = centeryfrac;
centeryfrac = 0;
sprtopscreen = y0;
spryscale = parms.destheight / img->GetHeight();
sprtopscreen = FLOAT2FIXED(y0);
// There is not enough precision in the drawing routines to keep the full
// precision for y0. :(
sprtopscreen &= ~(FRACUNIT - 1);
double yscale = parms.destheight / img->GetHeight();
double iyscale = 1 / yscale;
spryscale = FLOAT2FIXED(yscale);
#if 0
// Fix precision errors that are noticeable at some resolutions
if (((y0 + parms.destheight) >> FRACBITS) > ((y0 + spryscale * img->GetHeight()) >> FRACBITS))
if ((y0 + parms.destheight) > (y0 + yscale * img->GetHeight()))
{
spryscale++;
}
#endif
sprflipvert = false;
dc_iscale = 0xffffffffu / (unsigned)spryscale;
dc_texturemid = FixedMul (-y0, dc_iscale);
//dc_iscale = FLOAT2FIXED(iyscale);
//dc_texturemid = FLOAT2FIXED((-y0) * iyscale);
//dc_iscale = 0xffffffffu / (unsigned)spryscale;
dc_iscale = DivScale32(1, spryscale);
dc_texturemid = FixedMul(-sprtopscreen, dc_iscale) + FixedMul(centeryfrac-FRACUNIT, dc_iscale);
fixed_t frac = 0;
fixed_t xiscale = DivScale32 (img->GetWidth(), parms.destwidth);
int x2 = (x0 + parms.destwidth) >> FRACBITS;
double xiscale = parms.texwidth / parms.destwidth;
double x2 = x0 + parms.destwidth;
if (bottomclipper[0] != parms.dclip)
{
clearbufshort (bottomclipper, screen->GetWidth(), (short)parms.dclip);
clearbufshort(bottomclipper, screen->GetWidth(), (short)parms.dclip);
}
if (parms.uclip != 0)
{
if (topclipper[0] != parms.uclip)
{
clearbufshort (topclipper, screen->GetWidth(), (short)parms.uclip);
clearbufshort(topclipper, screen->GetWidth(), (short)parms.uclip);
}
mceilingclip = topclipper;
}
@ -214,48 +226,53 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
xiscale = -xiscale;
}
dc_x = x0 >> FRACBITS;
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
fixed_t xscale = parms.destwidth / parms.texwidth;
dc_x += (parms.windowleft * xscale) >> FRACBITS;
frac += parms.windowleft << FRACBITS;
x2 -= ((parms.texwidth - parms.windowright) * xscale) >> FRACBITS;
double xscale = parms.destwidth / parms.texwidth;
x0 += parms.windowleft * xscale;
frac += FLOAT2FIXED(parms.windowleft);
x2 -= (parms.texwidth - parms.windowright) * xscale;
}
if (dc_x < parms.lclip)
if (x0 < parms.lclip)
{
frac += (parms.lclip - dc_x) * xiscale;
dc_x = parms.lclip;
frac += FLOAT2FIXED((parms.lclip - x0) * xiscale);
x0 = parms.lclip;
}
if (x2 > parms.rclip)
{
x2 = parms.rclip;
}
if (parms.destheight < 32*FRACUNIT)
// Drawing short output ought to fit in the data cache well enough
// if we draw one column at a time, so do that, since it's simpler.
if (parms.destheight < 32 || (parms.dclip - parms.uclip) < 32)
{
mode = DoDraw0;
}
dc_x = int(x0);
int x2_i = int(x2);
fixed_t xiscale_i = FLOAT2FIXED(xiscale);
if (mode == DoDraw0)
{
// One column at a time
stop4 = dc_x;
}
else // DoDraw1
else // DoDraw1`
{
// Up to four columns at a time
stop4 = x2 & ~3;
stop4 = x2_i & ~3;
}
if (dc_x < x2)
if (dc_x < x2_i)
{
while ((dc_x < stop4) && (dc_x & 3))
{
pixels = img->GetColumn (frac >> FRACBITS, spanptr);
R_DrawMaskedColumn (pixels, spans);
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumn(pixels, spans);
dc_x++;
frac += xiscale;
frac += xiscale_i;
}
while (dc_x < stop4)
@ -263,20 +280,20 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
rt_initcols();
for (int zz = 4; zz; --zz)
{
pixels = img->GetColumn (frac >> FRACBITS, spanptr);
R_DrawMaskedColumnHoriz (pixels, spans);
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumnHoriz(pixels, spans);
dc_x++;
frac += xiscale;
frac += xiscale_i;
}
rt_draw4cols (dc_x - 4);
rt_draw4cols(dc_x - 4);
}
while (dc_x < x2)
while (dc_x < x2_i)
{
pixels = img->GetColumn (frac >> FRACBITS, spanptr);
R_DrawMaskedColumn (pixels, spans);
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
R_DrawMaskedColumn(pixels, spans);
dc_x++;
frac += xiscale;
frac += xiscale_i;
}
}
centeryfrac = centeryback;
@ -287,11 +304,11 @@ void STACK_ARGS DCanvas::DrawTextureV(FTexture *img, int x, int y, uint32 tag, v
if (ticdup != 0 && menuactive == MENU_Off)
{
NetUpdate ();
NetUpdate();
}
}
bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const
bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool hw) const
{
INTBOOL boolval;
int intval;
@ -313,8 +330,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
virtBottom = false;
parms->texwidth = img->GetScaledWidth();
parms->texheight = img->GetScaledHeight();
parms->texwidth = img->GetScaledWidthDouble();
parms->texheight = img->GetScaledHeightDouble();
parms->windowleft = 0;
parms->windowright = parms->texwidth;
@ -322,8 +339,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->uclip = 0;
parms->lclip = 0;
parms->rclip = this->GetWidth();
parms->destwidth = parms->windowright << FRACBITS;
parms->destheight = parms->texheight << FRACBITS;
parms->destwidth = parms->windowright;
parms->destheight = parms->texheight;
parms->top = img->GetScaledTopOffset();
parms->left = img->GetScaledLeftOffset();
parms->alpha = FRACUNIT;
@ -344,10 +361,12 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
parms->specialcolormap = NULL;
parms->colormapstyle = NULL;
parms->x = x << FRACBITS;
parms->y = y << FRACBITS;
parms->x = x;
parms->y = y;
// Parse the tag list for attributes
// Parse the tag list for attributes. (For floating point attributes,
// consider that the C ABI dictates that all floats be promoted to
// doubles when passed as function arguments.)
while (tag != TAG_DONE)
{
va_list *more_p;
@ -357,11 +376,11 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
{
case TAG_IGNORE:
default:
data = va_arg (tags, DWORD);
data = va_arg(tags, DWORD);
break;
case TAG_MORE:
more_p = va_arg (tags, va_list *);
more_p = va_arg(tags, va_list *);
va_end (tags);
#ifndef NO_VA_COPY
va_copy (tags, *more_p);
@ -371,35 +390,43 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_DestWidth:
parms->destwidth = va_arg (tags, int) << FRACBITS;
parms->destwidth = va_arg(tags, int);
break;
case DTA_DestWidthF:
parms->destwidth = va_arg(tags, double);
break;
case DTA_DestHeight:
parms->destheight = va_arg (tags, int) << FRACBITS;
parms->destheight = va_arg(tags, int);
break;
case DTA_DestHeightF:
parms->destheight = va_arg(tags, double);
break;
case DTA_Clean:
boolval = va_arg (tags, INTBOOL);
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->x = (parms->x - 160*FRACUNIT) * CleanXfac + (Width * (FRACUNIT/2));
parms->y = (parms->y - 100*FRACUNIT) * CleanYfac + (Height * (FRACUNIT/2));
parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT;
parms->destheight = parms->texheight * CleanYfac * FRACUNIT;
parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5);
parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5);
parms->destwidth = parms->texwidth * CleanXfac;
parms->destheight = parms->texheight * CleanYfac;
}
break;
case DTA_CleanNoMove:
boolval = va_arg (tags, INTBOOL);
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT;
parms->destheight = parms->texheight * CleanYfac * FRACUNIT;
parms->destwidth = parms->texwidth * CleanXfac;
parms->destheight = parms->texheight * CleanYfac;
}
break;
case DTA_320x200:
boolval = va_arg (tags, INTBOOL);
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->virtWidth = 320;
@ -408,7 +435,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_Bottom320x200:
boolval = va_arg (tags, INTBOOL);
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->virtWidth = 320;
@ -421,99 +448,123 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
{
bool xright = parms->x < 0;
bool ybot = parms->y < 0;
intval = va_arg (tags, int);
intval = va_arg(tags, int);
if (hud_scale)
{
parms->x *= CleanXfac;
if (intval == HUD_HorizCenter)
parms->x += Width * FRACUNIT / 2;
parms->x += Width * 0.5;
else if (xright)
parms->x = Width * FRACUNIT + parms->x;
parms->x = Width + parms->x;
parms->y *= CleanYfac;
if (ybot)
parms->y = Height * FRACUNIT + parms->y;
parms->destwidth = parms->texwidth * CleanXfac * FRACUNIT;
parms->destheight = parms->texheight * CleanYfac * FRACUNIT;
parms->y = Height + parms->y;
parms->destwidth = parms->texwidth * CleanXfac;
parms->destheight = parms->texheight * CleanYfac;
}
else
{
if (intval == HUD_HorizCenter)
parms->x += Width * FRACUNIT / 2;
parms->x += Width * 0.5;
else if (xright)
parms->x = Width * FRACUNIT + parms->x;
parms->x = Width + parms->x;
if (ybot)
parms->y = Height * FRACUNIT + parms->y;
parms->y = Height + parms->y;
}
}
break;
case DTA_VirtualWidth:
parms->virtWidth = va_arg (tags, int);
parms->virtWidth = va_arg(tags, int);
break;
case DTA_VirtualWidthF:
parms->virtWidth = va_arg(tags, double);
break;
case DTA_VirtualHeight:
parms->virtHeight = va_arg (tags, int);
parms->virtHeight = va_arg(tags, int);
break;
case DTA_VirtualHeightF:
parms->virtHeight = va_arg(tags, double);
break;
case DTA_Alpha:
parms->alpha = MIN<fixed_t> (FRACUNIT, va_arg (tags, fixed_t));
parms->alpha = MIN<fixed_t>(FRACUNIT, va_arg (tags, fixed_t));
break;
case DTA_AlphaChannel:
parms->alphaChannel = va_arg (tags, INTBOOL);
parms->alphaChannel = va_arg(tags, INTBOOL);
break;
case DTA_FillColor:
parms->fillcolor = va_arg (tags, int);
parms->fillcolor = va_arg(tags, uint32);
break;
case DTA_Translation:
parms->remap = va_arg (tags, FRemapTable *);
parms->remap = va_arg(tags, FRemapTable *);
break;
case DTA_ColorOverlay:
parms->colorOverlay = va_arg (tags, DWORD);
parms->colorOverlay = va_arg(tags, DWORD);
break;
case DTA_FlipX:
parms->flipX = va_arg (tags, INTBOOL);
parms->flipX = va_arg(tags, INTBOOL);
break;
case DTA_TopOffset:
parms->top = va_arg (tags, int);
parms->top = va_arg(tags, int);
break;
case DTA_TopOffsetF:
parms->top = va_arg(tags, double);
break;
case DTA_LeftOffset:
parms->left = va_arg (tags, int);
parms->left = va_arg(tags, int);
break;
case DTA_LeftOffsetF:
parms->left = va_arg(tags, double);
break;
case DTA_CenterOffset:
if (va_arg (tags, int))
if (va_arg(tags, int))
{
parms->left = parms->texwidth / 2;
parms->top = parms->texheight / 2;
parms->left = parms->texwidth * 0.5;
parms->top = parms->texheight * 0.5;
}
break;
case DTA_CenterBottomOffset:
if (va_arg (tags, int))
if (va_arg(tags, int))
{
parms->left = parms->texwidth / 2;
parms->left = parms->texwidth * 0.5;
parms->top = parms->texheight;
}
break;
case DTA_WindowLeft:
parms->windowleft = va_arg (tags, int);
parms->windowleft = va_arg(tags, int);
break;
case DTA_WindowLeftF:
parms->windowleft = va_arg(tags, double);
break;
case DTA_WindowRight:
parms->windowright = va_arg (tags, int);
parms->windowright = va_arg(tags, int);
break;
case DTA_WindowRightF:
parms->windowright = va_arg(tags, double);
break;
case DTA_ClipTop:
parms->uclip = va_arg (tags, int);
parms->uclip = va_arg(tags, int);
if (parms->uclip < 0)
{
parms->uclip = 0;
@ -521,7 +572,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_ClipBottom:
parms->dclip = va_arg (tags, int);
parms->dclip = va_arg(tags, int);
if (parms->dclip > this->GetHeight())
{
parms->dclip = this->GetHeight();
@ -529,7 +580,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_ClipLeft:
parms->lclip = va_arg (tags, int);
parms->lclip = va_arg(tags, int);
if (parms->lclip < 0)
{
parms->lclip = 0;
@ -537,7 +588,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_ClipRight:
parms->rclip = va_arg (tags, int);
parms->rclip = va_arg(tags, int);
if (parms->rclip > this->GetWidth())
{
parms->rclip = this->GetWidth();
@ -545,15 +596,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_ShadowAlpha:
parms->shadowAlpha = MIN<fixed_t> (FRACUNIT, va_arg (tags, fixed_t));
parms->shadowAlpha = MIN<fixed_t>(FRACUNIT, va_arg (tags, fixed_t));
break;
case DTA_ShadowColor:
parms->shadowColor = va_arg (tags, int);
parms->shadowColor = va_arg(tags, int);
break;
case DTA_Shadow:
boolval = va_arg (tags, INTBOOL);
boolval = va_arg(tags, INTBOOL);
if (boolval)
{
parms->shadowAlpha = FRACUNIT/2;
@ -566,32 +617,32 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break;
case DTA_Masked:
parms->masked = va_arg (tags, INTBOOL);
parms->masked = va_arg(tags, INTBOOL);
break;
case DTA_BilinearFilter:
parms->bilinear = va_arg (tags, INTBOOL);
parms->bilinear = va_arg(tags, INTBOOL);
break;
case DTA_KeepRatio:
// I think this is a terribly misleading name, since it actually turns
// *off* aspect ratio correction.
parms->keepratio = va_arg (tags, INTBOOL);
parms->keepratio = va_arg(tags, INTBOOL);
break;
case DTA_RenderStyle:
parms->style.AsDWORD = va_arg (tags, DWORD);
parms->style.AsDWORD = va_arg(tags, DWORD);
break;
case DTA_SpecialColormap:
parms->specialcolormap = va_arg (tags, FSpecialColormap *);
parms->specialcolormap = va_arg(tags, FSpecialColormap *);
break;
case DTA_ColormapStyle:
parms->colormapstyle = va_arg (tags, FColormapStyle *);
parms->colormapstyle = va_arg(tags, FColormapStyle *);
break;
}
tag = va_arg (tags, DWORD);
tag = va_arg(tags, DWORD);
}
va_end (tags);
@ -645,66 +696,72 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
return true;
}
void DCanvas::VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h,
double vwidth, double vheight, bool vbottom, bool handleaspect) const
{
int myratio = handleaspect ? CheckRatio (Width, Height) : 0;
int right = x + w;
int bottom = y + h;
double right = x + w;
double bottom = y + h;
if (myratio != 0 && myratio != 4)
{ // The target surface is either 16:9 or 16:10, so expand the
// specified virtual size to avoid undesired stretching of the
// image. Does not handle non-4:3 virtual sizes. I'll worry about
// those if somebody expresses a desire to use them.
x = Scale(x - vwidth*FRACUNIT/2,
Width*960,
vwidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2;
w = Scale(right - vwidth*FRACUNIT/2,
Width*960,
vwidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2 - x;
x = (x - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5;
w = (right - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5 - x;
}
else
{
x = Scale (x, Width, vwidth);
w = Scale (right, Width, vwidth) - x;
x = x * Width / vwidth;
w = right * Width / vwidth - x;
}
if (myratio == 4)
{ // The target surface is 5:4
y = Scale(y - vheight*FRACUNIT/2,
Height*600,
vheight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2;
h = Scale(bottom - vheight*FRACUNIT/2,
Height*600,
vheight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2 - y;
y = (y - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5;
h = (bottom - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5 - y;
if (vbottom)
{
y += (Height - Height * BaseRatioSizes[myratio][3] / 48) << (FRACBITS - 1);
y += (Height - Height * BaseRatioSizes[myratio][3] / 48.0) * 0.5;
}
}
else
{
y = Scale (y, Height, vheight);
h = Scale (bottom, Height, vheight) - y;
y = y * Height / vheight;
h = bottom * Height / vheight - y;
}
}
void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
{
double dx, dy, dw, dh;
dx = FIXED2FLOAT(x);
dy = FIXED2FLOAT(y);
dw = FIXED2FLOAT(w);
dh = FIXED2FLOAT(h);
VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect);
x = FLOAT2FIXED(dx);
y = FLOAT2FIXED(dy);
w = FLOAT2FIXED(dw);
h = FLOAT2FIXED(dh);
}
void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
{
x <<= FRACBITS;
y <<= FRACBITS;
w <<= FRACBITS;
h <<= FRACBITS;
VirtualToRealCoords(x, y, w, h, vwidth, vheight, vbottom, handleaspect);
x >>= FRACBITS;
y >>= FRACBITS;
w >>= FRACBITS;
h >>= FRACBITS;
double dx, dy, dw, dh;
dx = x;
dy = y;
dw = w;
dh = h;
VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect);
x = int(dx + 0.5);
y = int(dy + 0.5);
w = int(dx + dw + 0.5) - x;
h = int(dy + dh + 0.5) - y;
}
void DCanvas::FillBorder (FTexture *img)

View file

@ -87,8 +87,8 @@ enum
DTA_VirtualHeight, // pretend the canvas is this tall
DTA_TopOffset, // override texture's top offset
DTA_LeftOffset, // override texture's left offset
DTA_CenterOffset, // override texture's left and top offsets and set them for the texture's middle
DTA_CenterBottomOffset,// override texture's left and top offsets and set them for the texture's bottom middle
DTA_CenterOffset, // bool: override texture's left and top offsets and set them for the texture's middle
DTA_CenterBottomOffset,// bool: override texture's left and top offsets and set them for the texture's bottom middle
DTA_WindowLeft, // don't draw anything left of this column (on source, not dest)
DTA_WindowRight, // don't draw anything at or to the right of this column (on source, not dest)
DTA_ClipTop, // don't draw anything above this row (on dest, not source)
@ -104,6 +104,16 @@ enum
DTA_SpecialColormap,// pointer to FSpecialColormapParameters (likely to be forever hardware-only)
DTA_ColormapStyle, // pointer to FColormapStyle (hardware-only)
// floating point duplicates of some of the above:
DTA_DestWidthF,
DTA_DestHeightF,
DTA_TopOffsetF,
DTA_LeftOffsetF,
DTA_VirtualWidthF,
DTA_VirtualHeightF,
DTA_WindowLeftF,
DTA_WindowRightF,
// For DrawText calls:
DTA_TextLen, // stop after this many characters, even if \0 not hit
DTA_CellX, // horizontal size of character cell
@ -188,9 +198,12 @@ public:
// Text drawing functions -----------------------------------------------
// 2D Texture drawing
void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...);
void STACK_ARGS DrawTexture (FTexture *img, double x, double y, int tags, ...);
void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
void VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const;
// Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead.
void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
// 2D Text drawing
@ -199,21 +212,23 @@ public:
struct DrawParms
{
fixed_t x, y;
int texwidth;
int texheight;
int windowleft;
int windowright;
double x, y;
double texwidth;
double texheight;
double destwidth;
double destheight;
double virtWidth;
double virtHeight;
double windowleft;
double windowright;
int dclip;
int uclip;
int lclip;
int rclip;
fixed_t destwidth;
fixed_t destheight;
int top;
int left;
double top;
double left;
fixed_t alpha;
int fillcolor;
uint32 fillcolor;
FRemapTable *remap;
const BYTE *translation;
DWORD colorOverlay;
@ -221,8 +236,6 @@ public:
INTBOOL flipX;
fixed_t shadowAlpha;
int shadowColor;
int virtWidth;
int virtHeight;
INTBOOL keepratio;
INTBOOL masked;
INTBOOL bilinear;
@ -239,8 +252,8 @@ protected:
int LockCount;
bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const;
virtual void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
bool ParseDrawTextureTags (FTexture *img, int x, int y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const;
virtual void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags);
bool ParseDrawTextureTags (FTexture *img, double x, double y, uint32 tag, va_list tags, DrawParms *parms, bool hw) const;
DCanvas() {}
@ -339,7 +352,7 @@ public:
// Tells the device to recreate itself with the new setting from vid_refreshrate.
virtual void NewRefreshRate ();
// Set the rect defining the area effected by blending.
// Set the rect defining the area affected by blending.
virtual void SetBlendingRect (int x1, int y1, int x2, int y2);
// render 3D view
@ -470,6 +483,7 @@ extern "C" void ASM_PatchPitch (void);
#endif
int CheckRatio (int width, int height);
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
extern const int BaseRatioSizes[5][4];

View file

@ -1231,6 +1231,6 @@ typedef TMatrix3x3<float> FMatrix3x3;
typedef TAngle<float> FAngle;
#define FLOAT2FIXED(f) fixed_t((f) * float(65536))
#define FIXED2FLOAT(f) (float(f) / float(65536))
#define FIXED2FLOAT(f) ((f) / float(65536))
#endif

View file

@ -2734,7 +2734,7 @@ void D3DFB::DrawPixel(int x, int y, int palcolor, uint32 color)
//
//==========================================================================
void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_first, va_list tags)
void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, double x, double y, uint32 tags_first, va_list tags)
{
if (In2D < 2)
{
@ -2759,17 +2759,17 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
CheckQuadBatch();
float xscale = float(parms.destwidth) / parms.texwidth / 65536.f;
float yscale = float(parms.destheight) / parms.texheight / 65536.f;
float x0 = float(parms.x) / 65536.f - float(parms.left) * xscale;
float y0 = float(parms.y) / 65536.f - float(parms.top) * yscale;
float x1 = x0 + float(parms.destwidth) / 65536.f;
float y1 = y0 + float(parms.destheight) / 65536.f;
double xscale = parms.destwidth / parms.texwidth;
double yscale = parms.destheight / parms.texheight;
double x0 = parms.x - parms.left * xscale;
double y0 = parms.y - parms.top * yscale;
double x1 = x0 + parms.destwidth;
double y1 = y0 + parms.destheight;
float u0 = tex->Box->Left;
float v0 = tex->Box->Top;
float u1 = tex->Box->Right;
float v1 = tex->Box->Bottom;
float uscale = 1.f / tex->Box->Owner->Width;
double uscale = 1.f / tex->Box->Owner->Width;
bool scissoring = false;
if (parms.flipX)
@ -2779,9 +2779,9 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
if (parms.windowleft > 0 || parms.windowright < parms.texwidth)
{
x0 += parms.windowleft * xscale;
u0 += parms.windowleft * uscale;
u0 = float(u0 + parms.windowleft * uscale);
x1 -= (parms.texwidth - parms.windowright) * xscale;
u1 -= (parms.texwidth - parms.windowright) * uscale;
u1 = float(u1 - (parms.texwidth - parms.windowright) * uscale);
}
#if 0
float vscale = 1.f / tex->Box->Owner->Height / yscale;
@ -2841,6 +2841,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
float yoffs = GatheringWipeScreen ? 0.5f : 0.5f - LBOffset;
#if 0
// Coordinates are truncated to integers, because that's effectively
// what the software renderer does. The hardware will instead round
// to nearest, it seems.
@ -2848,11 +2849,18 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
y0 = floorf(y0) - yoffs;
x1 = floorf(x1) - 0.5f;
y1 = floorf(y1) - yoffs;
#else
x0 = x0 - 0.5f;
y0 = y0 - yoffs;
x1 = x1 - 0.5f;
y1 = y1 - yoffs;
#endif
FBVERTEX *vert = &VertexData[VertexPos];
vert[0].x = x0;
vert[0].y = y0;
// Fill the vertex buffer.
vert[0].x = float(x0);
vert[0].y = float(y0);
vert[0].z = 0;
vert[0].rhw = 1;
vert[0].color0 = color0;
@ -2860,8 +2868,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
vert[0].tu = u0;
vert[0].tv = v0;
vert[1].x = x1;
vert[1].y = y0;
vert[1].x = float(x1);
vert[1].y = float(y0);
vert[1].z = 0;
vert[1].rhw = 1;
vert[1].color0 = color0;
@ -2869,8 +2877,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
vert[1].tu = u1;
vert[1].tv = v0;
vert[2].x = x1;
vert[2].y = y1;
vert[2].x = float(x1);
vert[2].y = float(y1);
vert[2].z = 0;
vert[2].rhw = 1;
vert[2].color0 = color0;
@ -2878,8 +2886,8 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
vert[2].tu = u1;
vert[2].tv = v1;
vert[3].x = x0;
vert[3].y = y1;
vert[3].x = float(x0);
vert[3].y = float(y1);
vert[3].z = 0;
vert[3].rhw = 1;
vert[3].color0 = color0;
@ -2887,6 +2895,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
vert[3].tu = u0;
vert[3].tv = v1;
// Fill the vertex index buffer.
IndexData[IndexPos ] = VertexPos;
IndexData[IndexPos + 1] = VertexPos + 1;
IndexData[IndexPos + 2] = VertexPos + 2;
@ -2894,6 +2903,7 @@ void STACK_ARGS D3DFB::DrawTextureV (FTexture *img, int x, int y, uint32 tags_fi
IndexData[IndexPos + 4] = VertexPos + 2;
IndexData[IndexPos + 5] = VertexPos + 3;
// Batch the quad.
QuadBatchPos++;
VertexPos += 4;
IndexPos += 6;

View file

@ -248,7 +248,7 @@ public:
void DrawBlendingRect ();
FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping);
FNativePalette *CreatePalette (FRemapTable *remap);
void STACK_ARGS DrawTextureV (FTexture *img, int x, int y, uint32 tag, va_list tags);
void STACK_ARGS DrawTextureV (FTexture *img, double x, double y, uint32 tag, va_list tags);
void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color);
void Dim (PalEntry color, float amount, int x1, int y1, int w, int h);
void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin);

File diff suppressed because it is too large Load diff