Merge branch 'Dumbeldor/opti_phys_entities' into 'master'

Physics improvements

See merge request veloren/veloren!1809
This commit is contained in:
Marcel 2021-02-22 14:17:23 +00:00
commit cee08c7012
4 changed files with 58 additions and 47 deletions

View File

@ -65,7 +65,7 @@ pub use location::{Waypoint, WaypointArea};
pub use misc::Object; pub use misc::Object;
pub use ori::Ori; pub use ori::Ori;
pub use phys::{ pub use phys::{
Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PreviousVelDtCache, Scale, Sticky, Vel, Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PreviousPhysCache, Scale, Sticky, Vel,
}; };
pub use player::Player; pub use player::Player;
pub use poise::{Poise, PoiseChange, PoiseSource, PoiseState}; pub use poise::{Poise, PoiseChange, PoiseSource, PoiseState};

View File

@ -24,9 +24,15 @@ impl Component for Vel {
/// It's updated and read in physics sys to speed up entity<->entity collisions /// It's updated and read in physics sys to speed up entity<->entity collisions
/// no need to send it via network /// no need to send it via network
#[derive(Copy, Clone, Default, Debug, PartialEq)] #[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct PreviousVelDtCache(pub Vec3<f32>); pub struct PreviousPhysCache {
pub velocity: Vec3<f32>,
pub middle: Vec3<f32>,
///calculates a Sphere over the Entity for quick boundry checking
pub radius: f32,
pub scale: f32,
}
impl Component for PreviousVelDtCache { impl Component for PreviousPhysCache {
type Storage = IdvStorage<Self>; type Storage = IdvStorage<Self>;
} }

View File

@ -1,7 +1,7 @@
use common::{ use common::{
comp::{ comp::{
BeamSegment, CharacterState, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, BeamSegment, CharacterState, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos,
PreviousVelDtCache, Projectile, Scale, Shockwave, Sticky, Vel, PreviousPhysCache, Projectile, Scale, Shockwave, Sticky, Vel,
}, },
consts::{FRIC_GROUND, GRAVITY}, consts::{FRIC_GROUND, GRAVITY},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
@ -67,7 +67,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Pos>, WriteStorage<'a, Pos>,
WriteStorage<'a, Vel>, WriteStorage<'a, Vel>,
WriteStorage<'a, Ori>, WriteStorage<'a, Ori>,
WriteStorage<'a, PreviousVelDtCache>, WriteStorage<'a, PreviousPhysCache>,
ReadStorage<'a, Mounting>, ReadStorage<'a, Mounting>,
ReadStorage<'a, Projectile>, ReadStorage<'a, Projectile>,
ReadStorage<'a, BeamSegment>, ReadStorage<'a, BeamSegment>,
@ -96,7 +96,7 @@ impl<'a> System<'a> for Sys {
mut positions, mut positions,
mut velocities, mut velocities,
mut orientations, mut orientations,
mut previous_velocities_times_dt, mut previous_phys_cache,
mountings, mountings,
projectiles, projectiles,
beams, beams,
@ -139,12 +139,12 @@ impl<'a> System<'a> for Sys {
// it means the step needs to take into account the speeds of both // it means the step needs to take into account the speeds of both
// entities. // entities.
span!(guard, "Maintain pushback cache"); span!(guard, "Maintain pushback cache");
//Add PreviousVelDtCache for all relevant entities //Add PreviousPhysCache for all relevant entities
for entity in ( for entity in (
&entities, &entities,
&velocities, &velocities,
&positions, &positions,
!&previous_velocities_times_dt, !&previous_phys_cache,
!&mountings, !&mountings,
!&beams, !&beams,
!&shockwaves, !&shockwaves,
@ -153,22 +153,36 @@ impl<'a> System<'a> for Sys {
.map(|(e, _, _, _, _, _, _)| e) .map(|(e, _, _, _, _, _, _)| e)
.collect::<Vec<_>>() .collect::<Vec<_>>()
{ {
let _ = previous_velocities_times_dt.insert(entity, PreviousVelDtCache(Vec3::zero())); let _ = previous_phys_cache.insert(entity, PreviousPhysCache {
velocity: Vec3::zero(),
middle: Vec3::zero(),
radius: 0.0,
scale: 0.0,
});
} }
//Update PreviousVelDtCache //Update PreviousPhysCache
for (_, vel, _, mut vel_dt, _, _, _) in ( for (_, vel, position, mut phys_cache, collider, scale, _, _, _) in (
&entities, &entities,
&velocities, &velocities,
&positions, &positions,
&mut previous_velocities_times_dt, &mut previous_phys_cache,
colliders.maybe(),
scales.maybe(),
!&mountings, !&mountings,
!&beams, !&beams,
!&shockwaves, !&shockwaves,
) )
.join() .join()
{ {
vel_dt.0 = vel.0 * dt.0; phys_cache.velocity = vel.0 * dt.0;
phys_cache.middle = position.0;
let scale_find = scale.map(|s| s.0).unwrap_or(1.0);
let radius_find = collider.map(|c| c.get_radius()).unwrap_or(0.5);
phys_cache.radius = radius_find * scale_find;
phys_cache.scale = scale_find;
} }
drop(guard); drop(guard);
span!(guard, "Apply pushback"); span!(guard, "Apply pushback");
@ -176,8 +190,7 @@ impl<'a> System<'a> for Sys {
&entities, &entities,
&positions, &positions,
&mut velocities, &mut velocities,
&previous_velocities_times_dt, &previous_phys_cache,
scales.maybe(),
masses.maybe(), masses.maybe(),
colliders.maybe(), colliders.maybe(),
!&mountings, !&mountings,
@ -189,10 +202,10 @@ impl<'a> System<'a> for Sys {
char_states.maybe(), char_states.maybe(),
) )
.par_join() .par_join()
.filter(|(_, _, _, _, _, _, _, _, sticky, physics, _, _)| { .filter(|(_, _, _, _, _, _, _, sticky, physics, _, _)| {
sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground) sticky.is_none() || (physics.on_wall.is_none() && !physics.on_ground)
}) })
.map(|(e, p, v, vd, s, m, c, _, _, ph, pr, c_s)| (e, p, v, vd, s, m, c, ph, pr, c_s)) .map(|(e, p, v, vd, m, c, _, _, ph, pr, c_s)| (e, p, v, vd, m, c, ph, pr, c_s))
.fold( .fold(
PhysicsMetrics::default, PhysicsMetrics::default,
|mut metrics, |mut metrics,
@ -200,16 +213,13 @@ impl<'a> System<'a> for Sys {
entity, entity,
pos, pos,
vel, vel,
vel_dt, previous_cache,
scale,
mass, mass,
collider, collider,
physics, physics,
projectile, projectile,
char_state_maybe, char_state_maybe,
)| { )| {
let scale = scale.map(|s| s.0).unwrap_or(1.0);
let radius = collider.map(|c| c.get_radius()).unwrap_or(0.5);
let modifier = if char_state_maybe.map_or(false, |c_s| c_s.is_dodge()) { let modifier = if char_state_maybe.map_or(false, |c_s| c_s.is_dodge()) {
0.5 0.5
} else { } else {
@ -218,7 +228,7 @@ impl<'a> System<'a> for Sys {
let z_limits = collider let z_limits = collider
.map(|c| c.get_z_limits(modifier)) .map(|c| c.get_z_limits(modifier))
.unwrap_or((-0.5 * modifier, 0.5 * modifier)); .unwrap_or((-0.5 * modifier, 0.5 * modifier));
let mass = mass.map(|m| m.0).unwrap_or(scale); let mass = mass.map(|m| m.0).unwrap_or(previous_cache.scale);
// Resets touch_entities in physics // Resets touch_entities in physics
physics.touch_entities.clear(); physics.touch_entities.clear();
@ -231,8 +241,7 @@ impl<'a> System<'a> for Sys {
entity_other, entity_other,
other, other,
pos_other, pos_other,
vel_dt_other, previous_cache_other,
scale_other,
mass_other, mass_other,
collider_other, collider_other,
_, _,
@ -244,8 +253,7 @@ impl<'a> System<'a> for Sys {
&entities, &entities,
&uids, &uids,
&positions, &positions,
&previous_velocities_times_dt, &previous_phys_cache,
scales.maybe(),
masses.maybe(), masses.maybe(),
colliders.maybe(), colliders.maybe(),
!&projectiles, !&projectiles,
@ -256,18 +264,12 @@ impl<'a> System<'a> for Sys {
) )
.join() .join()
{ {
if entity == entity_other { let collision_dist = previous_cache.radius + previous_cache_other.radius;
continue; if previous_cache
} .middle
.distance_squared(previous_cache_other.middle)
let scale_other = scale_other.map(|s| s.0).unwrap_or(1.0); > collision_dist.powi(2)
let radius_other = collider_other.map(|c| c.get_radius()).unwrap_or(0.5); || entity == entity_other
let collision_dist = scale * radius + scale_other * radius_other;
// Sanity check: skip colliding entities that are too far from each other
if (pos.0 - pos_other.0).xy().magnitude()
> (vel_dt.0 - vel_dt_other.0).xy().magnitude() + collision_dist
{ {
continue; continue;
} }
@ -282,7 +284,9 @@ impl<'a> System<'a> for Sys {
let z_limits_other = collider_other let z_limits_other = collider_other
.map(|c| c.get_z_limits(modifier_other)) .map(|c| c.get_z_limits(modifier_other))
.unwrap_or((-0.5 * modifier_other, 0.5 * modifier_other)); .unwrap_or((-0.5 * modifier_other, 0.5 * modifier_other));
let mass_other = mass_other.map(|m| m.0).unwrap_or(scale_other); let mass_other = mass_other
.map(|m| m.0)
.unwrap_or(previous_cache_other.scale);
//This check after the pos check, as we currently don't have that many //This check after the pos check, as we currently don't have that many
// massless entites [citation needed] // massless entites [citation needed]
if mass_other == 0.0 { if mass_other == 0.0 {
@ -292,7 +296,8 @@ impl<'a> System<'a> for Sys {
metrics.entity_entity_collision_checks += 1; metrics.entity_entity_collision_checks += 1;
const MIN_COLLISION_DIST: f32 = 0.3; const MIN_COLLISION_DIST: f32 = 0.3;
let increments = ((vel_dt.0 - vel_dt_other.0).magnitude() let increments = ((previous_cache.velocity - previous_cache_other.velocity)
.magnitude()
/ MIN_COLLISION_DIST) / MIN_COLLISION_DIST)
.max(1.0) .max(1.0)
.ceil() as usize; .ceil() as usize;
@ -301,16 +306,16 @@ impl<'a> System<'a> for Sys {
for i in 0..increments { for i in 0..increments {
let factor = i as f32 * step_delta; let factor = i as f32 * step_delta;
let pos = pos.0 + vel_dt.0 * factor; let pos = pos.0 + previous_cache.velocity * factor;
let pos_other = pos_other.0 + vel_dt_other.0 * factor; let pos_other = pos_other.0 + previous_cache_other.velocity * factor;
let diff = pos.xy() - pos_other.xy(); let diff = pos.xy() - pos_other.xy();
if diff.magnitude_squared() <= collision_dist.powi(2) if diff.magnitude_squared() <= collision_dist.powi(2)
&& pos.z + z_limits.1 * scale && pos.z + z_limits.1 * previous_cache.scale
>= pos_other.z + z_limits_other.0 * scale_other >= pos_other.z + z_limits_other.0 * previous_cache_other.scale
&& pos.z + z_limits.0 * scale && pos.z + z_limits.0 * previous_cache.scale
<= pos_other.z + z_limits_other.1 * scale_other <= pos_other.z + z_limits_other.1 * previous_cache_other.scale
{ {
if !collided { if !collided {
physics.touch_entities.push(*other); physics.touch_entities.push(*other);

View File

@ -171,7 +171,7 @@ impl State {
ecs.register::<comp::invite::Invite>(); ecs.register::<comp::invite::Invite>();
ecs.register::<comp::invite::PendingInvites>(); ecs.register::<comp::invite::PendingInvites>();
ecs.register::<comp::Beam>(); ecs.register::<comp::Beam>();
ecs.register::<comp::PreviousVelDtCache>(); ecs.register::<comp::PreviousPhysCache>();
// Register synced resources used by the ECS. // Register synced resources used by the ECS.
ecs.insert(TimeOfDay(0.0)); ecs.insert(TimeOfDay(0.0));