diff --git a/examples/physics_2d.cpp b/examples/physics_2d.cpp index ab6c19cf..e046bbe6 100644 --- a/examples/physics_2d.cpp +++ b/examples/physics_2d.cpp @@ -70,7 +70,7 @@ struct physics_2d_app float const inf = std::numeric_limits::infinity(); - material = physics.add_material({1.f, 0.5f, 0.9f}); + material = physics.add_material({1.f, 0.5f, 0.5f}); ball_shape = physics.add_shape(phys2d::ball{ball_radius}); ball_group = physics.create_group(); @@ -78,12 +78,14 @@ struct physics_2d_app box_shape = physics.add_shape(phys2d::box{box_width, box_height}); box_group = physics.create_group(); - if(false) - for (int x = -4; x <= 4; ++x) + int nx = std::ceil(simulation_box[0].length() / box_width); + int ny = std::ceil(simulation_box[1].length() / box_height); + + for (int x = 0; x < nx; ++x) { - for (int y = 0; y < 3; ++y) + for (int y = 0; y < ny / 3; ++y) { - geom::point pos{simulation_box[0].center() + x * box_width, simulation_box[1].min + (y + 0.5f) * box_height}; + geom::point pos{simulation_box.corner((x + 0.5f) / nx, (y + 0.5f) / ny)}; physics.add_object(box_group, box_shape, material, {pos, 0.f}, {}); } } @@ -103,9 +105,9 @@ struct physics_2d_app auto wall_3_shape = physics.add_shape(phys2d::half_space{{0.f, -1.f}, -simulation_box[1].max}); physics.add_object(wall_group, wall_3_shape, wall_material, {}, {}); - auto task = util::recursive([this, dx = 0.1f](auto && self) mutable -> void { -// physics.add_object(box_group, box_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {}); - physics.add_object(ball_group, ball_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {}); + auto task = util::recursive([this, dx = box_width * 0.4f](auto && self) mutable -> void { + physics.add_object(box_group, box_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {}); +// physics.add_object(ball_group, ball_shape, material, {simulation_box.corner(0.5f, 0.9f) + geom::vector{dx, 0.f}, 0.f}, {}); // float r = pcg::uniform_distribution{0.05f, 0.5f}(gen); // auto new_shape = physics.add_shape(phys2d::ball{r}); @@ -113,8 +115,8 @@ struct physics_2d_app // radiuses.push_back(r); dx *= -1.f; - if (physics.group_size(box_group) < 200) - loop.dispatch_at(std::chrono::system_clock::now() + std::chrono::milliseconds{250}, self); + if (physics.group_size(box_group) < 100) + loop.dispatch_at(std::chrono::system_clock::now() + std::chrono::milliseconds{100}, self); }); (void)task; // task(); @@ -138,7 +140,7 @@ struct physics_2d_app if (mouse) { - physics.add_object(ball_group, ball_shape, material, {*mouse, 0.f}, {}); + physics.add_object(ball_group, ball_shape, material, {*mouse, 0.f}, {{0.f, 0.f}, 25.f}); } } @@ -153,7 +155,7 @@ struct physics_2d_app if (mouse) { - physics.add_object(box_group, box_shape, material, {*mouse, 0.f}, {}); + physics.explode(*mouse, 10.f, 1.f); } } diff --git a/libs/phys/include/psemek/phys/engine_2d.hpp b/libs/phys/include/psemek/phys/engine_2d.hpp index 3facb47b..47eba6ed 100644 --- a/libs/phys/include/psemek/phys/engine_2d.hpp +++ b/libs/phys/include/psemek/phys/engine_2d.hpp @@ -53,6 +53,10 @@ namespace psemek::phys2d void set_gravity(geom::vector const & g); + // Effects + + void explode(geom::point const & center, float strength, float attenuation); + // Main update void update(float dt); diff --git a/libs/phys/source/engine_2d.cpp b/libs/phys/source/engine_2d.cpp index 10dbe2b8..6733bc44 100644 --- a/libs/phys/source/engine_2d.cpp +++ b/libs/phys/source/engine_2d.cpp @@ -337,6 +337,8 @@ namespace psemek::phys2d std::optional> gravity; + void explode(geom::point const & center, float strength, float attenuation); + void update(float dt); void apply_gravity(float dt); @@ -347,6 +349,21 @@ namespace psemek::phys2d float energy(); }; + void engine::impl::explode(geom::point const & center, float strength, float attenuation) + { + for (auto & g : groups) + { + for (std::size_t i = 0; i < g.infos.size(); ++i) + { + auto r = g.static_states[i].position - center; + float l = geom::length(r); + + auto J = (r / l) * strength / (1.f + l * l * attenuation); + g.dynamic_states[i].velocity += J * g.infos[i].inv_mass; + } + } + } + void engine::impl::update(float dt) { apply_gravity(dt); @@ -640,6 +657,11 @@ namespace psemek::phys2d impl().gravity = g; } + void engine::explode(geom::point const & center, float strength, float attenuation) + { + impl().explode(center, strength, attenuation); + } + void engine::update(float dt) { impl().update(dt);