From 9a8b5b37bcef6ebd152cd796e7f70622af35aa33 Mon Sep 17 00:00:00 2001 From: Zwip-Zwap Zapony Date: Fri, 25 Aug 2023 10:42:12 +0200 Subject: [PATCH] Interpolate radius/height when scaling mobjs --- src/hardware/hw_main.c | 15 ++++------ src/hardware/hw_md2.c | 6 ++-- src/r_fps.c | 22 ++++++++++++-- src/r_fps.h | 2 ++ src/r_things.cpp | 66 +++++++++++++++++++++++++++++++++--------- 5 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 22f7514a0..d6f7d8c5f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -4993,7 +4993,7 @@ static void HWR_ProjectSprite(mobj_t *thing) R_InterpolateMobjState(caster, R_GetTimeFrac(RTF_LEVEL), &casterinterp); groundz = R_GetShadowZ(thing, NULL); - floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + casterinterp.z - groundz); + floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? casterinterp.height : 0) + casterinterp.z - groundz); shadowheight = FIXED_TO_FLOAT(floordiff); shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale)); @@ -5357,7 +5357,6 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) gl_vissprite_t *vis; float tr_x, tr_y; float tz; - float rad; // uncapped/interpolation interpmobjstate_t interp = {0}; @@ -5384,15 +5383,13 @@ static void HWR_ProjectBoundingBox(mobj_t *thing) tr_x += gl_viewx; tr_y += gl_viewy; - rad = FIXED_TO_FLOAT(thing->radius); - vis = HWR_NewVisSprite(); - vis->x1 = tr_x - rad; - vis->x2 = tr_x + rad; - vis->z1 = tr_y - rad; - vis->z2 = tr_y + rad; + vis->x1 = tr_x - FIXED_TO_FLOAT(interp.radius); + vis->x2 = tr_x + FIXED_TO_FLOAT(interp.radius); + vis->z1 = tr_y - FIXED_TO_FLOAT(interp.radius); + vis->z2 = tr_y + FIXED_TO_FLOAT(interp.radius); vis->gz = FIXED_TO_FLOAT(interp.z); - vis->gzt = vis->gz + FIXED_TO_FLOAT(thing->height); + vis->gzt = vis->gz + FIXED_TO_FLOAT(interp.height); vis->mobj = thing; vis->precip = false; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 23bd29317..d908a889e 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1643,7 +1643,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.y = FIXED_TO_FLOAT(interp.y) + md2->offset; if (flip) - p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height); + p.z = FIXED_TO_FLOAT(interp.z + interp.height); else p.z = FIXED_TO_FLOAT(interp.z); @@ -1694,8 +1694,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.roll = true; // rotation pivot - p.centerx = FIXED_TO_FLOAT(spr->mobj->radius / 2); - p.centery = FIXED_TO_FLOAT(spr->mobj->height / 2); + p.centerx = FIXED_TO_FLOAT(interp.radius / 2); + p.centery = FIXED_TO_FLOAT(interp.height / 2); // rotation axes relative to camera pitchR = FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT); diff --git a/src/r_fps.c b/src/r_fps.c index f7d4597ab..2e4128182 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -288,6 +288,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) out->y = mobj->y; out->z = mobj->z; out->scale = mobj->scale; + out->radius = mobj->radius; + out->height = mobj->height; out->subsector = mobj->subsector; out->angle = mobj->player ? mobj->player->drawangle : mobj->angle; out->pitch = mobj->pitch; @@ -304,11 +306,21 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) out->x = R_LerpFixed(mobj->old_x, mobj->x, frac); out->y = R_LerpFixed(mobj->old_y, mobj->y, frac); out->z = R_LerpFixed(mobj->old_z, mobj->z, frac); - out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac); out->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac); out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac); - out->spritexoffset = mobj->resetinterp ? mobj->spritexoffset : R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac); - out->spriteyoffset = mobj->resetinterp ? mobj->spriteyoffset : R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac); + + if (mobj->scale == mobj->old_scale) // Tiny optimisation - scale is usually unchanging, so let's skip a lerp, two FixedMuls, and two FixedDivs + { + out->scale = mobj->scale; + out->radius = mobj->radius; + out->height = mobj->height; + } + else + { + out->scale = R_LerpFixed(mobj->old_scale, mobj->scale, frac); + out->radius = FixedMul(mobj->radius, FixedDiv(out->scale, mobj->scale)); + out->height = FixedMul(mobj->height, FixedDiv(out->scale, mobj->scale)); + } out->subsector = R_PointInSubsector(out->x, out->y); @@ -350,6 +362,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->y = mobj->y; out->z = mobj->z; out->scale = mapobjectscale; + out->radius = mobj->radius; + out->height = mobj->height; out->subsector = mobj->subsector; out->angle = mobj->angle; out->spritexscale = mobj->spritexscale; @@ -363,6 +377,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst out->y = R_LerpFixed(mobj->old_y, mobj->y, frac); out->z = R_LerpFixed(mobj->old_z, mobj->z, frac); out->scale = mapobjectscale; + out->radius = mobj->radius; + out->height = mobj->height; out->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac); out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac); out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac); diff --git a/src/r_fps.h b/src/r_fps.h index 7561c1acb..d719fb276 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -78,6 +78,8 @@ struct interpmobjstate_t { subsector_t *subsector; angle_t angle; fixed_t scale; + fixed_t radius; + fixed_t height; fixed_t spritexscale; fixed_t spriteyscale; fixed_t spritexoffset; diff --git a/src/r_things.cpp b/src/r_things.cpp index e6282030b..e2bc281a7 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1396,7 +1396,7 @@ fixed_t R_GetShadowZ( R_InterpolateMobjState(thing, R_GetTimeFrac(RTF_LEVEL), &interp); - halfHeight = interp.z + (thing->height >> 1); + halfHeight = interp.z + (interp.height >> 1); floorz = P_GetFloorZ(thing, interp.subsector->sector, interp.x, interp.y, NULL); ceilingz = P_GetCeilingZ(thing, interp.subsector->sector, interp.x, interp.y, NULL); @@ -1434,6 +1434,33 @@ fixed_t R_GetShadowZ( } } + // Check polyobjects and see if groundz needs to be altered + if (numPolyObjects) + { + // This isn't very precise, but the precise method was far too slow. + // (Polies are just naturally pretty flickery anyway :P) + polyobj_t *po = interp.subsector->polyList; + + while (po) + { + if (!(po->flags & POF_RENDERPLANES) || !P_MobjInsidePolyobj(po, thing)) + { + po = (polyobj_t *)(po->link.next); + continue; + } + + // We're inside it! Yess... + z = isflipped ? po->lines[0]->backsector->floorheight : po->lines[0]->backsector->ceilingheight; + if CHECKZ + { + groundz = z; + groundslope = NULL; + } + + po = (polyobj_t *)(po->link.next); + } + } + if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))) : (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))) { @@ -1472,9 +1499,9 @@ static void R_SkewShadowSprite( //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); if (viewz < groundz) - *shadowyscale += FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + *shadowyscale += FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope); else - *shadowyscale -= FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + *shadowyscale -= FixedMul(FixedMul(interp.radius*2 / spriteheight, scalemul), zslope); *shadowyscale = abs((*shadowyscale)); *shadowskew = xslope; @@ -1610,8 +1637,8 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) // 0--2 // start in the (0) corner - gx = interp.x - thing->radius - viewx; - gy = interp.y - thing->radius - viewy; + gx = interp.x - interp.radius - viewx; + gy = interp.y - interp.radius - viewy; tz = FixedMul(gx, viewcos) + FixedMul(gy, viewsin); @@ -1633,14 +1660,14 @@ static void R_ProjectBoundingBox(mobj_t *thing, vissprite_t *vis) box = R_NewVisSprite(); box->mobj = thing; box->mobjflags = thing->flags; - box->thingheight = thing->height; + box->thingheight = interp.height; box->cut = SC_BBOX; box->gx = tx; box->gy = tz; - box->scale = 2 * FixedMul(thing->radius, viewsin); - box->xscale = 2 * FixedMul(thing->radius, viewcos); + box->scale = 2 * FixedMul(interp.radius, viewsin); + box->xscale = 2 * FixedMul(interp.radius, viewcos); box->pz = interp.z; box->pzt = box->pz + box->thingheight; @@ -1710,6 +1737,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t tr_x, tr_y; fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! + fixed_t radius, height; // For drop shadows fixed_t sortscale, sortsplat = 0; fixed_t linkscale = 0; fixed_t sort_x = 0, sort_y = 0, sort_z; @@ -1798,6 +1826,9 @@ static void R_ProjectSprite(mobj_t *thing) interp.y += thing->spryoff; interp.z += thing->sprzoff; + radius = interp.radius; // For drop shadows + height = interp.height; // Ditto + // transform the origin point tr_x = interp.x - viewx; tr_y = interp.y - viewy; @@ -2207,6 +2238,11 @@ static void R_ProjectSprite(mobj_t *thing) if (! R_ThingVisible(thing)) return; + R_InterpolateMobjState(thing, R_GetTimeFrac(RTF_LEVEL), &tracer_interp); + + radius = tracer_interp.radius; // For drop shadows + height = tracer_interp.height; // Ditto + tr_x = (tracer_interp.x + sort_x) - viewx; tr_y = (tracer_interp.y + sort_y) - viewy; tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); @@ -2279,6 +2315,10 @@ static void R_ProjectSprite(mobj_t *thing) { fixed_t groundz = R_GetShadowZ(thing, NULL); boolean isflipped = (thing->eflags & MFE_VERTICALFLIP); + mobj_t *caster = thing->target; + interpmobjstate_t casterinterp = { 0 }; // MSVC compatibility - SSNTails + + R_InterpolateMobjState(caster, R_GetTimeFrac(RTF_LEVEL), &casterinterp); if (shadoweffects) { @@ -2287,8 +2327,8 @@ static void R_ProjectSprite(mobj_t *thing) if (shadowdraw) { - spritexscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spritexscale)); - spriteyscale = FixedMul(thing->radius * 2, FixedMul(shadowscale, spriteyscale)); + spritexscale = FixedMul(radius * 2, FixedMul(shadowscale, spritexscale)); + spriteyscale = FixedMul(radius * 2, FixedMul(shadowscale, spriteyscale)); spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); spriteyscale = std::min(spriteyscale, spritexscale) / patch->height; spritexscale /= patch->width; @@ -2303,7 +2343,7 @@ static void R_ProjectSprite(mobj_t *thing) { R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan); - gzt = (isflipped ? (interp.z + thing->height) : interp.z) + patch->height * spriteyscale / 2; + gzt = (isflipped ? (interp.z + height) : interp.z) + patch->height * spriteyscale / 2; gz = gzt - patch->height * spriteyscale; cut = static_cast(cut | SC_SHEAR); @@ -2318,7 +2358,7 @@ static void R_ProjectSprite(mobj_t *thing) // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = interp.z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gz = interp.z + interp.height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); } else @@ -2451,7 +2491,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->gy = interp.y; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = thing->height; + vis->thingheight = height; vis->pz = interp.z; vis->pzt = vis->pz + vis->thingheight; vis->floorclip = floorClip;