Make affines respect SPRTINFO

"Things yama forgets about until the last minute"
This commit is contained in:
yamamama 2026-03-03 17:00:57 -05:00
parent de8f2e40da
commit 00a9e94161
3 changed files with 92 additions and 11 deletions

View file

@ -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)

View file

@ -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<float>(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<float>(affine_bounds.yup - pivydiff) / affineyscale) + thingyoffset;
const fixed_t real_height = FLOAT_TO_FIXED(static_cast<float>(affine_bounds.ylen) / affineyscale);
useoffset = FixedMul(real_topoffset, FixedMul(rawyscale, this_scale));

View file

@ -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);