From 211d7446d6a390a0ff7a7448f26c98574c97fdbe Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Mon, 22 Apr 2024 09:35:24 +0200 Subject: [PATCH] effects: enable interpolation for 60 FPS --- CHANGELOG.md | 3 +++ src/game/effects.c | 22 ++++++++++++++-------- src/game/interpolation.c | 33 +++++++++++++++++++++++++++++---- src/global/types.h | 7 +++++++ 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49afa0483a..7d56f88a7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ - fixed the camera being thrown through doors for one frame when looked at from fixed camera positions (#954) - fixed console not retaining changed user settings across game relaunches (#1318) - fixed passport inventory item not being animated in 60 FPS (#1314) +- fixed object explosions not being animated in 60 FPS (#1314) +- fixed lava emitters not being animated in 60 FPS (#1314) +- fixed underwater bubbles not being animated in 60 FPS (#1314) - fixed compass needle being too fast in 60 FPS (#1316, regression from 4.0) - fixed black screen flickers that can occur in 60 FPS (#1295) - decreased initial flicker upon game launch (#1322) diff --git a/src/game/effects.c b/src/game/effects.c index 0c5720cb21..988b6e262b 100644 --- a/src/game/effects.c +++ b/src/game/effects.c @@ -119,30 +119,36 @@ void Effect_NewRoom(int16_t fx_num, int16_t room_num) r->fx_number = fx_num; } -void Effect_Draw(int16_t fxnum) +void Effect_Draw(const int16_t fxnum) { - FX_INFO *fx = &g_Effects[fxnum]; - OBJECT_INFO *object = &g_Objects[fx->object_number]; + const FX_INFO *const fx = &g_Effects[fxnum]; + const OBJECT_INFO *const object = &g_Objects[fx->object_number]; if (!object->loaded) { return; } if (object->nmeshes < 0) { Output_DrawSprite( - fx->pos.x, fx->pos.y, fx->pos.z, - object->mesh_index - fx->frame_number, 4096); + fx->interp.result.pos.x, fx->interp.result.pos.y, + fx->interp.result.pos.z, object->mesh_index - fx->frame_number, + 4096); } else { Matrix_Push(); - Matrix_TranslateAbs(fx->pos.x, fx->pos.y, fx->pos.z); + Matrix_TranslateAbs( + fx->interp.result.pos.x, fx->interp.result.pos.y, + fx->interp.result.pos.z); if (g_MatrixPtr->_23 > Output_GetNearZ() && g_MatrixPtr->_23 < Output_GetFarZ()) { - Matrix_RotYXZ(fx->rot.y, fx->rot.x, fx->rot.z); + Matrix_RotYXZ( + fx->interp.result.rot.y, fx->interp.result.rot.x, + fx->interp.result.rot.z); if (object->nmeshes) { Output_CalculateStaticLight(fx->shade); Output_DrawPolygons(g_Meshes[object->mesh_index], -1); } else { Output_CalculateLight( - fx->pos.x, fx->pos.y, fx->pos.z, fx->room_number); + fx->interp.result.pos.x, fx->interp.result.pos.y, + fx->interp.result.pos.z, fx->room_number); Output_DrawPolygons(g_Meshes[fx->frame_number], -1); } } diff --git a/src/game/interpolation.c b/src/game/interpolation.c index 2460e7a145..f13184c62b 100644 --- a/src/game/interpolation.c +++ b/src/game/interpolation.c @@ -1,6 +1,7 @@ #include "game/interpolation.h" #include "game/clock.h" +#include "game/effects.h" #include "game/items.h" #include "game/lara/lara_hair.h" #include "game/phase/phase.h" @@ -90,7 +91,7 @@ void Interpolation_Commit(void) INTERPOLATE_ROT(&g_Lara, head_rot.z, ratio, PHD_45); for (int i = 0; i < Item_GetTotalCount(); i++) { - ITEM_INFO *item = &g_Items[i]; + ITEM_INFO *const item = &g_Items[i]; if ((item->flags & IF_KILLED_ITEM) || item->status == IS_NOT_ACTIVE || item->object_number == O_BAT) { COMMIT(item, pos.x); @@ -122,9 +123,21 @@ void Interpolation_Commit(void) INTERPOLATE_ROT(g_LaraItem, rot.z, ratio, PHD_45); } + int16_t fx_num = g_NextFxActive; + while (fx_num != NO_ITEM) { + FX_INFO *const fx = &g_Effects[fx_num]; + INTERPOLATE(fx, pos.x, ratio, 128); + INTERPOLATE(fx, pos.y, ratio, MAX(128, fx->fall_speed * 2)); + INTERPOLATE(fx, pos.z, ratio, 128); + INTERPOLATE_ROT(fx, rot.x, ratio, PHD_45); + INTERPOLATE_ROT(fx, rot.y, ratio, PHD_45); + INTERPOLATE_ROT(fx, rot.z, ratio, PHD_45); + fx_num = fx->next_active; + } + if (Lara_Hair_IsActive()) { for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) { - HAIR_SEGMENT *hair = Lara_Hair_GetSegment(i); + HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i); INTERPOLATE(hair, pos.x, ratio, 128); INTERPOLATE( hair, pos.y, ratio, MAX(128, g_LaraItem->fall_speed * 2)); @@ -162,7 +175,7 @@ void Interpolation_Remember(void) REMEMBER(&g_Lara, head_rot.z); for (int i = 0; i < Item_GetTotalCount(); i++) { - ITEM_INFO *item = &g_Items[i]; + ITEM_INFO *const item = &g_Items[i]; REMEMBER(item, pos.x); REMEMBER(item, pos.y); REMEMBER(item, pos.z); @@ -180,9 +193,21 @@ void Interpolation_Remember(void) REMEMBER(g_LaraItem, rot.z); } + int16_t fx_num = g_NextFxActive; + while (fx_num != NO_ITEM) { + FX_INFO *const fx = &g_Effects[fx_num]; + REMEMBER(fx, pos.x); + REMEMBER(fx, pos.y); + REMEMBER(fx, pos.z); + REMEMBER(fx, rot.x); + REMEMBER(fx, rot.y); + REMEMBER(fx, rot.z); + fx_num = fx->next_active; + } + if (Lara_Hair_IsActive()) { for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) { - HAIR_SEGMENT *hair = Lara_Hair_GetSegment(i); + HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i); REMEMBER(hair, pos.x); REMEMBER(hair, pos.y); REMEMBER(hair, pos.z); diff --git a/src/global/types.h b/src/global/types.h index 2bec5a9716..c24a14e896 100644 --- a/src/global/types.h +++ b/src/global/types.h @@ -1364,6 +1364,13 @@ typedef struct FX_INFO { int16_t frame_number; int16_t counter; int16_t shade; + + struct { + struct { + XYZ_32 pos; + XYZ_16 rot; + } result, prev; + } interp; } FX_INFO; typedef struct LARA_INFO {