replace physics loop with fixed-step loop
This commit is contained in:
@ -4,7 +4,6 @@
|
|||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
|
|
||||||
#define PRINT_TIMINGS
|
#define PRINT_TIMINGS
|
||||||
#define VERLET_UPDATE
|
|
||||||
// #define WEB
|
// #define WEB
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
@ -19,7 +18,6 @@ constexpr int MENU_ROWS = 3;
|
|||||||
constexpr int MENU_COLS = 3;
|
constexpr int MENU_COLS = 3;
|
||||||
|
|
||||||
// Camera Controls
|
// Camera Controls
|
||||||
constexpr float SIM_SPEED = 4.0;
|
|
||||||
constexpr float CAMERA_FOV = 120.0;
|
constexpr float CAMERA_FOV = 120.0;
|
||||||
constexpr float CAMERA_DISTANCE = 20.0;
|
constexpr float CAMERA_DISTANCE = 20.0;
|
||||||
constexpr float MIN_CAMERA_DISTANCE = 2.0;
|
constexpr float MIN_CAMERA_DISTANCE = 2.0;
|
||||||
@ -31,7 +29,8 @@ constexpr float PAN_MULTIPLIER = 10.0;
|
|||||||
constexpr float ROT_SPEED = 1.0;
|
constexpr float ROT_SPEED = 1.0;
|
||||||
|
|
||||||
// Physics Engine
|
// Physics Engine
|
||||||
constexpr int UPDATES_PER_FRAME = 1;
|
constexpr float SIM_SPEED = 4.0;
|
||||||
|
constexpr float TIMESTEP = 1.0 / 60; // Do 60 physics updates per second
|
||||||
constexpr float MASS = 1.0;
|
constexpr float MASS = 1.0;
|
||||||
constexpr float SPRING_CONSTANT = 5.0;
|
constexpr float SPRING_CONSTANT = 5.0;
|
||||||
constexpr float DAMPENING_CONSTANT = 1.0;
|
constexpr float DAMPENING_CONSTANT = 1.0;
|
||||||
|
|||||||
@ -129,8 +129,6 @@ public:
|
|||||||
|
|
||||||
auto CalculateRepulsionForces() -> void;
|
auto CalculateRepulsionForces() -> void;
|
||||||
|
|
||||||
auto EulerUpdate(float delta_time) -> void;
|
|
||||||
|
|
||||||
auto VerletUpdate(float delta_time) -> void;
|
auto VerletUpdate(float delta_time) -> void;
|
||||||
|
|
||||||
auto InvalidateGrid() -> void;
|
auto InvalidateGrid() -> void;
|
||||||
|
|||||||
39
src/main.cpp
39
src/main.cpp
@ -63,9 +63,13 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
std::chrono::duration<double, std::milli>(0);
|
std::chrono::duration<double, std::milli>(0);
|
||||||
std::chrono::duration<double, std::milli> render_time_accumulator =
|
std::chrono::duration<double, std::milli> render_time_accumulator =
|
||||||
std::chrono::duration<double, std::milli>(0);
|
std::chrono::duration<double, std::milli>(0);
|
||||||
int time_measure_count = 0;
|
int loop_count = 0;
|
||||||
#endif
|
#endif
|
||||||
|
float timestep_accumulator = 0.0;
|
||||||
|
int update_accumulator = 0;
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
|
timestep_accumulator += GetFrameTime();
|
||||||
|
|
||||||
// Input update
|
// Input update
|
||||||
state.previous_state = state.current_state;
|
state.previous_state = state.current_state;
|
||||||
input.HandleInput();
|
input.HandleInput();
|
||||||
@ -76,16 +80,17 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
std::chrono::high_resolution_clock::time_point ps =
|
std::chrono::high_resolution_clock::time_point ps =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
#endif
|
#endif
|
||||||
for (int i = 0; i < UPDATES_PER_FRAME; ++i) {
|
|
||||||
|
while (timestep_accumulator > TIMESTEP) {
|
||||||
mass_springs.ClearForces();
|
mass_springs.ClearForces();
|
||||||
mass_springs.CalculateSpringForces();
|
mass_springs.CalculateSpringForces();
|
||||||
mass_springs.CalculateRepulsionForces();
|
mass_springs.CalculateRepulsionForces();
|
||||||
#ifdef VERLET_UPDATE
|
mass_springs.VerletUpdate(TIMESTEP * SIM_SPEED);
|
||||||
mass_springs.VerletUpdate(GetFrameTime() / UPDATES_PER_FRAME * SIM_SPEED);
|
|
||||||
#else
|
timestep_accumulator -= TIMESTEP;
|
||||||
mass_springs.EulerUpdate(GetFrameTime() * SIM_SPEED);
|
update_accumulator++;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PRINT_TIMINGS
|
#ifdef PRINT_TIMINGS
|
||||||
std::chrono::high_resolution_clock::time_point pe =
|
std::chrono::high_resolution_clock::time_point pe =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
@ -97,6 +102,7 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
std::chrono::high_resolution_clock::time_point rs =
|
std::chrono::high_resolution_clock::time_point rs =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
renderer.UpdateCamera(mass_springs, state.current_state);
|
renderer.UpdateCamera(mass_springs, state.current_state);
|
||||||
renderer.UpdateTextureSizes();
|
renderer.UpdateTextureSizes();
|
||||||
renderer.DrawMassSprings(mass_springs, state.current_state,
|
renderer.DrawMassSprings(mass_springs, state.current_state,
|
||||||
@ -107,23 +113,26 @@ auto main(int argc, char *argv[]) -> int {
|
|||||||
renderer.DrawMenu(mass_springs, state.current_preset, state.current_state,
|
renderer.DrawMenu(mass_springs, state.current_preset, state.current_state,
|
||||||
state.winning_states);
|
state.winning_states);
|
||||||
renderer.DrawTextures();
|
renderer.DrawTextures();
|
||||||
|
|
||||||
#ifdef PRINT_TIMINGS
|
#ifdef PRINT_TIMINGS
|
||||||
std::chrono::high_resolution_clock::time_point re =
|
std::chrono::high_resolution_clock::time_point re =
|
||||||
std::chrono::high_resolution_clock::now();
|
std::chrono::high_resolution_clock::now();
|
||||||
render_time_accumulator += re - rs;
|
render_time_accumulator += re - rs;
|
||||||
|
|
||||||
time_measure_count++;
|
loop_count++;
|
||||||
if (GetTime() - last_print_time > 10.0) {
|
if (GetTime() - last_print_time > 10.0) {
|
||||||
std::cout << " - Physics time avg: "
|
std::cout << " - Physics time avg: "
|
||||||
<< physics_time_accumulator / time_measure_count << "."
|
<< physics_time_accumulator / loop_count << "." << std::endl;
|
||||||
<< std::endl;
|
std::cout << " - Render time avg: "
|
||||||
std::cout << " - Render time avg: "
|
<< render_time_accumulator / loop_count << "." << std::endl;
|
||||||
<< render_time_accumulator / time_measure_count << "."
|
std::cout << " - Physics updates avg: "
|
||||||
<< std::endl;
|
<< static_cast<float>(update_accumulator) / loop_count
|
||||||
|
<< "x per frame." << std::endl;
|
||||||
last_print_time = GetTime();
|
last_print_time = GetTime();
|
||||||
physics_time_accumulator = std::chrono::duration<double, std::milli>(0);
|
physics_time_accumulator = std::chrono::duration<double, std::milli>(0);
|
||||||
render_time_accumulator = std::chrono::duration<double, std::milli>(0);
|
render_time_accumulator = std::chrono::duration<double, std::milli>(0);
|
||||||
time_measure_count = 0;
|
loop_count = 0;
|
||||||
|
update_accumulator = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -226,13 +226,6 @@ auto MassSpringSystem::CalculateRepulsionForces() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto MassSpringSystem::EulerUpdate(float delta_time) -> void {
|
|
||||||
for (auto &[state, mass] : masses) {
|
|
||||||
mass.CalculateVelocity(delta_time);
|
|
||||||
mass.CalculatePosition(delta_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto MassSpringSystem::VerletUpdate(float delta_time) -> void {
|
auto MassSpringSystem::VerletUpdate(float delta_time) -> void {
|
||||||
for (auto &[state, mass] : masses) {
|
for (auto &[state, mass] : masses) {
|
||||||
mass.VerletUpdate(delta_time);
|
mass.VerletUpdate(delta_time);
|
||||||
|
|||||||
Reference in New Issue
Block a user