mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-21 03:21:28 +00:00
rework interpolation to allow for precalculated frames
This commit is contained in:
parent
b1318e4b22
commit
1429e22441
9 changed files with 186 additions and 84 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "palentry.h"
|
||||
#include "name.h"
|
||||
#include "dictionary.h"
|
||||
#include "bonecomponents.h"
|
||||
|
||||
extern bool save_full;
|
||||
|
||||
|
@ -247,7 +248,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString
|
|||
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &mo, struct ModelOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnim &ao, ModelAnim *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def);
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
||||
|
||||
void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "TRS.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
|
||||
class DBoneComponents : public DObject
|
||||
{
|
||||
|
@ -14,3 +16,37 @@ public:
|
|||
|
||||
DBoneComponents() = default;
|
||||
};
|
||||
|
||||
struct ModelAnimFrameInterp
|
||||
{
|
||||
float inter = -1.0f;
|
||||
int frame1 = -1;
|
||||
int frame2 = -1;
|
||||
};
|
||||
|
||||
struct ModelAnimFramePrecalculatedIQM
|
||||
{
|
||||
TArray<TRS> precalcBones;
|
||||
};
|
||||
|
||||
enum EModelAnimFlags
|
||||
{
|
||||
MODELANIM_NONE = 1 << 0, // no animation
|
||||
MODELANIM_LOOP = 1 << 1, // animation loops, otherwise it stays on the last frame once it ends
|
||||
};
|
||||
|
||||
struct ModelAnim
|
||||
{
|
||||
int firstFrame = 0;
|
||||
int lastFrame = 0;
|
||||
int loopFrame = 0;
|
||||
float framerate = 0;
|
||||
double startFrame = 0;
|
||||
int flags = MODELANIM_NONE;
|
||||
double startTic = 0; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation)
|
||||
double switchOffset = 0; // when the animation was changed -- where to interpolate the switch from
|
||||
};
|
||||
|
||||
static_assert(sizeof(ModelAnim) == sizeof(double) * 6);
|
||||
|
||||
using ModelAnimFrame = std::variant<std::nullptr_t, ModelAnimFrameInterp, ModelAnimFramePrecalculatedIQM>;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "tarray.h"
|
||||
#include "name.h"
|
||||
|
||||
#include "bonecomponents.h"
|
||||
|
||||
class DBoneComponents;
|
||||
class FModelRenderer;
|
||||
class FGameTexture;
|
||||
|
@ -94,7 +96,8 @@ public:
|
|||
virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0;
|
||||
virtual float getAspectFactor(float vscale) { return 1.f; }
|
||||
virtual const TArray<TRS>* AttachAnimationData() { return nullptr; };
|
||||
virtual const TArray<VSMatrix> CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* bones, int index) { return {}; };
|
||||
|
||||
virtual const TArray<VSMatrix> CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) { return {}; };
|
||||
|
||||
void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; }
|
||||
IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; }
|
||||
|
|
|
@ -120,7 +120,8 @@ public:
|
|||
void BuildVertexBuffer(FModelRenderer* renderer) override;
|
||||
void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override;
|
||||
const TArray<TRS>* AttachAnimationData() override;
|
||||
const TArray<VSMatrix> CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* bones, int index) override;
|
||||
const TArray<VSMatrix> CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* bones, int index);
|
||||
const TArray<VSMatrix> CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index) override;
|
||||
|
||||
private:
|
||||
void LoadGeometry();
|
||||
|
|
|
@ -560,7 +560,29 @@ static TRS InterpolateBone(const TRS &from, const TRS &to, float t, float invt)
|
|||
return bone;
|
||||
}
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBones(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* boneComponentData, int index)
|
||||
#include "printf.h"
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray<TRS>* animationData, DBoneComponents* bones, int index)
|
||||
{
|
||||
if(inter <= 0 || !(std::holds_alternative<ModelAnimFrameInterp>(from) || std::holds_alternative<ModelAnimFramePrecalculatedIQM>(from)))
|
||||
{
|
||||
return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFrameInterp>(from))
|
||||
{
|
||||
auto &from_interp = std::get<ModelAnimFrameInterp>(from);
|
||||
|
||||
Printf("CalculateBones({%d, %d, %f}, {%d, %d, %f}, %f)\n", from_interp.frame1, from_interp.frame2, from_interp.inter, to.frame1, to.frame2, to.inter, inter);
|
||||
|
||||
return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, animationData, bones, index);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFramePrecalculatedIQM>(from))
|
||||
{ //TODO
|
||||
return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, animationData, bones, index);
|
||||
}
|
||||
}
|
||||
|
||||
const TArray<VSMatrix> IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const TArray<TRS>* animationData, DBoneComponents* boneComponentData, int index)
|
||||
{
|
||||
const TArray<TRS>& animationFrames = animationData ? *animationData : TRSData;
|
||||
if (Joints.Size() > 0)
|
||||
|
|
|
@ -700,24 +700,6 @@ enum EViewPosFlags // [MC] Flags for SetViewPos.
|
|||
VPSF_ORTHOGRAPHIC = 1 << 4, // Use orthographic projection (hardware renderer only).
|
||||
};
|
||||
|
||||
enum EAnimOverrideFlags
|
||||
{
|
||||
ANIMOVERRIDE_NONE = 1 << 0, // no animation
|
||||
ANIMOVERRIDE_LOOP = 1 << 1, // animation loops, otherwise it stays on the last frame once it ends
|
||||
};
|
||||
|
||||
struct AnimOverride
|
||||
{
|
||||
int firstFrame;
|
||||
int lastFrame;
|
||||
int loopFrame;
|
||||
double startFrame;
|
||||
int flags = ANIMOVERRIDE_NONE;
|
||||
float framerate;
|
||||
double startTic; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation)
|
||||
double switchOffset; // when the animation was changed -- where to interpolate the switch from
|
||||
};
|
||||
|
||||
struct ModelOverride
|
||||
{
|
||||
int modelID;
|
||||
|
@ -753,8 +735,8 @@ public:
|
|||
int overrideFlagsSet;
|
||||
int overrideFlagsClear;
|
||||
|
||||
AnimOverride curAnim;
|
||||
AnimOverride prevAnim; // used for interpolation when switching anims
|
||||
ModelAnim curAnim;
|
||||
ModelAnimFrame prevAnim; // used for interpolation when switching anims
|
||||
|
||||
DActorModelData() = default;
|
||||
virtual void Serialize(FSerializer& arc) override;
|
||||
|
|
|
@ -5128,7 +5128,8 @@ enum ESetAnimationFlags
|
|||
SAF_NOOVERRIDE = 1 << 2,
|
||||
};
|
||||
|
||||
extern double getCurrentFrame(const AnimOverride &anim, double tic, bool *looped);
|
||||
double getCurrentFrame(const ModelAnim &anim, double tic, bool *looped);
|
||||
void calcFrame(const ModelAnim &anim, double tic, ModelAnimFrameInterp &inter);
|
||||
|
||||
void SetAnimationInternal(AActor * self, FName animName, double framerate, int startFrame, int loopFrame, int endFrame, int interpolateTics, int flags, double ticFrac)
|
||||
{
|
||||
|
@ -5150,7 +5151,7 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(animName == NAME_None)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5165,12 +5166,12 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
int animStart = mdl->FindFirstFrame(animName);
|
||||
if(animStart == FErr_NotFound)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("Could not find animation %s\n", animName.GetChars());
|
||||
return;
|
||||
}
|
||||
|
||||
if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != ANIMOVERRIDE_NONE && self->modelData->curAnim.firstFrame == animStart)
|
||||
if((flags & SAF_NOOVERRIDE) && self->modelData->curAnim.flags != MODELANIM_NONE && self->modelData->curAnim.firstFrame == animStart)
|
||||
{
|
||||
//same animation as current, skip setting it
|
||||
return;
|
||||
|
@ -5184,14 +5185,15 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(!(flags & SAF_INSTANT))
|
||||
{
|
||||
self->modelData->prevAnim = self->modelData->curAnim;
|
||||
|
||||
bool looped = false;
|
||||
self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic, &looped);
|
||||
|
||||
if(!looped)
|
||||
if(self->modelData->curAnim.startTic > tic)
|
||||
{
|
||||
self->modelData->prevAnim.flags &= ~ANIMOVERRIDE_LOOP;
|
||||
//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
self->modelData->prevAnim = ModelAnimFrameInterp{};
|
||||
|
||||
calcFrame(self->modelData->curAnim, tic, std::get<ModelAnimFrameInterp>(self->modelData->prevAnim));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5206,19 +5208,19 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
|
||||
if(startFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (startFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
else if(loopFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (loopFrame) is past the end of animation %s\n", startFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
else if(endFrame >= len)
|
||||
{
|
||||
self->modelData->curAnim.flags = ANIMOVERRIDE_NONE;
|
||||
self->modelData->curAnim.flags = MODELANIM_NONE;
|
||||
Printf("frame %d (endFrame) is past the end of animation %s\n", endFrame, animName.GetChars());
|
||||
return;
|
||||
}
|
||||
|
@ -5227,12 +5229,12 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s
|
|||
self->modelData->curAnim.lastFrame = endFrame < 0 ? animEnd - 1 : animStart + endFrame;
|
||||
self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame;
|
||||
self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame;
|
||||
self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0;
|
||||
self->modelData->curAnim.flags = (flags & SAF_LOOP) ? MODELANIM_LOOP : 0;
|
||||
self->modelData->curAnim.framerate = (float)framerate;
|
||||
|
||||
if(!(flags & SAF_INSTANT))
|
||||
{
|
||||
int startTic = floor(tic) + interpolateTics;
|
||||
int startTic = int(floor(tic)) + interpolateTics;
|
||||
self->modelData->curAnim.startTic = startTic;
|
||||
self->modelData->curAnim.switchOffset = startTic - tic;
|
||||
}
|
||||
|
@ -5264,7 +5266,7 @@ void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFr
|
|||
|
||||
EnsureModelData(self);
|
||||
|
||||
if(self->modelData->curAnim.flags & ANIMOVERRIDE_NONE) return;
|
||||
if(self->modelData->curAnim.flags & MODELANIM_NONE) return;
|
||||
|
||||
if(framerate < 0)
|
||||
{
|
||||
|
|
|
@ -1443,7 +1443,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, AnimModelOverride &amo
|
|||
return arc;
|
||||
}
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def)
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelAnim &ao, struct ModelAnim *def)
|
||||
{
|
||||
arc.BeginObject(key);
|
||||
arc("firstFrame", ao.firstFrame);
|
||||
|
@ -1458,6 +1458,64 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &a
|
|||
return arc;
|
||||
}
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def)
|
||||
{
|
||||
arc.BeginObject(key);
|
||||
if(arc.isReading())
|
||||
{
|
||||
if(arc.HasKey("firstFrame"))
|
||||
{ // legacy save, clear interpolation
|
||||
ao = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
FString type = "nullptr";
|
||||
arc("type", type);
|
||||
if(type.Compare("nullptr") == 0)
|
||||
{
|
||||
ao = nullptr;
|
||||
}
|
||||
else if(type.Compare("interp") == 0)
|
||||
{
|
||||
ModelAnimFrameInterp tmp;
|
||||
arc("inter", tmp.inter);
|
||||
arc("frame1", tmp.frame1);
|
||||
arc("frame2", tmp.frame2);
|
||||
ao = tmp;
|
||||
}
|
||||
else if(type.Compare("precalcIQM") == 0)
|
||||
{
|
||||
//TODO, unreachable
|
||||
ao = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // if(arc.isWriting())
|
||||
{
|
||||
if(std::holds_alternative<std::nullptr_t>(ao))
|
||||
{
|
||||
FString tmp = "nullptr";
|
||||
arc("type", tmp);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFrameInterp>(ao))
|
||||
{
|
||||
FString type = "interp";
|
||||
arc("type", type);
|
||||
arc("inter", std::get<ModelAnimFrameInterp>(ao).inter);
|
||||
arc("frame1", std::get<ModelAnimFrameInterp>(ao).frame1);
|
||||
arc("frame2", std::get<ModelAnimFrameInterp>(ao).frame2);
|
||||
}
|
||||
else if(std::holds_alternative<ModelAnimFramePrecalculatedIQM>(ao))
|
||||
{
|
||||
//TODO
|
||||
FString type = "nullptr";
|
||||
arc("type", type);
|
||||
}
|
||||
}
|
||||
arc.EndObject();
|
||||
return arc;
|
||||
}
|
||||
|
||||
void DActorModelData::Serialize(FSerializer& arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
@ -3862,7 +3920,7 @@ void AActor::Tick ()
|
|||
special2++;
|
||||
}
|
||||
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
modelData->curAnim.startTic += 1;
|
||||
}
|
||||
|
@ -3915,7 +3973,7 @@ void AActor::Tick ()
|
|||
special2++;
|
||||
}
|
||||
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
modelData->curAnim.startTic += 1;
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ void RenderHUDModel(FModelRenderer *renderer, DPSprite *psp, FVector3 translatio
|
|||
renderer->EndDrawHUDModel(playermo->RenderStyle, smf_flags);
|
||||
}
|
||||
|
||||
double getCurrentFrame(const AnimOverride &anim, double tic, bool *looped)
|
||||
double getCurrentFrame(const ModelAnim &anim, double tic, bool *looped)
|
||||
{
|
||||
if(anim.framerate <= 0) return anim.startFrame;
|
||||
|
||||
|
@ -266,7 +266,7 @@ double getCurrentFrame(const AnimOverride &anim, double tic, bool *looped)
|
|||
|
||||
double duration = double(anim.lastFrame) - anim.startFrame;
|
||||
|
||||
if((anim.flags & ANIMOVERRIDE_LOOP) && frame >= duration)
|
||||
if((anim.flags & MODELANIM_LOOP) && frame >= duration)
|
||||
{
|
||||
if(looped) *looped = true;
|
||||
frame = frame - duration;
|
||||
|
@ -278,26 +278,37 @@ double getCurrentFrame(const AnimOverride &anim, double tic, bool *looped)
|
|||
}
|
||||
}
|
||||
|
||||
static void fixFrame(const AnimOverride &anim, double frame, double &inter, int &prev, int &next, bool looped)
|
||||
void calcFrame(const ModelAnim &anim, double tic, ModelAnimFrameInterp &inter)
|
||||
{
|
||||
prev = int(floor(frame));
|
||||
bool looped = false;
|
||||
|
||||
double frame = getCurrentFrame(anim, tic, &looped);
|
||||
|
||||
inter.frame1 = int(floor(frame));
|
||||
|
||||
inter.inter = frame - inter.frame1;
|
||||
|
||||
inter.frame2 = int(ceil(frame));
|
||||
|
||||
int startFrame = (looped ? anim.startFrame : anim.loopFrame);
|
||||
|
||||
if(prev < startFrame) prev = anim.lastFrame;
|
||||
|
||||
inter = frame - prev;
|
||||
|
||||
next = int(ceil(frame));
|
||||
|
||||
if(next > anim.lastFrame) next = startFrame;
|
||||
if(inter.frame1 < startFrame) inter.frame1 = anim.lastFrame;
|
||||
if(inter.frame2 > anim.lastFrame) inter.frame2 = startFrame;
|
||||
}
|
||||
|
||||
static void calcFrame(const AnimOverride &anim, double tic, double &inter, int &prev, int &next)
|
||||
void calcFrames(const ModelAnim &curAnim, double tic, ModelAnimFrameInterp &to, float &inter)
|
||||
{
|
||||
bool looped = false;
|
||||
double frame = getCurrentFrame(anim, tic, &looped);
|
||||
fixFrame(anim, frame, inter, prev, next, looped);
|
||||
if(curAnim.startTic > tic)
|
||||
{
|
||||
inter = (tic - (curAnim.startTic - curAnim.switchOffset)) / curAnim.switchOffset;
|
||||
|
||||
calcFrame(curAnim, curAnim.startTic, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
inter = -1.0f;
|
||||
calcFrame(curAnim, tic, to);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpriteModelFrame *smf, const FState *curState, const int curTics, FTranslationID translation, AActor* actor)
|
||||
|
@ -308,17 +319,11 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
int smf_flags = smf->getFlags(actor->modelData);
|
||||
|
||||
const FSpriteModelFrame * smfNext = nullptr;
|
||||
double inter = 0.;
|
||||
double inter_main = -1.f;
|
||||
double inter_next = -1.f;
|
||||
float inter = 0.;
|
||||
|
||||
bool is_decoupled = (actor->flags9 & MF9_DECOUPLEDANIMATIONS);
|
||||
|
||||
int decoupled_main_prev_frame = -1;
|
||||
int decoupled_next_prev_frame = -1;
|
||||
|
||||
int decoupled_main_frame = -1;
|
||||
int decoupled_next_frame = -1;
|
||||
ModelAnimFrameInterp decoupled_frame;
|
||||
|
||||
// if prev_frame == -1: interpolate(main_frame, next_frame, inter), else: interpolate(interpolate(main_prev_frame, main_frame, inter_main), interpolate(next_prev_frame, next_frame, inter_next), inter)
|
||||
// 4-way interpolation is needed to interpolate animation switches between animations that aren't 35hz
|
||||
|
@ -326,24 +331,15 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
if(is_decoupled)
|
||||
{
|
||||
smfNext = smf = &BaseSpriteModelFrames[actor->GetClass()];
|
||||
if(actor->modelData && !(actor->modelData->curAnim.flags & ANIMOVERRIDE_NONE))
|
||||
if(actor->modelData && !(actor->modelData->curAnim.flags & MODELANIM_NONE))
|
||||
{
|
||||
double tic = actor->Level->totaltime;
|
||||
if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen())
|
||||
{
|
||||
tic += I_GetTimeFrac();
|
||||
}
|
||||
if(actor->modelData->curAnim.startTic > tic)
|
||||
{
|
||||
inter = (tic - (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchOffset)) / actor->modelData->curAnim.switchOffset;
|
||||
|
||||
fixFrame(actor->modelData->curAnim, actor->modelData->curAnim.startFrame, inter_next, decoupled_next_prev_frame, decoupled_next_frame, false);
|
||||
fixFrame(actor->modelData->prevAnim, actor->modelData->prevAnim.startFrame, inter_main, decoupled_main_prev_frame, decoupled_main_frame, actor->modelData->prevAnim.flags & ANIMOVERRIDE_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
calcFrame(actor->modelData->curAnim, tic, inter, decoupled_main_frame, decoupled_next_frame);
|
||||
}
|
||||
calcFrames(actor->modelData->curAnim, tic, decoupled_frame, inter);
|
||||
}
|
||||
}
|
||||
else if (gl_interpolate_model_frames && !(smf_flags & MDL_NOINTERPOLATION))
|
||||
|
@ -543,14 +539,14 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
|
||||
if(is_decoupled)
|
||||
{
|
||||
if(decoupled_main_frame != -1)
|
||||
if(decoupled_frame.frame1 != -1)
|
||||
{
|
||||
boneData = animation->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, animationData, actor->boneComponentData, i);
|
||||
boneData = animation->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boneData = animation->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, animationData, actor->boneComponentData, i);
|
||||
boneData = animation->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, animationData, actor->boneComponentData, i);
|
||||
}
|
||||
boneStartingPosition = renderer->SetupFrame(animation, 0, 0, 0, boneData, -1);
|
||||
evaluatedSingle = true;
|
||||
|
@ -559,14 +555,14 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
{
|
||||
if(is_decoupled)
|
||||
{
|
||||
if(decoupled_main_frame != -1)
|
||||
if(decoupled_frame.frame1 != -1)
|
||||
{
|
||||
boneData = mdl->CalculateBones(decoupled_main_frame, decoupled_next_frame, inter, decoupled_main_prev_frame, inter_main, decoupled_next_prev_frame, inter_next, nullptr, actor->boneComponentData, i);
|
||||
boneData = mdl->CalculateBones(actor->modelData->prevAnim, decoupled_frame, inter, nullptr, actor->boneComponentData, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boneData = mdl->CalculateBones(modelframe, modelframenext, nextFrame ? inter : -1.f, 0, -1.f, 0, -1.f, nullptr, actor->boneComponentData, i);
|
||||
boneData = mdl->CalculateBones(nullptr, {nextFrame ? inter : -1.0f, modelframe, modelframenext}, -1.0f, nullptr, actor->boneComponentData, i);
|
||||
}
|
||||
boneStartingPosition = renderer->SetupFrame(mdl, 0, 0, 0, boneData, -1);
|
||||
evaluatedSingle = true;
|
||||
|
|
Loading…
Reference in a new issue