From d3f93fc3c6d1dd1d0dbfb7b7040e7f8f7f7b9bea Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Tue, 24 Feb 2026 18:15:14 +0100 Subject: [PATCH] wip: draw physics thread ups --- include/config.hpp | 5 ++--- include/physics.hpp | 1 + include/renderer.hpp | 2 +- src/main.cpp | 5 ++++- src/physics.cpp | 16 ++++++++++++++-- src/renderer.cpp | 5 ++++- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/include/config.hpp b/include/config.hpp index 69017ef..8820065 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -29,15 +29,14 @@ constexpr float ROT_SPEED = 1.0; constexpr float CAMERA_SMOOTH_SPEED = 15.0; // Physics Engine -constexpr float SIM_SPEED = 1.0; // How large each update should be -constexpr float TIMESTEP = 1.0 / 90; // Do 90 physics updates per second +constexpr float TIMESTEP = 0.01; // How large each update should be constexpr float MASS = 1.0; // Mass spring system constexpr float SPRING_CONSTANT = 5.0; // Mass spring system constexpr float DAMPENING_CONSTANT = 1.0; // Mass spring system constexpr float REST_LENGTH = 2.0; // Mass spring system constexpr float VERLET_DAMPENING = 0.05; // [0, 1] constexpr float BH_FORCE = 2.0; // BH: [1.0, 3.0] -constexpr float THETA = 1.0; // Barnes-Hut [0.5, 1.0] +constexpr float THETA = 0.9; // Barnes-Hut [0.5, 1.0] constexpr float SOFTENING = 0.01; // Barnes-Hut [0.01, 1.0] constexpr float GRID_FORCE = 0.02; // Grid: [0.0, ~0.05] constexpr float REPULSION_RANGE = 5.0 * REST_LENGTH; // Grid diff --git a/include/physics.hpp b/include/physics.hpp index 5bd4bcf..29f4e78 100644 --- a/include/physics.hpp +++ b/include/physics.hpp @@ -122,6 +122,7 @@ class ThreadedPhysics { TracyLockable(std::mutex, data_mtx); std::condition_variable_any data_ready_cnd; std::condition_variable_any data_consumed_cnd; + float ups; bool data_ready = false; bool data_consumed = true; std::vector masses; // Read by renderer diff --git a/include/renderer.hpp b/include/renderer.hpp index 85b44b2..64a67dc 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -77,7 +77,7 @@ public: const std::vector> &springs) -> void; - auto DrawTextures() -> void; + auto DrawTextures(float ups) -> void; }; #endif diff --git a/src/main.cpp b/src/main.cpp index c234f39..8c2426d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,6 +44,7 @@ auto main(int argc, char *argv[]) -> int { OrbitCamera3D camera; Renderer renderer(camera, state, input); + float ups; std::vector masses; // Read from physics std::vector> springs; // Read from physics @@ -61,6 +62,8 @@ auto main(int argc, char *argv[]) -> int { { std::unique_lock lock(physics.state.data_mtx); + ups = physics.state.ups; + // Only copy data if any has been produced if (physics.state.data_ready) { masses = physics.state.masses; @@ -88,7 +91,7 @@ auto main(int argc, char *argv[]) -> int { renderer.DrawMassSprings(masses, springs); renderer.DrawKlotski(); renderer.DrawMenu(masses, springs); - renderer.DrawTextures(); + renderer.DrawTextures(ups); FrameMarkEnd("MainThread"); } diff --git a/src/physics.cpp b/src/physics.cpp index 6c18d32..d71ade8 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -190,8 +192,17 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) [&](const struct ClearGraph &cg) { mass_springs.Clear(); }, }; + std::chrono::time_point last = std::chrono::high_resolution_clock::now(); + std::chrono::duration deltatime(0); + while (state.running.load()) { FrameMarkStart("PhysicsThread"); + + // Time tracking + std::chrono::time_point now = std::chrono::high_resolution_clock::now(); + deltatime = now - last; + last = now; + // Handle queued commands { std::lock_guard lock(state.command_mtx); @@ -208,11 +219,10 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) } // Physics update - // TODO: Respect thread-local deltatime + calculate UPS mass_springs.ClearForces(); mass_springs.CalculateSpringForces(); mass_springs.CalculateRepulsionForces(); - mass_springs.VerletUpdate(TIMESTEP * SIM_SPEED); + mass_springs.VerletUpdate(TIMESTEP); // Publish the positions for the renderer (copy) FrameMarkStart("PhysicsThreadProduceLock"); @@ -225,6 +235,8 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) break; } + state.ups = 1.0 / deltatime.count(); + state.masses.clear(); state.masses.reserve(mass_springs.masses.size()); for (const auto &mass : mass_springs.masses) { diff --git a/src/renderer.cpp b/src/renderer.cpp index 8bb9c42..b66b1d0 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -316,7 +316,7 @@ auto Renderer::DrawMenu( EndTextureMode(); } -auto Renderer::DrawTextures() -> void { +auto Renderer::DrawTextures(float ups) -> void { BeginDrawing(); DrawTextureRec(menu_target.texture, Rectangle(0, 0, menu_target.texture.width, @@ -330,6 +330,9 @@ auto Renderer::DrawTextures() -> void { Rectangle(0, 0, render_target.texture.width, -1 * render_target.texture.height), Vector2(GetScreenWidth() / 2.0, MENU_HEIGHT), WHITE); + DrawFPS(GetScreenWidth() / 2 + 10, MENU_HEIGHT + 10); + DrawText(TextFormat("%.0f UPS", ups), GetScreenWidth() / 2 + 120, + MENU_HEIGHT + 10, 20, ORANGE); EndDrawing(); }