#ifndef PHYSICS_HPP_ #define PHYSICS_HPP_ #include "config.hpp" #include #include #include #include #include #include #include #include #include class cpu_layout_engine { struct add_mass {}; struct add_spring { size_t a; size_t b; }; struct clear_graph {}; using command = std::variant; struct physics_state { #ifdef TRACY TracyLockable(std::mutex, command_mtx); #else std::mutex command_mtx; #endif std::queue pending_commands; #ifdef TRACY TracyLockable(std::mutex, data_mtx); #else std::mutex data_mtx; #endif std::condition_variable_any data_ready_cnd; std::condition_variable_any data_consumed_cnd; Vector3 mass_center = Vector3Zero(); int ups = 0; size_t mass_count = 0; // For debug size_t spring_count = 0; // For debug std::vector masses; // Read by renderer bool data_ready = false; bool data_consumed = true; std::atomic running{true}; }; private: std::optional* const> thread_pool; std::thread physics; public: physics_state state; public: explicit cpu_layout_engine( const std::optional* const> _thread_pool = std::nullopt) : thread_pool(_thread_pool), physics(physics_thread, std::ref(state), std::ref(thread_pool)) {} cpu_layout_engine(const cpu_layout_engine& copy) = delete; auto operator=(const cpu_layout_engine& copy) -> cpu_layout_engine& = delete; cpu_layout_engine(cpu_layout_engine&& move) = delete; auto operator=(cpu_layout_engine&& move) -> cpu_layout_engine& = delete; ~cpu_layout_engine() { state.running = false; state.data_ready_cnd.notify_all(); state.data_consumed_cnd.notify_all(); physics.join(); } private: #ifdef ASYNC_OCTREE static auto set_octree_pool_thread_name(size_t idx) -> void; #endif static auto physics_thread(physics_state& state, std::optional* const> thread_pool) -> void; public: auto clear_cmd() -> void; auto add_mass_cmd() -> void; auto add_spring_cmd(size_t a, size_t b) -> void; auto add_mass_springs_cmd(size_t num_masses, const std::vector>& springs) -> void; }; #endif