3002: Make animations more consistent with high float values r=def- a=Jupeyy

fixes what is described in #2997

Old client animation when server time is huge:

[vid_old.zip](https://github.com/ddnet/ddnet/files/5322484/vid_old.zip)

 client animation when server time is huge:

[vid_new.zip](https://github.com/ddnet/ddnet/files/5322486/vid_new.zip)

@Fireball-Teeworlds maybe u can try, if that fixes the stuff for u

Co-authored-by: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
bors[bot] 2020-10-05 14:48:09 +00:00 committed by GitHub
commit 1b253bfbfd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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]);
}
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;
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);
static float s_Time = 0.0f;
static float s_LastLocalTime = pThis->LocalTime();
const int64 TickToMicroSeconds = (1000000ll / (int64)pThis->Client()->GameTickSpeed());
static int64 s_Time = 0;
static int64 s_LastLocalTime = time_get_microseconds();
if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK)
{
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)
{
s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
(pThis->Client()->GameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy));
// get the lerp of the current tick and prev
int MinTick = pThis->Client()->PrevGameTick(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
{
s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy));
int MinTick = pThis->m_LastLocalTick;
s_Time = (int64)(mix<double>(0,
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
{
@ -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))
{
s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
(pThis->Client()->GameTick(g_Config.m_ClDummy) - pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
pThis->Client()->IntraGameTick(g_Config.m_ClDummy));
// get the lerp of the current tick and prev
int MinTick = pThis->Client()->PrevGameTick(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
{
s_Time += pThis->LocalTime() - s_LastLocalTime;
s_LastLocalTime = pThis->LocalTime();
int64 CurTime = time_get_microseconds();
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)
{
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];
g = aChannels[1];
b = aChannels[2];
@ -1379,7 +1395,7 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
aColor[0] = aColor[1] = aColor[2] = aColor[3] = 1.f;
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;
@ -1389,7 +1405,7 @@ void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads *pQuadLayer,
if(q->m_PosEnv >= 0)
{
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];
OffsetY = aChannels[1];
Rot = aChannels[2] / 180.0f * pi;

View file

@ -151,7 +151,7 @@ public:
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

View file

@ -199,7 +199,7 @@ void CMapSounds::OnRender()
if(pVoice->m_pSource->m_PosEnv >= 0)
{
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];
OffsetY = aChannels[1];
}
@ -218,7 +218,7 @@ void CMapSounds::OnRender()
if(pVoice->m_pSource->m_SoundEnv >= 0)
{
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);
Sound()->SetVoiceVolume(pVoice->m_Voice, Volume);

View file

@ -39,7 +39,7 @@ enum
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
{
@ -83,7 +83,7 @@ public:
void RenderTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote, vec2 Dir, vec2 Pos, float Alpha = 1.0f);
// 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 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);

View file

@ -11,7 +11,7 @@
#include <game/generated/client_data.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)
{
@ -31,13 +31,16 @@ void CRenderTools::RenderEvalEnvelope(CEnvPoint *pPoints, int NumPoints, int Cha
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++)
{
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 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)
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)
{
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];
g = aChannels[1];
b = aChannels[2];
@ -133,7 +136,7 @@ void CRenderTools::ForceRenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags
if(q->m_PosEnv >= 0)
{
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];
OffsetY = aChannels[1];
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)
{
float aChannels[4];
pfnEval(ColorEnvOffset / 1000.0f, ColorEnv, aChannels, pUser);
pfnEval(ColorEnvOffset, ColorEnv, aChannels, pUser);
r = aChannels[0];
g = aChannels[1];
b = aChannels[2];
@ -266,7 +269,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, Color
if(ColorEnv >= 0)
{
float aChannels[4];
pfnEval(ColorEnvOffset / 1000.0f, ColorEnv, aChannels, pUser);
pfnEval(ColorEnvOffset, ColorEnv, aChannels, pUser);
r = aChannels[0];
g = aChannels[1];
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;
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];
float t = pThis->m_AnimateTime + TimeOffset;
float t = pThis->m_AnimateTime + (TimeOffsetMillis / 1000.0f);
t *= pThis->m_AnimateSpeed;
e->Eval(t, pChannels);
}

View file

@ -89,7 +89,7 @@ public:
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;
}
@ -944,7 +944,7 @@ public:
CEditorMap m_Map;
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;
char m_aSettingsCommand[256];

View file

@ -35,7 +35,7 @@ void CLayerSounds::Render(bool Tileset)
if(pSource->m_PosEnv >= 0)
{
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];
OffsetY = aChannels[1];
}
@ -87,7 +87,7 @@ void CLayerSounds::Render(bool Tileset)
if(pSource->m_PosEnv >= 0)
{
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];
OffsetY = aChannels[1];
}