diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e10bcb43d..33919afc8 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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 diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 77c52c60f..0a986fbbb 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -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; diff --git a/src/r_things.cpp b/src/r_things.cpp index c03c162ba..ea4accfa3 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -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, diff --git a/src/textures/textures.h b/src/textures/textures.h index 0f595b5cb..b62da46d8 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -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(); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 05cd73c5c..7c05d9042 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -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 (FRACUNIT, va_arg (tags, fixed_t)); + parms->alpha = MIN(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 (FRACUNIT, va_arg (tags, fixed_t)); + parms->shadowAlpha = MIN(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) diff --git a/src/v_video.h b/src/v_video.h index 3109901bb..394ba319e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -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]; diff --git a/src/vectors.h b/src/vectors.h index f3b154aa2..ea11ab611 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -1231,6 +1231,6 @@ typedef TMatrix3x3 FMatrix3x3; typedef TAngle FAngle; #define FLOAT2FIXED(f) fixed_t((f) * float(65536)) -#define FIXED2FLOAT(f) (float(f) / float(65536)) +#define FIXED2FLOAT(f) ((f) / float(65536)) #endif diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index a776144ea..7e9197b0e 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -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; diff --git a/src/win32/win32iface.h b/src/win32/win32iface.h index 6c7c066b7..6cce6afe1 100644 --- a/src/win32/win32iface.h +++ b/src/win32/win32iface.h @@ -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); diff --git a/zdoom.vcproj b/zdoom.vcproj index 2a33a2c6b..681c2ce69 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1868,6 +1860,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2057,6 +2057,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2067,14 +2075,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5343,14 +5351,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5629,7 +5629,7 @@ />