Make animations more consistent with high float values

This commit is contained in:
Jupeyy 2020-10-04 02:30:36 +02:00
parent b33b3295c0
commit 50b20fb1cd
8 changed files with 57 additions and 38 deletions

View file

@ -59,7 +59,7 @@ void CMapLayers::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *p
Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]); Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]);
} }
void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) void CMapLayers::EnvelopeEval(int TimeOffsetMillis, int Env, float *pChannels, void *pUser)
{ {
CMapLayers *pThis = (CMapLayers *)pUser; CMapLayers *pThis = (CMapLayers *)pUser;
pChannels[0] = 0; pChannels[0] = 0;
@ -84,8 +84,10 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start + Env, 0, 0); CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start + Env, 0, 0);
static float s_Time = 0.0f; const int64 TickToMicroSeconds = (1000000ll / (int64)pThis->Client()->GameTickSpeed());
static float s_LastLocalTime = pThis->LocalTime();
static int64 s_Time = 0;
static int64 s_LastLocalTime = time_get_microseconds();
if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK)
{ {
const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo();
@ -99,18 +101,26 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
} }
if(pItem->m_Version < 2 || pItem->m_Synchronized) if(pItem->m_Version < 2 || pItem->m_Synchronized)
{ {
s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), // get the lerp of the current tick and prev
(pThis->Client()->GameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), int MinTick = pThis->Client()->PrevGameTick(g_Config.m_ClDummy);
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); s_Time = (int64)(mix<double>(
0,
(pThis->Client()->GameTick(g_Config.m_ClDummy) - MinTick),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)) *
TickToMicroSeconds) +
MinTick * TickToMicroSeconds;
} }
else else
{ {
s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), int MinTick = pThis->m_LastLocalTick;
pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), s_Time = (int64)(mix<double>(0,
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); pThis->m_CurrentLocalTick - MinTick,
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)) *
TickToMicroSeconds) +
MinTick * TickToMicroSeconds;
} }
} }
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + TimeOffset, pChannels); pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + (int64)TimeOffsetMillis * 1000ll, pChannels);
} }
else else
{ {
@ -118,17 +128,23 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void
{ {
if(pThis->m_pClient->m_Snap.m_pGameInfoObj) // && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) if(pThis->m_pClient->m_Snap.m_pGameInfoObj) // && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
{ {
s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), // get the lerp of the current tick and prev
(pThis->Client()->GameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), int MinTick = pThis->Client()->PrevGameTick(g_Config.m_ClDummy);
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); s_Time = (int64)(mix<double>(
0,
(pThis->Client()->GameTick(g_Config.m_ClDummy) - MinTick),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy)) *
TickToMicroSeconds) +
MinTick * TickToMicroSeconds;
} }
} }
else else
{ {
s_Time += pThis->LocalTime() - s_LastLocalTime; int64 CurTime = time_get_microseconds();
s_LastLocalTime = pThis->LocalTime(); s_Time += CurTime - s_LastLocalTime;
s_LastLocalTime = CurTime;
} }
pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + TimeOffset, pChannels); pThis->RenderTools()->RenderEvalEnvelope(pPoints + pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time + (int64)TimeOffsetMillis * 1000ll, pChannels);
} }
} }
@ -989,7 +1005,7 @@ void CMapLayers::RenderTileLayer(int LayerIndex, ColorRGBA *pColor, CMapItemLaye
if(pTileLayer->m_ColorEnv >= 0) if(pTileLayer->m_ColorEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
EnvelopeEval(pTileLayer->m_ColorEnvOffset / 1000.0f, pTileLayer->m_ColorEnv, aChannels, this); EnvelopeEval(pTileLayer->m_ColorEnvOffset, pTileLayer->m_ColorEnv, aChannels, this);
r = aChannels[0]; r = aChannels[0];
g = aChannels[1]; g = aChannels[1];
b = aChannels[2]; b = aChannels[2];
@ -1379,7 +1395,7 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
aColor[0] = aColor[1] = aColor[2] = aColor[3] = 1.f; aColor[0] = aColor[1] = aColor[2] = aColor[3] = 1.f;
if(q->m_ColorEnv >= 0) if(q->m_ColorEnv >= 0)
{ {
EnvelopeEval(q->m_ColorEnvOffset / 1000.0f, q->m_ColorEnv, aColor, this); EnvelopeEval(q->m_ColorEnvOffset, q->m_ColorEnv, aColor, this);
} }
float OffsetX = 0; float OffsetX = 0;
@ -1389,7 +1405,7 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
if(q->m_PosEnv >= 0) if(q->m_PosEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
EnvelopeEval(q->m_PosEnvOffset / 1000.0f, q->m_PosEnv, aChannels, this); EnvelopeEval(q->m_PosEnvOffset, q->m_PosEnv, aChannels, this);
OffsetX = aChannels[0]; OffsetX = aChannels[0];
OffsetY = aChannels[1]; OffsetY = aChannels[1];
Rot = aChannels[2] / 180.0f * pi; Rot = aChannels[2] / 180.0f * pi;

View file

@ -151,7 +151,7 @@ public:
void EnvelopeUpdate(); void EnvelopeUpdate();
static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); static void EnvelopeEval(int TimeOffsetMillis, int Env, float *pChannels, void *pUser);
}; };
#endif #endif

View file

@ -199,7 +199,7 @@ void CMapSounds::OnRender()
if(pVoice->m_pSource->m_PosEnv >= 0) if(pVoice->m_pSource->m_PosEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
CMapLayers::EnvelopeEval(pVoice->m_pSource->m_PosEnvOffset / 1000.0f, pVoice->m_pSource->m_PosEnv, aChannels, m_pClient->m_pMapLayersBackGround); CMapLayers::EnvelopeEval(pVoice->m_pSource->m_PosEnvOffset, pVoice->m_pSource->m_PosEnv, aChannels, m_pClient->m_pMapLayersBackGround);
OffsetX = aChannels[0]; OffsetX = aChannels[0];
OffsetY = aChannels[1]; OffsetY = aChannels[1];
} }
@ -218,7 +218,7 @@ void CMapSounds::OnRender()
if(pVoice->m_pSource->m_SoundEnv >= 0) if(pVoice->m_pSource->m_SoundEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
CMapLayers::EnvelopeEval(pVoice->m_pSource->m_SoundEnvOffset / 1000.0f, pVoice->m_pSource->m_SoundEnv, aChannels, m_pClient->m_pMapLayersBackGround); CMapLayers::EnvelopeEval(pVoice->m_pSource->m_SoundEnvOffset, pVoice->m_pSource->m_SoundEnv, aChannels, m_pClient->m_pMapLayersBackGround);
float Volume = clamp(aChannels[0], 0.0f, 1.0f); float Volume = clamp(aChannels[0], 0.0f, 1.0f);
Sound()->SetVoiceVolume(pVoice->m_Voice, Volume); Sound()->SetVoiceVolume(pVoice->m_Voice, Volume);

View file

@ -39,7 +39,7 @@ enum
TILERENDERFLAG_EXTEND = 4, TILERENDERFLAG_EXTEND = 4,
}; };
typedef void (*ENVELOPE_EVAL)(float TimeOffset, int Env, float *pChannels, void *pUser); typedef void (*ENVELOPE_EVAL)(int TimeOffsetMillis, int Env, float *pChannels, void *pUser);
class CRenderTools class CRenderTools
{ {
@ -83,7 +83,7 @@ public:
void RenderTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos, float Alpha = 1.0f); void RenderTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos, float Alpha = 1.0f);
// map render methods (gc_render_map.cpp) // map render methods (gc_render_map.cpp)
static void RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult); static void RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, int64 TimeMicros, float *pResult);
void RenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser); void RenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser);
void ForceRenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser, float Alpha = 1.0f); void ForceRenderQuads(CQuad *pQuads, int NumQuads, int Flags, ENVELOPE_EVAL pfnEval, void *pUser, float Alpha = 1.0f);
void RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags, ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset); void RenderTilemap(CTile *pTiles, int w, int h, float Scale, ColorRGBA Color, int RenderFlags, ENVELOPE_EVAL pfnEval, void *pUser, int ColorEnv, int ColorEnvOffset);

View file

@ -11,7 +11,7 @@
#include <game/generated/client_data.h> #include <game/generated/client_data.h>
#include <game/generated/protocol.h> #include <game/generated/protocol.h>
void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, float Time, float *pResult) void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Channels, int64 TimeMicros, float *pResult)
{ {
if(NumPoints == 0) if(NumPoints == 0)
{ {
@ -31,13 +31,16 @@ void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Cha
return; return;
} }
Time = fmod(Time, pPoints[NumPoints - 1].m_Time / 1000.0f) * 1000.0f; int64 MaxPointTime = (int64)pPoints[NumPoints - 1].m_Time * 1000ll;
TimeMicros = TimeMicros % MaxPointTime;
int TimeMillis = (int)(TimeMicros / 1000ll);
for(int i = 0; i < NumPoints - 1; i++) for(int i = 0; i < NumPoints - 1; i++)
{ {
if(Time >= pPoints[i].m_Time && Time <= pPoints[i + 1].m_Time) if(TimeMillis >= pPoints[i].m_Time && TimeMillis <= pPoints[i + 1].m_Time)
{ {
float Delta = pPoints[i + 1].m_Time - pPoints[i].m_Time; float Delta = pPoints[i + 1].m_Time - pPoints[i].m_Time;
float a = (Time - pPoints[i].m_Time) / Delta; float a = (float)(((double)TimeMicros / 1000.0) - pPoints[i].m_Time) / Delta;
if(pPoints[i].m_Curvetype == CURVETYPE_SMOOTH) if(pPoints[i].m_Curvetype == CURVETYPE_SMOOTH)
a = -2 * a * a * a + 3 * a * a; // second hermite basis a = -2 * a * a * a + 3 * a * a; // second hermite basis
@ -102,7 +105,7 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags
if(q->m_ColorEnv >= 0) if(q->m_ColorEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
pfnEval(q->m_ColorEnvOffset / 1000.0f, q->m_ColorEnv, aChannels, pUser); pfnEval(q->m_ColorEnvOffset, q->m_ColorEnv, aChannels, pUser);
r = aChannels[0]; r = aChannels[0];
g = aChannels[1]; g = aChannels[1];
b = aChannels[2]; b = aChannels[2];
@ -133,7 +136,7 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags
if(q->m_PosEnv >= 0) if(q->m_PosEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
pfnEval(q->m_PosEnvOffset / 1000.0f, q->m_PosEnv, aChannels, pUser); pfnEval(q->m_PosEnvOffset, q->m_PosEnv, aChannels, pUser);
OffsetX = aChannels[0]; OffsetX = aChannels[0];
OffsetY = aChannels[1]; OffsetY = aChannels[1];
Rot = aChannels[2] / 360.0f * pi * 2; Rot = aChannels[2] / 360.0f * pi * 2;
@ -190,7 +193,7 @@ void CRenderTools::RenderTileRectangle(int RectX, int RectY, int RectW, int Rect
if(ColorEnv >= 0) if(ColorEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
pfnEval(ColorEnvOffset / 1000.0f, ColorEnv, aChannels, pUser); pfnEval(ColorEnvOffset, ColorEnv, aChannels, pUser);
r = aChannels[0]; r = aChannels[0];
g = aChannels[1]; g = aChannels[1];
b = aChannels[2]; b = aChannels[2];
@ -266,7 +269,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, Color
if(ColorEnv >= 0) if(ColorEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
pfnEval(ColorEnvOffset / 1000.0f, ColorEnv, aChannels, pUser); pfnEval(ColorEnvOffset, ColorEnv, aChannels, pUser);
r = aChannels[0]; r = aChannels[0];
g = aChannels[1]; g = aChannels[1];
b = aChannels[2]; b = aChannels[2];

View file

@ -280,7 +280,7 @@ void CEditorImage::AnalyseTileFlags()
} }
} }
void CEditor::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser) void CEditor::EnvelopeEval(int TimeOffsetMillis, int Env, float *pChannels, void *pUser)
{ {
CEditor *pThis = (CEditor *)pUser; CEditor *pThis = (CEditor *)pUser;
if(Env < 0 || Env >= pThis->m_Map.m_lEnvelopes.size()) if(Env < 0 || Env >= pThis->m_Map.m_lEnvelopes.size())
@ -293,7 +293,7 @@ void CEditor::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pU
} }
CEnvelope *e = pThis->m_Map.m_lEnvelopes[Env]; CEnvelope *e = pThis->m_Map.m_lEnvelopes[Env];
float t = pThis->m_AnimateTime + TimeOffset; float t = pThis->m_AnimateTime + (TimeOffsetMillis / 1000.0f);
t *= pThis->m_AnimateSpeed; t *= pThis->m_AnimateSpeed;
e->Eval(t, pChannels); e->Eval(t, pChannels);
} }

View file

@ -89,7 +89,7 @@ public:
int Eval(float Time, float *pResult) int Eval(float Time, float *pResult)
{ {
CRenderTools::RenderEvalEnvelope(m_lPoints.base_ptr(), m_lPoints.size(), m_Channels, Time, pResult); CRenderTools::RenderEvalEnvelope(m_lPoints.base_ptr(), m_lPoints.size(), m_Channels, (int64)((double)Time * 1000000.0), pResult);
return m_Channels; return m_Channels;
} }
@ -944,7 +944,7 @@ public:
CEditorMap m_Map; CEditorMap m_Map;
int m_ShiftBy; int m_ShiftBy;
static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); static void EnvelopeEval(int TimeOffsetMillis, int Env, float *pChannels, void *pUser);
float m_CommandBox; float m_CommandBox;
char m_aSettingsCommand[256]; char m_aSettingsCommand[256];

View file

@ -35,7 +35,7 @@ void CLayerSounds::Render(bool Tileset)
if(pSource->m_PosEnv >= 0) if(pSource->m_PosEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
m_pEditor->EnvelopeEval(pSource->m_PosEnvOffset / 1000.0f, pSource->m_PosEnv, aChannels, m_pEditor); m_pEditor->EnvelopeEval(pSource->m_PosEnvOffset, pSource->m_PosEnv, aChannels, m_pEditor);
OffsetX = aChannels[0]; OffsetX = aChannels[0];
OffsetY = aChannels[1]; OffsetY = aChannels[1];
} }
@ -87,7 +87,7 @@ void CLayerSounds::Render(bool Tileset)
if(pSource->m_PosEnv >= 0) if(pSource->m_PosEnv >= 0)
{ {
float aChannels[4]; float aChannels[4];
m_pEditor->EnvelopeEval(pSource->m_PosEnvOffset / 1000.0f, pSource->m_PosEnv, aChannels, m_pEditor); m_pEditor->EnvelopeEval(pSource->m_PosEnvOffset, pSource->m_PosEnv, aChannels, m_pEditor);
OffsetX = aChannels[0]; OffsetX = aChannels[0];
OffsetY = aChannels[1]; OffsetY = aChannels[1];
} }