- Mesaj
- 159
- Çözümler
- 1
- Beğeni
- 265
- Puan
- 794
- Ticaret Puanı
- 0
Effect Frame Update Optimization
The frame controller update function, used in mesh and texture effect animations, originally relied on a fixed loop, up to 20 iterations, to simulate the passage of frames based on the accumulated elapsed time.This approach had several downsides:
- Inefficient CPU usage due to repeated branching.
- Limited scalability — it could miss frames if the elapsed time was too large.
- More complex and harder-to-maintain code.
- The new logic replaces the loop with a direct calculation.
- It calculates how many frames should have passed based on the total accumulated elapsed time.
- All required frame advancements are processed at once, in a single operation.
- Looping behavior and animation end conditions are still handled correctly.
- Lower CPU usage — avoids unnecessary loops and repeated branching.
- Better scalability — handles large time jumps more smoothly, especially during low-FPS situations.
- Cleaner and more maintainable code.
- More responsive mesh and texture effect animations.
It does not guarantee a stable 60 FPS, but it ensures that frame updates are processed more efficiently, accurately, and responsively.
Mesh ve texture efekt animasyonlarında kullanılan frame controller update fonksiyonu, başlangıçta biriken geçen süreye göre frame geçişlerini simüle etmek için sabit bir döngüye, maksimum 20 iterasyona kadar, dayanıyordu.
Bu yaklaşımın birkaç olumsuz tarafı vardı:
- Tekrarlanan koşul kontrolleri nedeniyle verimsiz CPU kullanımı.
- Sınırlı ölçeklenebilirlik — geçen süre çok büyük olduğunda bazı frameler atlanabiliyordu.
- Daha karmaşık ve bakımı daha zor bir kod yapısı.
- Yeni mantık, döngü yapısını doğrudan hesaplama ile değiştirir.
- Toplam biriken geçen süreye göre kaç frame ilerlemesi gerektiğini hesaplar.
- Gerekli tüm frame ilerlemeleri tek seferde, tek bir işlem ile uygulanır.
- Döngü davranışı ve animasyon bitiş koşulları doğru şekilde korunmaya devam eder.
- Daha düşük CPU kullanımı — gereksiz döngülerden ve tekrarlanan koşul kontrollerinden kaçınır.
- Daha iyi ölçeklenebilirlik — özellikle düşük FPS durumlarında büyük zaman sıçramalarını daha düzgün şekilde işler.
- Daha temiz ve bakımı daha kolay kod.
- Mesh ve texture efekt animasyonlarında daha hızlı ve daha duyarlı frame güncellemeleri.
Sabit 60 FPS garantisi vermez, ancak frame güncellemelerinin daha verimli, daha doğru ve daha duyarlı şekilde işlenmesini sağlar.
FrameController.cpp:
#include "StdAfx.h"
#include "FrameController.h"
void CFrameController::Update(float fElapsedTime)
{
#ifdef ENABLE_EFFECT_UPDATE_OPTIMIZATION
if (!m_isActive)
return;
if (fElapsedTime <= 0.0f)
return;
if (m_fFrameTime <= 0.0f || m_dwMaxFrame == 0)
{
m_iLoopCount = 1;
m_dwcurFrame = 0;
m_fLastFrameTime = 0.0f;
m_isActive = FALSE;
return;
}
m_fLastFrameTime -= fElapsedTime;
if (m_fLastFrameTime >= 0.0f)
return;
double dAdvanceFrame = double(-m_fLastFrameTime) / double(m_fFrameTime);
DWORD dwAdvanceFrame;
if (!(dAdvanceFrame >= 0.0))
{
m_fLastFrameTime = m_fFrameTime;
return;
}
if (dAdvanceFrame >= 4294967295.0)
{
dwAdvanceFrame = 0xffffffff;
m_fLastFrameTime = 0.0f;
}
else
{
dwAdvanceFrame = DWORD(dAdvanceFrame);
double dLastFrameTime = double(m_fLastFrameTime) + double(m_fFrameTime) * double(dwAdvanceFrame);
if (dLastFrameTime < 0.0)
{
dLastFrameTime += double(m_fFrameTime);
++dwAdvanceFrame;
}
m_fLastFrameTime = float(dLastFrameTime);
}
if (dwAdvanceFrame == 0)
return;
if (m_dwcurFrame >= m_dwMaxFrame)
m_dwcurFrame = 0;
if (!m_isLoop)
{
if (dwAdvanceFrame >= m_dwMaxFrame - m_dwcurFrame)
{
m_iLoopCount = 1;
m_dwcurFrame = 0;
m_isActive = FALSE;
return;
}
m_dwcurFrame += dwAdvanceFrame;
return;
}
DWORD dwLoopCount = dwAdvanceFrame / m_dwMaxFrame;
DWORD dwFrame = dwAdvanceFrame % m_dwMaxFrame;
if (dwFrame >= m_dwMaxFrame - m_dwcurFrame)
{
++dwLoopCount;
m_dwcurFrame = dwFrame - (m_dwMaxFrame - m_dwcurFrame);
}
else
{
m_dwcurFrame += dwFrame;
}
if (m_iLoopCount > 0)
{
if (dwLoopCount >= DWORD(m_iLoopCount))
{
m_iLoopCount = 1;
m_dwcurFrame = 0;
m_isActive = FALSE;
return;
}
m_iLoopCount -= dwLoopCount;
}
else
{
m_iLoopCount = 0;
}
#else
m_fLastFrameTime -= fElapsedTime;
for (int i = 0; i < 20; ++i)
{
if (m_fLastFrameTime < 0.0f)
{
m_fLastFrameTime += m_fFrameTime;
++m_dwcurFrame;
if (m_dwcurFrame >= m_dwMaxFrame)
{
if (m_isLoop && --m_iLoopCount!=0)
{
if (m_iLoopCount<0)
m_iLoopCount = 0;
m_dwcurFrame = 0;
}
else
{
m_iLoopCount = 1;
m_dwcurFrame = 0;
m_isActive = FALSE;
return;
}
}
}
else
{
break;
}
}
#endif
}
void CFrameController::SetCurrentFrame(DWORD dwFrame)
{
m_dwcurFrame = dwFrame;
}
BYTE CFrameController::GetCurrentFrame()
{
return m_dwcurFrame;
}
void CFrameController::SetMaxFrame(DWORD dwMaxFrame)
{
m_dwMaxFrame = dwMaxFrame;
}
void CFrameController::SetFrameTime(float fTime)
{
m_fFrameTime = fTime;
m_fLastFrameTime = fTime;
}
void CFrameController::SetStartFrame(DWORD dwStartFrame)
{
m_dwStartFrame = dwStartFrame;
}
void CFrameController::SetLoopFlag(BOOL bFlag)
{
m_isLoop = bFlag;
}
void CFrameController::SetLoopCount(int iLoopCount)
{
m_iLoopCount = iLoopCount;
}
void CFrameController::SetActive(BOOL bFlag)
{
m_isActive = bFlag;
}
BOOL CFrameController::isActive(DWORD dwMainFrame)
{
if (dwMainFrame < m_dwStartFrame)
return FALSE;
return m_isActive;
}
void CFrameController::Clear()
{
m_isActive = TRUE;
m_dwcurFrame = 0;
m_fLastFrameTime = 0.0f;
m_iLoopCount = 0;
}
CFrameController::CFrameController()
{
m_isActive = TRUE;
m_dwcurFrame = 0;
m_fLastFrameTime = 0.0f;
m_iLoopCount = 0;
m_isLoop = FALSE;
m_dwMaxFrame = 0;
m_fFrameTime = 0.0f;
m_dwStartFrame = 0;
}
CFrameController::~CFrameController()
{
}
//martysama0134's dcf42890919f0da1c0e6dbb7f15bc7ec
alıntıdır.