Physics engine: always resolve penetration, but apply impulse only on approach velocity

This commit is contained in:
Nikita Lisitsa 2020-12-03 20:04:53 +03:00
parent b2b6d18dd0
commit a75b8710de

View file

@ -390,7 +390,7 @@ namespace psemek::phys2d
void apply_gravity(float dt); void apply_gravity(float dt);
void integrate(float dt); void integrate(float dt);
bool resolve_collisions(); void resolve_collisions();
void log_energy(); void log_energy();
float energy(); float energy();
@ -447,10 +447,8 @@ namespace psemek::phys2d
} }
} }
bool engine::impl::resolve_collisions() void engine::impl::resolve_collisions()
{ {
bool had_collision = false;
for (std::size_t gi = 0; gi < groups.size(); ++gi) for (std::size_t gi = 0; gi < groups.size(); ++gi)
{ {
for (std::size_t gj = gi; gj < groups.size(); ++gj) for (std::size_t gj = gi; gj < groups.size(); ++gj)
@ -473,8 +471,6 @@ namespace psemek::phys2d
if (c->penetration == geom::vector<float, 2>::zero()) continue; if (c->penetration == geom::vector<float, 2>::zero()) continue;
// TODO: handle inv_mass == 0
auto const n = geom::normalized(c->penetration); auto const n = geom::normalized(c->penetration);
auto const & infoi = groups[gi].infos[i]; auto const & infoi = groups[gi].infos[i];
@ -491,10 +487,8 @@ namespace psemek::phys2d
auto const u = uj - ui; auto const u = uj - ui;
if (geom::dot(u, n) > 0.f) continue; if (geom::dot(u, n) < 0.f)
{
had_collision = true;
auto const & mati = materials[infoi.material]; auto const & mati = materials[infoi.material];
auto const & matj = materials[infoj.material]; auto const & matj = materials[infoj.material];
@ -523,10 +517,10 @@ namespace psemek::phys2d
// Tangential relative velocity -> 0 // Tangential relative velocity -> 0
auto const J2 = - *geom::solve(K, u); auto const J2 = - *geom::solve(K, u);
// float const e = (mati.elasticity + matj.elasticity) / 2.f; // float const e = (mati.elasticity + matj.elasticity) / 2.f;
float const e = std::sqrt(mati.elasticity * matj.elasticity); float const e = std::sqrt(mati.elasticity * matj.elasticity);
// float const f = (mati.friction + matj.friction) / 2.f; // float const f = (mati.friction + matj.friction) / 2.f;
float const f = std::sqrt(mati.friction * matj.friction); float const f = std::sqrt(mati.friction * matj.friction);
float const mu = f; float const mu = f;
@ -546,6 +540,7 @@ namespace psemek::phys2d
groups[gi].dynamic_states[i].angular_velocity -= geom::det(ri, J) * infoi.inv_inertia; groups[gi].dynamic_states[i].angular_velocity -= geom::det(ri, J) * infoi.inv_inertia;
groups[gj].dynamic_states[j].angular_velocity += geom::det(rj, J) * infoj.inv_inertia; groups[gj].dynamic_states[j].angular_velocity += geom::det(rj, J) * infoj.inv_inertia;
}
groups[gi].static_states[i].position -= c->penetration * infoi.inv_mass / (infoi.inv_mass + infoj.inv_mass); groups[gi].static_states[i].position -= c->penetration * infoi.inv_mass / (infoi.inv_mass + infoj.inv_mass);
groups[gj].static_states[j].position += c->penetration * infoj.inv_mass / (infoi.inv_mass + infoj.inv_mass); groups[gj].static_states[j].position += c->penetration * infoj.inv_mass / (infoi.inv_mass + infoj.inv_mass);
@ -553,8 +548,6 @@ namespace psemek::phys2d
} }
} }
} }
return !had_collision;
} }
float engine::impl::energy() float engine::impl::energy()