Merge branch 'aweinstock/terrain-entity-physics-20210528' into 'master'

Fixed entities with voxel colliders being off by one physics tick for collision.

See merge request veloren/veloren!2355
This commit is contained in:
Marcel 2021-05-30 16:25:44 +00:00
commit a8fb168315
2 changed files with 40 additions and 12 deletions

View File

@ -142,6 +142,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Far away NPCs respond to being damaged by a projectile - Far away NPCs respond to being damaged by a projectile
- Fixed terrain clipping with glider - Fixed terrain clipping with glider
- Fixed an issue where prices weren't properly making their way from econsim to the actual trade values. - Fixed an issue where prices weren't properly making their way from econsim to the actual trade values.
- Fixed entities with voxel colliders being off by one physics tick for collision.
## [0.9.0] - 2021-03-20 ## [0.9.0] - 2021-03-20

View File

@ -556,13 +556,8 @@ impl<'a> PhysicsData<'a> {
drop(guard); drop(guard);
// Apply movement inputs // Apply movement inputs
span!(guard, "Apply movement and terrain collision"); span!(guard, "Apply movement");
let (positions, velocities, previous_phys_cache, orientations) = ( let (positions, velocities) = (&write.positions, &mut write.velocities);
&write.positions,
&mut write.velocities,
&write.previous_phys_cache,
&write.orientations,
);
// First pass: update velocity using air resistance and gravity for each entity. // First pass: update velocity using air resistance and gravity for each entity.
// We do this in a first pass because it helps keep things more stable for // We do this in a first pass because it helps keep things more stable for
@ -645,10 +640,34 @@ impl<'a> PhysicsData<'a> {
} }
}, },
); );
drop(guard);
job.cpu_stats.measure(ParMode::Single);
let velocities = &write.velocities; // Second pass: resolve collisions for terrain-like entities, this is required
// in order to update their positions before resolving collisions for
// non-terrain-like entities, since otherwise, collision is resolved
// based on where the terrain-like entity was in the previous frame.
Self::resolve_et_collision(job, read, write, voxel_collider_spatial_grid, true);
// Second pass: resolve collisions // Third pass: resolve collisions for non-terrain-like entities
Self::resolve_et_collision(job, read, write, voxel_collider_spatial_grid, false);
}
fn resolve_et_collision(
job: &mut Job<Sys>,
read: &PhysicsRead,
write: &mut PhysicsWrite,
voxel_collider_spatial_grid: &SpatialGrid,
terrain_like_entities: bool,
) {
let (positions, velocities, previous_phys_cache, orientations) = (
&write.positions,
&write.velocities,
&write.previous_phys_cache,
&write.orientations,
);
span!(guard, "Apply terrain collision");
job.cpu_stats.measure(ParMode::Rayon);
let (land_on_grounds, mut outcomes) = ( let (land_on_grounds, mut outcomes) = (
&read.entities, &read.entities,
read.scales.maybe(), read.scales.maybe(),
@ -665,6 +684,7 @@ impl<'a> PhysicsData<'a> {
!&read.mountings, !&read.mountings,
) )
.par_join() .par_join()
.filter(|tuple| matches!(tuple.3, Collider::Voxel { .. }) == terrain_like_entities)
.map_init( .map_init(
|| { || {
prof_span!(guard, "physics e<>t rayon job"); prof_span!(guard, "physics e<>t rayon job");
@ -1106,13 +1126,15 @@ impl<'a> PhysicsData<'a> {
write.outcomes.append(&mut outcomes); write.outcomes.append(&mut outcomes);
prof_span!(guard, "write deferred pos and vel"); prof_span!(guard, "write deferred pos and vel");
for (_, pos, vel, pos_vel_defer) in ( for (_, pos, vel, pos_vel_defer, _) in (
&read.entities, &read.entities,
&mut write.positions, &mut write.positions,
&mut write.velocities, &mut write.velocities,
&mut write.pos_vel_defers, &mut write.pos_vel_defers,
&read.colliders,
) )
.join() .join()
.filter(|tuple| matches!(tuple.4, Collider::Voxel { .. }) == terrain_like_entities)
{ {
if let Some(new_pos) = pos_vel_defer.pos.take() { if let Some(new_pos) = pos_vel_defer.pos.take() {
*pos = new_pos; *pos = new_pos;
@ -1124,8 +1146,13 @@ impl<'a> PhysicsData<'a> {
drop(guard); drop(guard);
prof_span!(guard, "record ori into phys_cache"); prof_span!(guard, "record ori into phys_cache");
for (ori, previous_phys_cache) in for (ori, previous_phys_cache, _) in (
(&write.orientations, &mut write.previous_phys_cache).join() &write.orientations,
&mut write.previous_phys_cache,
&read.colliders,
)
.join()
.filter(|tuple| matches!(tuple.2, Collider::Voxel { .. }) == terrain_like_entities)
{ {
previous_phys_cache.ori = ori.to_quat(); previous_phys_cache.ori = ori.to_quat();
} }