diff --git a/libs/phys/source/engine_2d.cpp b/libs/phys/source/engine_2d.cpp index f0daf0fe..b15af8d9 100644 --- a/libs/phys/source/engine_2d.cpp +++ b/libs/phys/source/engine_2d.cpp @@ -8,8 +8,6 @@ #include #include -#include - #include #include @@ -415,13 +413,18 @@ namespace psemek::phys2d std::optional> gravity; + std::set contacts_by_velocity; + std::set contacts_by_penetration; + void explode(geom::point const & center, float strength, float attenuation); void update(float dt); void apply_gravity(float dt); void integrate(float dt); - void resolve_collisions(); + void gather_collisions(); + void resolve_impulses(); + void resolve_penetrations(); void log_energy(); float energy(); @@ -446,7 +449,9 @@ namespace psemek::phys2d { apply_gravity(dt); integrate(dt); - resolve_collisions(); + gather_collisions(); + resolve_impulses(); + resolve_penetrations(); // log_energy(); } @@ -478,7 +483,7 @@ namespace psemek::phys2d } } - void engine::impl::resolve_collisions() + void engine::impl::gather_collisions() { for (std::size_t gi = 0; gi < groups.size(); ++gi) { @@ -491,7 +496,8 @@ namespace psemek::phys2d } } - std::set contacts_by_velocity; + contacts_by_velocity.clear(); + contacts_by_penetration.clear(); for (std::size_t gi = 0; gi < groups.size(); ++gi) { @@ -547,12 +553,13 @@ namespace psemek::phys2d } } } + } - std::size_t const contact_count = contacts_by_velocity.size(); - std::size_t const impulse_iterations = contact_count * 2; - std::size_t const penetraion_iterations = contact_count * 2; + void engine::impl::resolve_impulses() + { + std::size_t const iterations = contacts_by_velocity.size() * 2; - for (std::size_t iteration = 0; iteration < impulse_iterations; ++iteration) + for (std::size_t iteration = 0; iteration < iterations; ++iteration) { contact const & c = *contacts_by_velocity.begin(); @@ -711,9 +718,11 @@ namespace psemek::phys2d groups[ccc.gj].contacts_by_velocity[ccc.j][ctj] = new_it; } } + } - std::set contacts_by_penetration; + void engine::impl::resolve_penetrations() + { for (auto it = contacts_by_velocity.begin(); it != contacts_by_velocity.end();) { auto jt = it++; @@ -726,9 +735,9 @@ namespace psemek::phys2d groups[c.gj].contacts_by_penetration[c.j].push_back(new_it); } - assert(contacts_by_penetration.size() == contact_count); + std::size_t const iterations = contacts_by_penetration.size() * 2; - for (std::size_t iteration = 0; iteration < penetraion_iterations; ++iteration) + for (std::size_t iteration = 0; iteration < iterations; ++iteration) { contact const & c = *contacts_by_penetration.begin();