Copy interpolation to shields and overlays

Also handle overlays in splitscreen properly
This commit is contained in:
Zwip-Zwap Zapony 2023-05-29 16:37:48 +02:00
parent b5232a4ca4
commit e5fdfadce7
5 changed files with 96 additions and 30 deletions

View file

@ -5120,6 +5120,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
spriteyscale = FIXED_TO_FLOAT(interp.spriteyscale);
// transform the origin point
if (thing->type == MT_OVERLAY) // Handle overlays
R_ThingOffsetOverlay(thing, &interp.x, &interp.y);
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
@ -5439,6 +5441,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
// calculate tz for tracer, same way it is calculated for this sprite
// transform the origin point
if (thing->tracer->type == MT_OVERLAY) // Handle overlays
R_ThingOffsetOverlay(thing->tracer, &tracer_interp.x, &tracer_interp.y);
tr_x = FIXED_TO_FLOAT(tracer_interp.x) - gl_viewx;
tr_y = FIXED_TO_FLOAT(tracer_interp.y) - gl_viewy;

View file

@ -1580,6 +1580,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
#undef INTERPOLERATION_LIMIT
#endif
if (spr->mobj->type == MT_OVERLAY) // Handle overlays
R_ThingOffsetOverlay(spr->mobj, &interp.x, &interp.y);
//Hurdler: it seems there is still a small problem with mobj angle
p.x = FIXED_TO_FLOAT(interp.x);
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;

View file

@ -6764,15 +6764,33 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale));
thing->destscale = thing->scale;
thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale);
#define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code
#define NewPH(player) P_GetPlayerHeight(player)
#define OldMH(mobj) FixedMul(mobj->height, FixedDiv(mobj->old_scale, mobj->scale))
#define OldPH(player) FixedMul(player->height, player->mo->old_scale)
P_UnsetThingPosition(thing);
thing->x = thing->target->x;
thing->y = thing->target->y;
thing->old_x = thing->target->old_x;
thing->old_y = thing->target->old_y;
if (thing->eflags & MFE_VERTICALFLIP)
thing->z = thing->target->z + (thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) - FixedMul(2*FRACUNIT, thing->target->scale);
{
thing->z = thing->target->z + NewMH(thing->target) - NewMH(thing) + ((NewPH(thing->target->player) - NewMH(thing->target)) / 3) - (thing->target->scale * 2);
thing->old_z = thing->target->old_z + OldMH(thing->target) - OldMH(thing) + ((OldPH(thing->target->player) - OldMH(thing->target)) / 3) - (thing->target->old_scale * 2);
}
else
thing->z = thing->target->z - (FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) + FixedMul(2*FRACUNIT, thing->target->scale);
{
thing->z = thing->target->z - ((NewPH(thing->target->player) - NewMH(thing->target)) / 3) + (thing->target->scale * 2);
thing->old_z = thing->target->old_z - ((OldPH(thing->target->player) - OldMH(thing->target)) / 3) + (thing->target->old_scale * 2);
}
P_SetThingPosition(thing);
P_CheckPosition(thing, thing->x, thing->y);
#undef NewMH
#undef NewPH
#undef OldMH
#undef OldPH
if (P_MobjWasRemoved(thing))
return false;
@ -6838,10 +6856,11 @@ void P_RunOverlays(void)
{
// run overlays
mobj_t *mo, *next = NULL;
fixed_t destx,desty,zoffs;
for (mo = overlaycap; mo; mo = next)
{
fixed_t zoffs;
I_Assert(!P_MobjWasRemoved(mo));
// grab next in chain, then unset the chain target
@ -6857,31 +6876,11 @@ void P_RunOverlays(void)
continue;
}
if (!splitscreen /*&& rendermode != render_soft*/)
{
angle_t viewingangle;
if (players[displayplayer].awayviewtics && players[displayplayer].awayviewmobj != NULL && !P_MobjWasRemoved(players[displayplayer].awayviewmobj))
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
else
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y);
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
viewingangle += ANGLE_180;
destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
}
else
{
destx = mo->target->x;
desty = mo->target->y;
}
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale;
mo->old_scale = mo->target->old_scale;
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
mo->old_angle = (mo->target->player ? mo->target->player->old_drawangle : mo->target->old_angle) + mo->movedir;
if (!(mo->state->frame & FF_ANIMATE))
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
@ -6891,15 +6890,26 @@ void P_RunOverlays(void)
zoffs = 0;
P_UnsetThingPosition(mo);
mo->x = destx;
mo->y = desty;
mo->x = mo->target->x;
mo->y = mo->target->y;
mo->old_x = mo->target->old_x;
mo->old_y = mo->target->old_y;
mo->radius = mo->target->radius;
mo->height = mo->target->height;
if (mo->eflags & MFE_VERTICALFLIP)
mo->z = (mo->target->z + mo->target->height - mo->height) - zoffs;
{
mo->z = mo->target->z + mo->target->height - mo->height - zoffs;
if (mo->scale == mo->old_scale)
mo->old_z = mo->target->old_z + mo->target->height - mo->height - zoffs;
else // Interpolate height scale changes - mo and mo->target have the same scales here, so don't interpolate them individually
mo->old_z = mo->target->old_z + FixedMul(mo->target->height - mo->height, FixedDiv(mo->old_scale, mo->scale)) - zoffs;
}
else
mo->z = mo->target->z + zoffs;
if (mo->state->var1)
{
mo->z = mo->target->z + zoffs;
mo->old_z = mo->target->old_z + zoffs;
}
if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
P_SetUnderlayPosition(mo);
else
P_SetThingPosition(mo);

View file

@ -1649,6 +1649,8 @@ static void R_ProjectSprite(mobj_t *thing)
this_scale = interp.scale;
// transform the origin point
if (thing->type == MT_OVERLAY) // Handle overlays
R_ThingOffsetOverlay(thing, &interp.x, &interp.y);
tr_x = interp.x - viewx;
tr_y = interp.y - viewy;
@ -1987,6 +1989,8 @@ static void R_ProjectSprite(mobj_t *thing)
R_InterpolateMobjState(thing, FRACUNIT, &tracer_interp);
}
if (thing->type == MT_OVERLAY) // Handle overlays
R_ThingOffsetOverlay(thing, &tracer_interp.x, &tracer_interp.y);
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);
@ -3521,6 +3525,50 @@ boolean R_ThingIsFullDark(mobj_t *thing)
return ((thing->frame & FF_BRIGHTMASK) == FF_FULLDARK || (thing->renderflags & RF_BRIGHTMASK) == RF_FULLDARK);
}
// Offsets MT_OVERLAY towards the camera at render-time - Works in splitscreen!
// The &x and &y arguments should be pre-interpolated, and will be modified
void R_ThingOffsetOverlay(mobj_t *thing, fixed_t *x, fixed_t *y)
{
mobj_t *mobj = thing;
INT16 offset = 0; // Offset towards or away from the camera, and how much
fixed_t offsetscale = thing->scale; // Occasionally needs to be interpolated
angle_t viewingangle;
UINT8 looplimit = 255; // Prevent infinite loops - A chain of 255 connected overlays is enough for any sane use case
#ifdef PARANOIA
if (P_MobjWasRemoved(mobj) || !x || !y)
I_Error("R_ThingOffsetOverlay: thing, x, or y is invalid");
#endif
do // Get the overlay's offset
{
// Does the overlay use FF_ANIMATE? If not, if var1 is non-zero, it's an underlay instead of an overlay
if (!(mobj->state->frame & FF_ANIMATE) && mobj->state->var1)
offset += 1; // Underlay below the target, away from the camera
else
offset -= 1; // Overlay on top of the target, towards the camera
looplimit -= 1;
mobj = mobj->target;
} while (!P_MobjWasRemoved(mobj) && mobj->type == MT_OVERLAY && looplimit > 0); // Handle overlays following other overlays
// Does the offset scale need to be interpolated?
if (thing->scale != thing->old_scale && R_UsingFrameInterpolation() && !paused)
{
interpmobjstate_t interp = {0};
R_InterpolateMobjState(thing, rendertimefrac, &interp);
offsetscale = interp.scale;
}
// Get the angle from the camera to the X and Y coordinates
viewingangle = R_PointToAngle(*x, *y);
// Finally, offset the X and Y coordinates towards or away from the camera
*x += P_ReturnThrustX(thing, viewingangle, FixedMul(offset * (FRACUNIT/4), offsetscale));
*y += P_ReturnThrustY(thing, viewingangle, FixedMul(offset * (FRACUNIT/4), offsetscale));
}
//
// R_DrawMasked
//

View file

@ -88,6 +88,8 @@ boolean R_ThingIsFullBright (mobj_t *thing);
boolean R_ThingIsSemiBright (mobj_t *thing);
boolean R_ThingIsFullDark (mobj_t *thing);
void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy);
// --------------
// MASKED DRAWING
// --------------