From 9af3d54a19f39dea6cf556ce68d26fe51797aabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 17 Apr 2024 21:26:54 -0300 Subject: [PATCH] Fix Decoupled Animation Crash, Interpolation Bugs, Simplify Interpolation code --- src/common/models/models_iqm.cpp | 4 +-- src/playsim/p_actionfunctions.cpp | 28 +++++++++-------- src/r_data/models.cpp | 52 +++++++++++++++++++++---------- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/common/models/models_iqm.cpp b/src/common/models/models_iqm.cpp index 1184a9390b..891a19647e 100644 --- a/src/common/models/models_iqm.cpp +++ b/src/common/models/models_iqm.cpp @@ -599,14 +599,14 @@ const TArray IQMModel::CalculateBones(int frame1, int frame2, float in if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0)) { - prev = inter1_prev < 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1); + prev = inter1_prev <= 0 ? animationFrames[offset1 + i] : InterpolateBone(animationFrames[offset1_1 + i], animationFrames[offset1 + i], inter1_prev, invt1); } TRS next; if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0)) { - next = inter2_prev < 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2); + next = inter2_prev <= 0 ? animationFrames[offset2 + i] : InterpolateBone(animationFrames[offset2_1 + i], animationFrames[offset2 + i], inter2_prev, invt2); } TRS bone; diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 3c48725bb9..f790cfb802 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -5128,6 +5128,8 @@ enum ESetAnimationFlags SAF_NOOVERRIDE = 1 << 2, }; +extern double getCurrentFrame(const AnimOverride &anim, double tic); + void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags, double ticFrac) { if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self"); @@ -5152,11 +5154,6 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s return; } - if(!(flags & SAF_INSTANT)) - { - self->modelData->prevAnim = self->modelData->curAnim; - } - double tic = self->Level->totaltime; if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen()) { @@ -5179,6 +5176,11 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s return; } + if(!(flags & SAF_INSTANT)) + { + self->modelData->prevAnim = self->modelData->curAnim; + } + int animEnd = mdl->FindLastFrame(animName); if(framerate < 0) @@ -5217,6 +5219,8 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s if(!(flags & SAF_INSTANT)) { + self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic); + self->modelData->curAnim.startTic = floor(tic) + interpolateTics; } else @@ -5235,8 +5239,6 @@ void SetAnimationUINative(AActor * self, int i_animName, double framerate, int s SetAnimationInternal(self, FName(ENamedName(i_animName)), framerate, startFrame, loopFrame, endFrame, interpolateTics, flags, I_GetTimeFrac()); } -extern double getCurrentFrame(const AnimOverride &anim, double tic); - void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFrac) { if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self"); @@ -5256,18 +5258,18 @@ void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFr } - if(self->modelData->curAnim.startTic < ticFrac) - { - self->modelData->curAnim.framerate = (float)framerate; - return; - } - double tic = self->Level->totaltime; if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen()) { tic += ticFrac; } + if(self->modelData->curAnim.startTic >= tic) + { + self->modelData->curAnim.framerate = (float)framerate; + return; + } + double frame = getCurrentFrame(self->modelData->curAnim, tic); self->modelData->curAnim.startFrame = frame; diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 4e5d368568..c2268cef81 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -323,9 +323,18 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr if(actor->modelData->curAnim.startTic > tic) { inter = (tic - actor->modelData->curAnim.switchTic) / (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchTic); - - calcFrame(actor->modelData->curAnim, actor->modelData->curAnim.startTic, inter_next, decoupled_next_prev_frame, decoupled_next_frame); - calcFrame(actor->modelData->prevAnim, actor->modelData->curAnim.switchTic, inter_main, decoupled_main_prev_frame, decoupled_main_frame); + + double nextFrame = actor->modelData->curAnim.startFrame; + + double prevFrame = actor->modelData->prevAnim.startFrame; + + decoupled_next_prev_frame = floor(nextFrame); + decoupled_next_frame = ceil(nextFrame); + inter_next = nextFrame - floor(nextFrame); + + decoupled_main_prev_frame = floor(prevFrame); + decoupled_main_frame = ceil(prevFrame); + inter_main = prevFrame - floor(prevFrame); } else { @@ -1073,22 +1082,31 @@ void ParseModelDefLump(int Lump) FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped) { - if (GetDefaultByType(ti)->hasmodel) + auto def = GetDefaultByType(ti); + if (def->hasmodel) { - FSpriteModelFrame smf; - - memset(&smf, 0, sizeof(smf)); - smf.type=ti; - smf.sprite=sprite; - smf.frame=frame; - - int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; - - while (hash>=0) + if(def->flags9 & MF9_DECOUPLEDANIMATIONS) { - FSpriteModelFrame * smff = &SpriteModelFrames[hash]; - if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; - hash=smff->hashnext; + FSpriteModelFrame * smf = BaseSpriteModelFrames.CheckKey((void*)ti); + if(smf) return smf; + } + else + { + FSpriteModelFrame smf; + + memset(&smf, 0, sizeof(smf)); + smf.type=ti; + smf.sprite=sprite; + smf.frame=frame; + + int hash = SpriteModelHash[ModelFrameHash(&smf) % SpriteModelFrames.Size()]; + + while (hash>=0) + { + FSpriteModelFrame * smff = &SpriteModelFrames[hash]; + if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff; + hash=smff->hashnext; + } } }