Add sector plane level interpolations

This commit is contained in:
Eidolon 2022-04-12 20:45:49 -05:00
parent ac2510f284
commit 9c8d0a3b6f
8 changed files with 238 additions and 0 deletions

View file

@ -477,6 +477,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
R_ApplyLevelInterpolators(cv_frameinterpolation.value == 1 ? rendertimefrac : FRACUNIT);
PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
@ -525,6 +526,7 @@ static void D_Display(void)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
PS_STOP_TIMING(ps_rendercalltime);
R_RestoreLevelInterpolators();
}
if (lastdraw)

View file

@ -1830,6 +1830,7 @@ void G_DoLoadLevel(boolean resetplayer)
}
// Setup the level.
R_InitializeLevelInterpolators();
if (!P_LoadLevel(false, false)) // this never returns false?
{
// fail so reset game stuff

View file

@ -13,6 +13,7 @@
#include "doomdef.h"
#include "p_local.h"
#include "r_fps.h"
#include "r_main.h"
#include "s_sound.h"
#include "z_zone.h"
@ -602,6 +603,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
ceiling->tag = tag;
ceiling->type = type;
firstone = 0;
// interpolation
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
}
return rtn;
}
@ -679,6 +683,10 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
ceiling->tag = tag;
ceiling->type = type;
// interpolation
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
}
return rtn;
}

View file

@ -16,6 +16,7 @@
#include "m_random.h"
#include "p_local.h"
#include "p_slopes.h"
#include "r_fps.h"
#include "r_state.h"
#include "s_sound.h"
#include "z_zone.h"
@ -573,6 +574,8 @@ void T_ContinuousFalling(continuousfall_t *faller)
{
faller->sector->ceilingheight = faller->ceilingstartheight;
faller->sector->floorheight = faller->floorstartheight;
R_ClearLevelInterpolatorState(&faller->thinker);
}
P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong
@ -2010,6 +2013,9 @@ void EV_DoFloor(line_t *line, floor_e floortype)
}
firstone = 0;
// interpolation
R_CreateInterpolator_SectorPlane(&dofloor->thinker, sec, false);
}
}
@ -2140,6 +2146,10 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
default:
break;
}
// interpolation
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&elevator->thinker, sec, true);
}
}
@ -2318,6 +2328,10 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole
faller->destheight = backwards ? backsector->ceilingheight : backsector->floorheight;
faller->direction = backwards ? 1 : -1;
// interpolation
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&faller->thinker, sec, true);
}
// Some other 3dfloor special things Tails 03-11-2002 (Search p_mobj.c for description)

View file

@ -20,6 +20,7 @@
#include "p_local.h"
#include "p_setup.h" // levelflats for flat animation
#include "r_data.h"
#include "r_fps.h"
#include "r_textures.h"
#include "m_random.h"
#include "p_mobj.h"
@ -5695,6 +5696,9 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
displace->speed = speed;
displace->type = type;
displace->reverse = reverse;
// interpolation
R_CreateInterpolator_SectorPlane(&displace->thinker, &sectors[affectee], false);
}
/** Adds a Mario block thinker, which changes the block's texture between blank
@ -5754,6 +5758,10 @@ static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t c
raise->flags |= RF_REVERSE;
if (spindash)
raise->flags |= RF_SPINDASH;
// interpolation
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&raise->thinker, sec, true);
}
static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic)
@ -5779,6 +5787,10 @@ static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, b
airbob->flags |= RF_SPINDASH;
if (dynamic)
airbob->flags |= RF_DYNAMIC;
// interpolation
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&airbob->thinker, sec, true);
}
/** Adds a thwomp thinker.
@ -5819,6 +5831,10 @@ static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t
sec->ceilingdata = thwomp;
// Start with 'resting' texture
sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture;
// interpolation
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, false);
R_CreateInterpolator_SectorPlane(&thwomp->thinker, sec, true);
}
/** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area.

View file

@ -764,6 +764,11 @@ void P_Ticker(boolean run)
LUA_HOOK(PostThinkFrame);
}
if (run)
{
R_UpdateLevelInterpolators();
}
P_MapEnd();
// Z_CheckMemCleanup();

View file

@ -20,6 +20,7 @@
#include "r_plane.h"
#include "p_spec.h"
#include "r_state.h"
#include "z_zone.h"
#ifdef HWRENDER
#include "hardware/hw_main.h" // for cv_glshearing
#endif
@ -40,6 +41,11 @@ viewvars_t *newview = &p1view_new;
enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1;
static levelinterpolator_t **levelinterpolators;
static size_t levelinterpolators_len;
static size_t levelinterpolators_size;
static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac)
{
return from + FixedMul(frac, to - from);
@ -194,3 +200,155 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->angle = mobj->angle;
}
static void AddInterpolator(levelinterpolator_t* interpolator)
{
if (levelinterpolators_len >= levelinterpolators_size)
{
if (levelinterpolators_size == 0)
{
levelinterpolators_size = 128;
}
else
{
levelinterpolators_size *= 2;
}
levelinterpolators = Z_ReallocAlign(
(void*) levelinterpolators,
sizeof(levelinterpolator_t*) * levelinterpolators_size,
PU_LEVEL,
NULL,
sizeof(levelinterpolator_t*) * 8
);
}
levelinterpolators[levelinterpolators_len] = interpolator;
levelinterpolators_len += 1;
}
static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker)
{
levelinterpolator_t *ret = (levelinterpolator_t*) Z_CallocAlign(
sizeof(levelinterpolator_t),
PU_LEVEL,
NULL,
sizeof(levelinterpolator_t) * 8
);
ret->type = type;
ret->thinker = thinker;
AddInterpolator(ret);
return ret;
}
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling)
{
levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorPlane, thinker);
interp->sectorplane.sector = sector;
interp->sectorplane.ceiling = ceiling;
if (ceiling)
{
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->ceilingheight;
}
else
{
interp->sectorplane.oldheight = interp->sectorplane.bakheight = sector->floorheight;
}
}
void R_InitializeLevelInterpolators(void)
{
levelinterpolators_len = 0;
levelinterpolators_size = 0;
levelinterpolators = NULL;
}
static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
{
switch (interp->type)
{
case LVLINTERP_SectorPlane:
interp->sectorplane.oldheight = interp->sectorplane.bakheight;
interp->sectorplane.bakheight = interp->sectorplane.ceiling ? interp->sectorplane.sector->ceilingheight : interp->sectorplane.sector->floorheight;
break;
}
}
void R_UpdateLevelInterpolators(void)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
UpdateLevelInterpolatorState(interp);
}
}
void R_ClearLevelInterpolatorState(thinker_t *thinker)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
if (interp->thinker == thinker)
{
// Do it twice to make the old state match the new
UpdateLevelInterpolatorState(interp);
UpdateLevelInterpolatorState(interp);
}
}
}
void R_ApplyLevelInterpolators(fixed_t frac)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
switch (interp->type)
{
case LVLINTERP_SectorPlane:
if (interp->sectorplane.ceiling)
{
interp->sectorplane.sector->ceilingheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
}
else
{
interp->sectorplane.sector->floorheight = R_LerpFixed(interp->sectorplane.oldheight, interp->sectorplane.bakheight, frac);
}
}
}
}
void R_RestoreLevelInterpolators(void)
{
size_t i;
for (i = 0; i < levelinterpolators_len; i++)
{
levelinterpolator_t *interp = levelinterpolators[i];
switch (interp->type)
{
case LVLINTERP_SectorPlane:
if (interp->sectorplane.ceiling)
{
interp->sectorplane.sector->ceilingheight = interp->sectorplane.bakheight;
}
else
{
interp->sectorplane.sector->floorheight = interp->sectorplane.bakheight;
}
}
}
}

View file

@ -51,6 +51,27 @@ typedef struct {
angle_t angle;
} interpmobjstate_t;
// Level interpolators
// The union tag for levelinterpolator_t
typedef enum {
LVLINTERP_SectorPlane,
} levelinterpolator_type_e;
// Tagged union of a level interpolator
typedef struct levelinterpolator_s {
levelinterpolator_type_e type;
thinker_t *thinker;
union {
struct {
sector_t *sector;
fixed_t oldheight;
fixed_t bakheight;
boolean ceiling;
} sectorplane;
};
} levelinterpolator_t;
// Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext
void R_InterpolateView(fixed_t frac);
// Buffer the current new views into the old views. Call once after each real tic.
@ -64,4 +85,17 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
// Evaluate the interpolated mobj state for the given precipmobj
void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjstate_t *out);
void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling);
// Initialize level interpolators after a level change
void R_InitializeLevelInterpolators(void);
// Update level interpolators, storing the previous and current states.
void R_UpdateLevelInterpolators(void);
// Clear states for all level interpolators for the thinker
void R_ClearLevelInterpolatorState(thinker_t *thinker);
// Apply level interpolators to the actual game state
void R_ApplyLevelInterpolators(fixed_t frac);
// Restore level interpolators to the real game state
void R_RestoreLevelInterpolators(void);
#endif