diff --git a/include/d/actor/d_a_obj_klift00.h b/include/d/actor/d_a_obj_klift00.h index 865fab8c47..ab5403d51b 100644 --- a/include/d/actor/d_a_obj_klift00.h +++ b/include/d/actor/d_a_obj_klift00.h @@ -25,6 +25,10 @@ public: int Draw(); int Delete(); +#if TARGET_PC + void onInterpCallback(); +#endif + enum Param_e { LOCK_e = (1 << 6), NO_BASE_DISP = (1 << 7) }; @@ -50,6 +54,13 @@ private: /* 0x1020 */ dCcD_Cyl mCylinderCollider; /* 0x115C */ s32 mStopSwingingFrames; +#if TARGET_PC + cXyz mChainInterpPrev[64]; + cXyz mChainInterpCurr[64]; + bool mChainInterpPrevValid; + bool mChainInterpCurrValid; +#endif + // Number of chain models u32 getArg0() { return fopAcM_GetParamBit(this, 0, 6); diff --git a/src/d/actor/d_a_obj_klift00.cpp b/src/d/actor/d_a_obj_klift00.cpp index 99b204592e..e44cce7467 100644 --- a/src/d/actor/d_a_obj_klift00.cpp +++ b/src/d/actor/d_a_obj_klift00.cpp @@ -11,6 +11,8 @@ #include "d/d_bg_w.h" #include "d/d_cc_uty.h" #include "d/d_com_inf_game.h" +#include "dusk/frame_interpolation.h" +#include "dusk/settings.h" struct daObjKLift00_HIO_c : public mDoHIO_entry_c { daObjKLift00_HIO_c(); @@ -295,6 +297,11 @@ int daObjKLift00_c::Create() { if(getLock()) mStopSwingingFrames = 5; +#if TARGET_PC + mChainInterpPrevValid = false; + mChainInterpCurrValid = false; +#endif + return 1; } @@ -436,6 +443,34 @@ int daObjKLift00_c::Execute(Mtx** i_mtx) { return 1; } +#if TARGET_PC +static void klift00_interp_callback(bool isSimFrame, void* pUserWork) { + static_cast(pUserWork)->onInterpCallback(); +} + +void daObjKLift00_c::onInterpCallback() { + if (!mChainInterpPrevValid || !mChainInterpCurrValid) { + return; + } + + const f32 alpha = dusk::frame_interp::get_interpolation_step(); + cXyz savedPositions[64]; + + for (int i = 0; i < mNumChains; i++) { + savedPositions[i] = mChainPositions[i].mCurrentPos; + const cXyz& p0 = mChainInterpPrev[i]; + const cXyz& p1 = mChainInterpCurr[i]; + mChainPositions[i].mCurrentPos = p0 + (p1 - p0) * alpha; + } + + setMtx(); + + for (int i = 0; i < mNumChains; i++) { + mChainPositions[i].mCurrentPos = savedPositions[i]; + } +} +#endif + int daObjKLift00_c::Draw() { g_env_light.settingTevStruct(16, ¤t.pos, &tevStr); g_env_light.setLightTevColorType_MAJI(mpLiftPlatform, &tevStr); @@ -457,6 +492,22 @@ int daObjKLift00_c::Draw() { dComIfGd_setList(); +#if TARGET_PC + if (dusk::getSettings().game.enableFrameInterpolation) { + if (mChainInterpCurrValid) { + memcpy(mChainInterpPrev, mChainInterpCurr, mNumChains * sizeof(cXyz)); + mChainInterpPrevValid = true; + } + + for (int i = 0; i < mNumChains; i++) { + mChainInterpCurr[i] = mChainPositions[i].mCurrentPos; + } + + mChainInterpCurrValid = true; + dusk::frame_interp::add_interpolation_callback(&klift00_interp_callback, this); + } +#endif + return 1; }