diff --git a/include/d/actor/d_a_e_mb.h b/include/d/actor/d_a_e_mb.h index f36c744879..527cf30eac 100644 --- a/include/d/actor/d_a_e_mb.h +++ b/include/d/actor/d_a_e_mb.h @@ -44,6 +44,12 @@ public: /* 0x88C */ u8 field_0x88C[0x8C8 - 0x88C]; /* 0x8C8 */ s8 field_0x8c8; /* 0x8C9 */ u8 mInitHIO; +#if TARGET_PC + cXyz mRopeInterpPrev[16]; + cXyz mRopeInterpCurr[16]; + bool mRopeInterpPrevValid; + bool mRopeInterpCurrValid; +#endif }; STATIC_ASSERT(sizeof(e_mb_class) == 0x8cc); diff --git a/src/d/actor/d_a_e_mb.cpp b/src/d/actor/d_a_e_mb.cpp index 939b253475..aa77a99612 100644 --- a/src/d/actor/d_a_e_mb.cpp +++ b/src/d/actor/d_a_e_mb.cpp @@ -12,6 +12,8 @@ #include "d/d_bomb.h" #include "c/c_damagereaction.h" #include "Z2AudioLib/Z2Instances.h" +#include "dusk/frame_interpolation.h" +#include "dusk/settings.h" #define ACTION_STANDBY 0 #define ACTION_WALK1 1 @@ -63,6 +65,22 @@ static void anm_init(e_mb_class* i_this, int i_anmID, f32 i_morf, u8 i_attr, f32 i_this->mAnm = i_anmID; } +#if TARGET_PC +static void e_mb_rope_interp_callback(bool isSimFrame, void* pUserWork) { + e_mb_class* i_this = (e_mb_class*)pUserWork; + if (!i_this->mRopeInterpPrevValid || !i_this->mRopeInterpCurrValid) { + return; + } + const f32 alpha = dusk::frame_interp::get_interpolation_step(); + cXyz* dst = i_this->mRopeMat.getPos(0); + for (int i = 0; i < 16; i++) { + const cXyz& p0 = i_this->mRopeInterpPrev[i]; + const cXyz& p1 = i_this->mRopeInterpCurr[i]; + dst[i] = p0 + (p1 - p0) * alpha; + } +} +#endif + static int daE_MB_Draw(e_mb_class* i_this) { fopAc_ac_c* a_this = (fopAc_ac_c*)i_this; @@ -86,6 +104,17 @@ static int daE_MB_Draw(e_mb_class* i_this) { static GXColor l_color = {0x14, 0x0F, 0x00, 0xFF}; i_this->mRopeMat.update(16, l_color, &a_this->tevStr); dComIfGd_set3DlineMat(&i_this->mRopeMat); +#if TARGET_PC + if (dusk::getSettings().game.enableFrameInterpolation) { + if (i_this->mRopeInterpCurrValid) { + memcpy(i_this->mRopeInterpPrev, i_this->mRopeInterpCurr, sizeof(i_this->mRopeInterpCurr)); + i_this->mRopeInterpPrevValid = true; + } + memcpy(i_this->mRopeInterpCurr, i_this->mRopeMat.getPos(0), 16 * sizeof(cXyz)); + i_this->mRopeInterpCurrValid = true; + dusk::frame_interp::add_interpolation_callback(&e_mb_rope_interp_callback, i_this); + } +#endif return 1; }