From 00a9e94161c39cc0a83f00eb229d979a8b6e0291 Mon Sep 17 00:00:00 2001 From: yamamama Date: Tue, 3 Mar 2026 17:00:57 -0500 Subject: [PATCH] Make affines respect SPRTINFO "Things yama forgets about until the last minute" --- src/hardware/hw_main.c | 44 +++++++++++++++++++++++++++++++----- src/r_things.cpp | 51 ++++++++++++++++++++++++++++++++++++++---- src/r_things.h | 8 ++++++- 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bed2b5ddf..1ecc0929a 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4914,6 +4914,8 @@ static void HWR_ProjectSprite(mobj_t *thing) boolean affinesprite = ((thing->player != NULL) || R_ThingIsAffineSprite(thing)); affine_t affine_transform = {0}; vector2_t affine_scale = {0}; + f_vector2_t affine_pivotoffsetdiff = {0}; + polyvertex_t affine_rootpoint = {0}; f_vector2_t affine_point[4] = {0}; float leftbound = 0, backbound = 0, topbound = 0; @@ -5136,6 +5138,18 @@ static void HWR_ProjectSprite(mobj_t *thing) if (affinesprite) { + vector2_t affine_pivot = {0}; + + vector2_t patch_defaultpivot = {.x = spr_offset, .y = (spr_height / 2)}; + + R_GetPivotVectorFromSpriteInfo(&affine_pivot, + &patch_defaultpivot, + sprinfo, + (thing->frame & FF_FRAMEMASK)); + + affine_pivotoffsetdiff.x = FIXED_TO_FLOAT(affine_pivot.x - spr_offset); + affine_pivotoffsetdiff.y = FIXED_TO_FLOAT(affine_pivot.y - spr_topoffset); + affine_scale.x = FLOAT_TO_FIXED(spritexscale * this_scale); affine_scale.y = FLOAT_TO_FIXED(spriteyscale * this_scale); @@ -5147,7 +5161,7 @@ static void HWR_ProjectSprite(mobj_t *thing) const fixed_t rolloffs_x = FixedDiv(interptarg->rollingxoffset, highresscale) * (((thing->renderflags & RF_FLIPOFFSETS) && flip) ? -1 : 1); const fixed_t rolloffs_y = FixedDiv(interptarg->rollingyoffset, highresscale); - fixed_t y_piv = spr_topoffset; + fixed_t y_piv = affine_pivot.y; if (vflip) { @@ -5173,11 +5187,11 @@ static void HWR_ProjectSprite(mobj_t *thing) affine_transform.d = FixedDiv(ca, affine_scale.y); } - affine_transform.ox = spr_offset - rolloffs_x; + affine_transform.ox = affine_pivot.x - rolloffs_x; affine_transform.oy = y_piv - rolloffs_y; spritexscale = 1.0; - spriteyscale = 1,0; + spriteyscale = 1.0; } if (thing->renderflags & RF_ABSOLUTEOFFSETS) @@ -5328,10 +5342,18 @@ static void HWR_ProjectSprite(mobj_t *thing) // loops take more processing time. If we can help it, it's better to just cut corners. float f_left = 0; float f_bottom = 0; + float f_right = 0; + float f_top = 0; + float f_xlen = 0; + float f_ylen = 0; #define BOUNDCHECK(i) \ { \ f_left = min(affine_point[i].x, f_left); \ f_bottom = max(affine_point[i].y, f_bottom); \ + f_top = min(affine_point[i].y, f_top); \ + f_right = max(affine_point[i].x, f_right); \ + f_xlen = (f_right - f_left); \ + f_ylen = (f_bottom - f_top); \ } BOUNDCHECK(0); @@ -5354,6 +5376,16 @@ static void HWR_ProjectSprite(mobj_t *thing) affine_rootpoint.x = tr_x; affine_rootpoint.z = tr_y; + // Rescale X and Y so we can multiply the pivot offset differences by them. + const float f_affinexscale = f_xlen / (FIXED_TO_FLOAT(spr_width)); + const float f_affineyscale = f_ylen / (FIXED_TO_FLOAT(spr_height)); + + affine_pivotoffsetdiff.x *= f_affinexscale; + affine_pivotoffsetdiff.y *= f_affineyscale; + + affine_rootpoint.x -= (affine_pivotoffsetdiff.x * rightcos); + affine_rootpoint.z -= (affine_pivotoffsetdiff.x * rightsin); + #ifdef ROTSPRITE const float xrescale = this_xscale / FIXED_TO_FLOAT(mapobjectscale); float f_visx = (FIXED_TO_FLOAT(FixedMul(visoffs.x, mapobjectscale))) * xrescale; @@ -5422,15 +5454,15 @@ nodeterminant: affine_rootpoint.y = 0; - const float f_topoffs = FIXED_TO_FLOAT(spr_topoffset); + const float f_topoffs = (FIXED_TO_FLOAT(spr_topoffset)); if (vflip) { - affine_rootpoint.y = FIXED_TO_FLOAT(interp.z + thing->height) - (f_topoffs * this_yscale); + affine_rootpoint.y = (FIXED_TO_FLOAT(interp.z + thing->height) + affine_pivotoffsetdiff.y) - (f_topoffs * this_yscale); } else { - affine_rootpoint.y = FIXED_TO_FLOAT(interp.z) + (f_topoffs * this_yscale); + affine_rootpoint.y = (FIXED_TO_FLOAT(interp.z) - affine_pivotoffsetdiff.y) + (f_topoffs * this_yscale); } if (!affinesprite) diff --git a/src/r_things.cpp b/src/r_things.cpp index 8198ca96a..ee4783b4c 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1971,6 +1971,28 @@ fixed_t R_GetSpriteDirectionalLighting(angle_t angle) return extralight; } +void R_GetPivotVectorFromSpriteInfo(vector2_t* out, + vector2_t* defaultpiv, + spriteinfo_t* sprinfo, + size_t frame) +{ + if (in_bit_array(sprinfo->available, frame)) + { + out->x = (sprinfo->pivot[frame].x * FRACUNIT); + out->y = (sprinfo->pivot[frame].y * FRACUNIT); + } + else if (in_bit_array(sprinfo->available, SPRINFO_DEFAULT_PIVOT)) + { + out->x = (sprinfo->pivot[SPRINFO_DEFAULT_PIVOT].x * FRACUNIT); + out->y = (sprinfo->pivot[SPRINFO_DEFAULT_PIVOT].y * FRACUNIT); + } + else + { + out->x = defaultpiv->x; + out->y = defaultpiv->y; + } +} + // // R_ProjectSprite // Generates a vissprite for a thing @@ -2060,6 +2082,7 @@ static void R_ProjectSprite(mobj_t *thing) affine_bounding_t affine_bounds = {0}; vector2_t affine_scale = {0}; vector2_t affine_distscale = {0}; + vector2_t affine_pivotoffsetdiff = {0}; if (R_IsOverlayingSMonitorPlayer(thing)) { @@ -2319,6 +2342,18 @@ static void R_ProjectSprite(mobj_t *thing) if (affinesprite) { + vector2_t affine_pivot = {0}; + + vector2_t patch_defaultpivot = {.x = (patch->leftoffset * FRACUNIT), .y = (patch->height * FRACHALF)}; + + R_GetPivotVectorFromSpriteInfo(&affine_pivot, + &patch_defaultpivot, + sprinfo, + (thing->frame & FF_FRAMEMASK)); + + affine_pivotoffsetdiff.x = affine_pivot.x - (patch->leftoffset * FRACUNIT); + affine_pivotoffsetdiff.y = affine_pivot.y - (patch->topoffset * FRACUNIT); + affine_scale.x = FixedMul(affine_scale.x, FixedMul(spritexscale, this_scale)); affine_scale.y = FixedMul(affine_scale.y, FixedMul(spriteyscale, this_scale)); @@ -2330,7 +2365,7 @@ static void R_ProjectSprite(mobj_t *thing) const fixed_t rolloffs_x = FixedDiv(interptarg->rollingxoffset, highresscale) * (((thing->renderflags & RF_FLIPOFFSETS) && flip) ? -1 : 1); const fixed_t rolloffs_y = FixedDiv(interptarg->rollingyoffset, highresscale); - fixed_t y_piv = ((patch->pivot.y + patch->topoffset) * FRACUNIT); + fixed_t y_piv = affine_pivot.y; if (vflip) { @@ -2356,13 +2391,20 @@ static void R_ProjectSprite(mobj_t *thing) affine_transform.d = FixedDiv(ca, affine_scale.y); } - affine_transform.ox = ((patch->pivot.x + patch->leftoffset) * FRACUNIT) - rolloffs_x; + affine_transform.ox = affine_pivot.x - rolloffs_x; affine_transform.oy = y_piv - rolloffs_y; V_GetAffineBounds(&affine_transform, patch, FRACUNIT, &affine_bounds); + // Rescale X and Y so we can multiply the pivot offset differences by them. + const fixed_t _affinexscale = FixedDiv(affine_bounds.xlen * FRACUNIT, patch->width * FRACUNIT); + const fixed_t _affineyscale = FixedDiv(affine_bounds.ylen * FRACUNIT, patch->height * FRACUNIT); + + affine_pivotoffsetdiff.x = FixedMul(affine_pivotoffsetdiff.x, _affinexscale); + affine_pivotoffsetdiff.y = FixedMul(affine_pivotoffsetdiff.y, _affineyscale); + spr_width = (affine_bounds.xlen * FRACUNIT); - spr_offset = (affine_bounds.xleft * FRACUNIT); + spr_offset = (affine_bounds.xleft * FRACUNIT) - affine_pivotoffsetdiff.x; //spr_height = (affine_bounds.ylen * FRACUNIT); //spr_topoffset = (affine_bounds.yup * FRACUNIT); @@ -2713,7 +2755,8 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t rawyscale = FixedDiv(affine_scale.y, FixedMul(this_scale, sortscale)); const float affineyscale = FIXED_TO_FLOAT(affine_scale.y); - const fixed_t real_topoffset = FLOAT_TO_FIXED(static_cast(affine_bounds.yup) / affineyscale) + thingyoffset; + const float pivydiff = FIXED_TO_FLOAT(affine_pivotoffsetdiff.y) * ((vflip) ? -1.0f : 1.0f); + const fixed_t real_topoffset = FLOAT_TO_FIXED(static_cast(affine_bounds.yup - pivydiff) / affineyscale) + thingyoffset; const fixed_t real_height = FLOAT_TO_FIXED(static_cast(affine_bounds.ylen) / affineyscale); useoffset = FixedMul(real_topoffset, FixedMul(rawyscale, this_scale)); diff --git a/src/r_things.h b/src/r_things.h index 31924f34a..977c2a211 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -91,12 +91,18 @@ boolean R_ThingVerticallyFlipped (mobj_t *thing); boolean R_ThingIsPaperSprite (mobj_t *thing); boolean R_ThingIsFloorSprite (mobj_t *thing); -boolean R_ThingIsAffineSprite (mobj_t *thing); + boolean R_ThingIsFullBright (mobj_t *thing); boolean R_ThingIsSemiBright (mobj_t *thing); boolean R_ThingIsFullDark (mobj_t *thing); + +boolean R_ThingIsAffineSprite (mobj_t *thing); boolean R_AffinePreScale (mobj_t *thing); +void R_GetPivotVectorFromSpriteInfo(vector2_t* out, + vector2_t* defaultpiv, + spriteinfo_t* sprinfo, + size_t frame); boolean R_ThingIsFlashing(mobj_t *thing);