mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-28 23:02:07 +00:00
Fix Decoupled Animation Crash, Interpolation Bugs, Simplify Interpolation code
This commit is contained in:
parent
1c3764ec89
commit
9af3d54a19
3 changed files with 52 additions and 32 deletions
|
@ -599,14 +599,14 @@ const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float in
|
||||||
|
|
||||||
if(frame1 >= 0 && (frame1_prev >= 0 || inter1_prev < 0))
|
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;
|
TRS next;
|
||||||
|
|
||||||
if(frame2 >= 0 && (frame2_prev >= 0 || inter2_prev < 0))
|
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;
|
TRS bone;
|
||||||
|
|
|
@ -5128,6 +5128,8 @@ enum ESetAnimationFlags
|
||||||
SAF_NOOVERRIDE = 1 << 2,
|
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)
|
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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(flags & SAF_INSTANT))
|
|
||||||
{
|
|
||||||
self->modelData->prevAnim = self->modelData->curAnim;
|
|
||||||
}
|
|
||||||
|
|
||||||
double tic = self->Level->totaltime;
|
double tic = self->Level->totaltime;
|
||||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!(flags & SAF_INSTANT))
|
||||||
|
{
|
||||||
|
self->modelData->prevAnim = self->modelData->curAnim;
|
||||||
|
}
|
||||||
|
|
||||||
int animEnd = mdl->FindLastFrame(animName);
|
int animEnd = mdl->FindLastFrame(animName);
|
||||||
|
|
||||||
if(framerate < 0)
|
if(framerate < 0)
|
||||||
|
@ -5217,6 +5219,8 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
||||||
|
|
||||||
if(!(flags & SAF_INSTANT))
|
if(!(flags & SAF_INSTANT))
|
||||||
{
|
{
|
||||||
|
self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic);
|
||||||
|
|
||||||
self->modelData->curAnim.startTic = floor(tic) + interpolateTics;
|
self->modelData->curAnim.startTic = floor(tic) + interpolateTics;
|
||||||
}
|
}
|
||||||
else
|
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());
|
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)
|
void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFrac)
|
||||||
{
|
{
|
||||||
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
|
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;
|
double tic = self->Level->totaltime;
|
||||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen())
|
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !self->Level->isFrozen())
|
||||||
{
|
{
|
||||||
tic += ticFrac;
|
tic += ticFrac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(self->modelData->curAnim.startTic >= tic)
|
||||||
|
{
|
||||||
|
self->modelData->curAnim.framerate = (float)framerate;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double frame = getCurrentFrame(self->modelData->curAnim, tic);
|
double frame = getCurrentFrame(self->modelData->curAnim, tic);
|
||||||
|
|
||||||
self->modelData->curAnim.startFrame = frame;
|
self->modelData->curAnim.startFrame = frame;
|
||||||
|
|
|
@ -323,9 +323,18 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
||||||
if(actor->modelData->curAnim.startTic > tic)
|
if(actor->modelData->curAnim.startTic > tic)
|
||||||
{
|
{
|
||||||
inter = (tic - actor->modelData->curAnim.switchTic) / (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchTic);
|
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);
|
double nextFrame = actor->modelData->curAnim.startFrame;
|
||||||
calcFrame(actor->modelData->prevAnim, actor->modelData->curAnim.switchTic, inter_main, decoupled_main_prev_frame, decoupled_main_frame);
|
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1073,22 +1082,31 @@ void ParseModelDefLump(int Lump)
|
||||||
|
|
||||||
FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped)
|
FSpriteModelFrame * FindModelFrameRaw(const PClass * ti, int sprite, int frame, bool dropped)
|
||||||
{
|
{
|
||||||
if (GetDefaultByType(ti)->hasmodel)
|
auto def = GetDefaultByType(ti);
|
||||||
|
if (def->hasmodel)
|
||||||
{
|
{
|
||||||
FSpriteModelFrame smf;
|
if(def->flags9 & MF9_DECOUPLEDANIMATIONS)
|
||||||
|
|
||||||
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];
|
FSpriteModelFrame * smf = BaseSpriteModelFrames.CheckKey((void*)ti);
|
||||||
if (smff->type==ti && smff->sprite==sprite && smff->frame==frame) return smff;
|
if(smf) return smf;
|
||||||
hash=smff->hashnext;
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue