Pan between ticks, and move animations at their own rate
CI / build (push) Successful in 27s

The point the camera looks at is its position plus an offset (setCameraFocus,
at each tick), so between ticks it now moves with the eased position: panning
moves the target the position eases to, and was still at 30 per second.

Between ticks, an animation is moved on at the rate it moved at the last step
(per tick: the client steps several ticks at once when it falls behind), not
only when it moved exactly a frame: animations played at other speeds were
posed at the tick, between smooth ones.

The engine's stats also log the longest time between frames.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 21:56:09 -07:00
1 parent d1437a3923
commit 4670a6a191
3 files changed
+49 -20

No files matched your search

+16 -5
View File
@@ -2,6 +2,7 @@
#include <windows.h>
#include <algorithm>
#include <bit>
#include <cmath>
#include <cstring>
@@ -263,6 +264,15 @@ void Engine::beginRendering(imvu::PiRenderTarget* target)
{
QueryPerformanceCounter(&frameStart_);
windowFrame_ = target == nullptr;
if (windowFrame_) {
if (lastWindowFrame_ != 0) {
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
longestGap_ = std::max(longestGap_, static_cast<double>(frameStart_.QuadPart - lastWindowFrame_) /
static_cast<double>(frequency.QuadPart));
}
lastWindowFrame_ = frameStart_.QuadPart;
}
// Frames into our render targets are drawn by the renderer process only; the client's renderer doesn't know them.
ourTarget_ = ours(target) ? target : nullptr;
// Decided per frame: frames into the client renderer's render targets, and frames while the renderer process
@@ -324,11 +334,11 @@ void Engine::endRendering()
const Recorder::Counters sent = recorder_->takeCounters();
if (statsLogged_ < 6 || frames_ % 3000 == 0) {
++statsLogged_;
log::info("engine: last 300 frames: {:.0f} per second; each {:.2f} ms beginRendering to endRendering, {:.2f} ms "
"in the client renderer's methods, {:.2f} ms sending, {:.0f} KB sent, {:.1f} buffer updates ({:.0f} "
"KB); drawTriangles {} (and {} with buffers not ours), drawTrianglesFromMemory {} (and {} without "
"indices), point sprites {}, lines {}, 2D projections {}",
300 / seconds, frameSeconds_ * 1000 / 300,
log::info("engine: last 300 frames: {:.0f} per second, at most {:.1f} ms apart; each {:.2f} ms beginRendering to "
"endRendering, {:.2f} ms in the client renderer's methods, {:.2f} ms sending, {:.0f} KB sent, {:.1f} "
"buffer updates ({:.0f} KB); drawTriangles {} (and {} with buffers not ours), drawTrianglesFromMemory "
"{} (and {} without indices), point sprites {}, lines {}, 2D projections {}",
300 / seconds, longestGap_ * 1000, frameSeconds_ * 1000 / 300,
static_cast<double>(innerTicks - innerTicksAtStats_) * 1000 / static_cast<double>(frequency.QuadPart) / 300,
sent.sendSeconds * 1000 / 300,
static_cast<double>(sent.bytes) / 1024 / 300, sent.bufferUpdates / 300.0,
@@ -337,6 +347,7 @@ void Engine::endRendering()
}
stats_ = {};
frameSeconds_ = 0;
longestGap_ = 0;
innerTicksAtStats_ = innerTicks;
}
}