From 0d4d5587b523506810e114a22b6666065255a9fc Mon Sep 17 00:00:00 2001 From: Boondorl <59555366+Boondorl@users.noreply.github.com> Date: Sun, 18 Dec 2022 01:04:25 -0500 Subject: [PATCH] Added FOV Interpolation --- src/d_main.cpp | 7 ++---- src/g_level.cpp | 1 + src/p_tick.cpp | 1 + src/playsim/actor.h | 4 ++++ src/playsim/actorinlines.h | 8 +++++++ src/playsim/d_player.h | 1 + src/playsim/p_mobj.cpp | 24 +++++++++++++++++++ src/playsim/p_user.cpp | 1 + src/scripting/vmthunks_actors.cpp | 7 ++++++ wadsrc/static/zscript/actors/actor.zs | 1 + .../zscript/actors/inventory/weapons.zs | 1 + .../zscript/actors/player/player_morph.zs | 2 ++ wadsrc/static/zscript/constants.zs | 1 + 13 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 12b3fb9ffb..d9177fbb47 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -899,11 +899,8 @@ void D_Display () DAngle fov = DAngle::fromDeg(90.); AActor *cam = players[consoleplayer].camera; if (cam) - { - if (cam->player) - fov = DAngle::fromDeg(cam->player->FOV); - else fov = DAngle::fromDeg(cam->CameraFOV); - } + fov = DAngle::fromDeg(cam->GetFOV(I_GetTimeFrac())); + R_SetFOV(vp, fov); } diff --git a/src/g_level.cpp b/src/g_level.cpp index 8aa0115063..ff348a879d 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1702,6 +1702,7 @@ int FLevelLocals::FinishTravel () } pawn->LinkToWorld (nullptr); pawn->ClearInterpolation(); + pawn->ClearFOVInterpolation(); const int tid = pawn->tid; // Save TID (actor isn't linked into the hash chain yet) pawn->tid = 0; // Reset TID pawn->SetTID(tid); // Set TID (and link actor into the hash chain) diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 57cc986afa..59d66a285c 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -158,6 +158,7 @@ void P_Ticker (void) while ((ac = it.Next())) { ac->ClearInterpolation(); + ac->ClearFOVInterpolation(); } P_ThinkParticles(Level); // [RH] make the particles think diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 271ac78afa..b1c848e409 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -929,6 +929,8 @@ public: void SetViewAngle(DAngle ang, int fflags); void SetViewRoll(DAngle roll, int fflags); + double GetFOV(double ticFrac); + PClassActor *GetBloodType(int type = 0) const; double Distance2DSquared(AActor *other, bool absolute = false) @@ -998,6 +1000,7 @@ public: DVector3 Vec3Angle(double length, DAngle angle, double dz, bool absolute = false); void ClearInterpolation(); + void ClearFOVInterpolation(); void Move(const DVector3 &vel) { @@ -1278,6 +1281,7 @@ public: // [RH] Used to interpolate the view to get >35 FPS DVector3 Prev; DRotator PrevAngles; + DAngle PrevFOV; int PrevPortalGroup; TArray AttachedLights; TDeletingArray UserLights; diff --git a/src/playsim/actorinlines.h b/src/playsim/actorinlines.h index 56a2e6ab88..939807c98d 100644 --- a/src/playsim/actorinlines.h +++ b/src/playsim/actorinlines.h @@ -34,6 +34,14 @@ inline void AActor::ClearInterpolation() else PrevPortalGroup = 0; } +inline void AActor::ClearFOVInterpolation() +{ + if (player) + PrevFOV = DAngle::fromDeg(player->FOV); + else + PrevFOV = DAngle::fromDeg(CameraFOV); +} + inline double secplane_t::ZatPoint(const AActor *ac) const { return (D + normal.X*ac->X() + normal.Y*ac->Y()) * negiC; diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index 8de552e040..27fd860dda 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -124,6 +124,7 @@ typedef enum CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_INTERPVIEWANGLES = 1 << 15, // [MR] flag for interpolating view angles without interpolating the entire frame CF_SCALEDNOLERP = 1 << 15, // [MR] flag for applying angles changes in the ticrate without interpolating the frame + CF_NOFOVINTERP = 1 << 16, // [B] Disable FOV interpolation when instantly zooming CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 996ddf7165..9f57563943 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -407,6 +407,7 @@ void AActor::PostSerialize() } } ClearInterpolation(); + ClearFOVInterpolation(); UpdateWaterLevel(false); } @@ -3552,6 +3553,28 @@ void AActor::SetViewAngle(DAngle ang, int fflags) } +double AActor::GetFOV(double ticFrac) +{ + // [B] Disable interpolation when playing online, otherwise it gets vomit inducing + if (netgame) + return player ? player->FOV : CameraFOV; + + double fov; + if (player) + { + if (player->cheats & CF_NOFOVINTERP) + return player->FOV; + + fov = player->FOV; + } + else + { + fov = CameraFOV; + } + + return PrevFOV.Degrees() * (1 - ticFrac) + fov * ticFrac; +} + void AActor::SetViewRoll(DAngle r, int fflags) { if (r != ViewAngles.Roll) @@ -4566,6 +4589,7 @@ void ConstructActor(AActor *actor, const DVector3 &pos, bool SpawningMapThing) // set subsector and/or block links actor->LinkToWorld (nullptr, SpawningMapThing); actor->ClearInterpolation(); + actor->ClearFOVInterpolation(); actor->dropoffz = actor->floorz = actor->Sector->floorplane.ZatPoint(pos); actor->ceilingz = actor->Sector->ceilingplane.ZatPoint(pos); diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 1636139add..0084bf16f7 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1266,6 +1266,7 @@ void P_PlayerThink (player_t *player) player->cheats &= ~CF_INTERPVIEW; player->cheats &= ~CF_INTERPVIEWANGLES; player->cheats &= ~CF_SCALEDNOLERP; + player->cheats &= ~CF_NOFOVINTERP; player->mo->FloatVar("prevBob") = player->bob; IFVIRTUALPTRNAME(player->mo, NAME_PlayerPawn, PlayerThink) diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index facbc59e39..8b7edabc27 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -716,6 +716,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearInterpolation, ClearInterpolation) return 0; } +DEFINE_ACTION_FUNCTION(AActor, ClearFOVInterpolation) +{ + PARAM_SELF_PROLOGUE(AActor); + self->ClearFOVInterpolation(); + return 0; +} + static int ApplyDamageFactors(PClassActor *itemcls, int damagetype, int damage, int defdamage) { DmgFactors &df = itemcls->ActorInfo()->DamageFactors; diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 978fc34ab6..fe8feefc3c 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -669,6 +669,7 @@ class Actor : Thinker native native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); native void ClearInterpolation(); + native void ClearFOVInterpolation(); native clearscope Vector3 PosRelative(sector sec) const; native void RailAttack(FRailParams p); diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index f40b7facb5..d4aa0e57da 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -464,6 +464,7 @@ class Weapon : StateProvider if (flags & 1) { // Make the zoom instant. player.FOV = player.DesiredFOV * zoom; + player.cheats |= CF_NOFOVINTERP; } if (flags & 2) { // Disable pitch/yaw scaling. diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index e6ca560a43..77df1ef269 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -220,6 +220,7 @@ extend class PlayerPawn { p.camera = morphed; } + morphed.ClearFOVInterpolation(); morphed.ScoreIcon = ScoreIcon; // [GRB] if (eflash) eflash.target = morphed; @@ -336,6 +337,7 @@ extend class PlayerPawn { player.camera = altmo; } + altmo.ClearFOVInterpolation(); // [MH] // If the player that was morphed is the one diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index fac6619af4..a8bc17bda5 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1140,6 +1140,7 @@ enum EPlayerCheats CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame CF_INTERPVIEWANGLES = 1 << 15, // [MR] flag for interpolating view angles without interpolating the entire frame CF_SCALEDNOLERP = 1 << 15, // [MR] flag for applying angles changes in the ticrate without interpolating the frame + CF_NOFOVINTERP = 1 << 16, // [B] Disable FOV interpolation when instantly zooming CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.