Merge branch 'zesterer/small-fixes' into 'master'

Fixed handling of orientation changes for airships

See merge request veloren/veloren!2640
This commit is contained in:
Joshua Barretto 2021-07-18 08:29:50 +00:00
commit 1501f0467e
4 changed files with 66 additions and 45 deletions

View File

@ -84,7 +84,7 @@ pub use self::{
misc::Object, misc::Object,
ori::Ori, ori::Ori,
phys::{ phys::{
Collider, Density, ForceUpdate, Mass, PhysicsState, Pos, PosVelDefer, PreviousPhysCache, Collider, Density, ForceUpdate, Mass, PhysicsState, Pos, PosVelOriDefer, PreviousPhysCache,
Scale, Sticky, Vel, Scale, Sticky, Vel,
}, },
player::DisconnectReason, player::DisconnectReason,

View File

@ -1,4 +1,4 @@
use super::Fluid; use super::{Fluid, Ori};
use crate::{consts::WATER_DENSITY, terrain::Block, uid::Uid}; use crate::{consts::WATER_DENSITY, terrain::Block, uid::Uid};
use hashbrown::HashSet; use hashbrown::HashSet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -31,12 +31,13 @@ impl Component for Vel {
/// Used to defer writes to Pos/Vel in nested join loops /// Used to defer writes to Pos/Vel in nested join loops
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct PosVelDefer { pub struct PosVelOriDefer {
pub pos: Option<Pos>, pub pos: Option<Pos>,
pub vel: Option<Vel>, pub vel: Option<Vel>,
pub ori: Option<Ori>,
} }
impl Component for PosVelDefer { impl Component for PosVelOriDefer {
// TODO: why not regular vec storage???? // TODO: why not regular vec storage????
type Storage = IdvStorage<Self>; type Storage = IdvStorage<Self>;
} }

View File

@ -166,7 +166,7 @@ impl State {
// Register common unsynced components // Register common unsynced components
ecs.register::<comp::PreviousPhysCache>(); ecs.register::<comp::PreviousPhysCache>();
ecs.register::<comp::PosVelDefer>(); ecs.register::<comp::PosVelOriDefer>();
// Register client-local components // Register client-local components
// TODO: only register on the client // TODO: only register on the client

View File

@ -3,7 +3,7 @@ use common::{
body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST}, body::ship::figuredata::{VoxelCollider, VOXEL_COLLIDER_MANIFEST},
fluid_dynamics::{Fluid, LiquidKind, Wings}, fluid_dynamics::{Fluid, LiquidKind, Wings},
BeamSegment, Body, CharacterState, Collider, Density, Mass, Mounting, Ori, PhysicsState, BeamSegment, Body, CharacterState, Collider, Density, Mass, Mounting, Ori, PhysicsState,
Pos, PosVelDefer, PreviousPhysCache, Projectile, Scale, Shockwave, Stats, Sticky, Vel, Pos, PosVelOriDefer, PreviousPhysCache, Projectile, Scale, Shockwave, Stats, Sticky, Vel,
}, },
consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY}, consts::{AIR_DENSITY, FRIC_GROUND, GRAVITY},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
@ -134,7 +134,7 @@ pub struct PhysicsWrite<'a> {
physics_states: WriteStorage<'a, PhysicsState>, physics_states: WriteStorage<'a, PhysicsState>,
positions: WriteStorage<'a, Pos>, positions: WriteStorage<'a, Pos>,
velocities: WriteStorage<'a, Vel>, velocities: WriteStorage<'a, Vel>,
pos_vel_defers: WriteStorage<'a, PosVelDefer>, pos_vel_ori_defers: WriteStorage<'a, PosVelOriDefer>,
orientations: WriteStorage<'a, Ori>, orientations: WriteStorage<'a, Ori>,
previous_phys_cache: WriteStorage<'a, PreviousPhysCache>, previous_phys_cache: WriteStorage<'a, PreviousPhysCache>,
outcomes: Write<'a, Vec<Outcome>>, outcomes: Write<'a, Vec<Outcome>>,
@ -537,27 +537,29 @@ impl<'a> PhysicsData<'a> {
ref mut write, ref mut write,
} = self; } = self;
prof_span!(guard, "insert PosVelDefer"); prof_span!(guard, "insert PosVelOriDefer");
// NOTE: keep in sync with join below // NOTE: keep in sync with join below
( (
&read.entities, &read.entities,
read.colliders.mask(), read.colliders.mask(),
&write.positions, &write.positions,
&write.velocities, &write.velocities,
&write.orientations,
write.orientations.mask(), write.orientations.mask(),
write.physics_states.mask(), write.physics_states.mask(),
!&write.pos_vel_defers, // This is the one we are adding !&write.pos_vel_ori_defers, // This is the one we are adding
write.previous_phys_cache.mask(), write.previous_phys_cache.mask(),
!&read.mountings, !&read.mountings,
) )
.join() .join()
.map(|t| (t.0, *t.2, *t.3)) .map(|t| (t.0, *t.2, *t.3, *t.4))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
.for_each(|(entity, pos, vel)| { .for_each(|(entity, pos, vel, ori)| {
let _ = write.pos_vel_defers.insert(entity, PosVelDefer { let _ = write.pos_vel_ori_defers.insert(entity, PosVelOriDefer {
pos: Some(pos), pos: Some(pos),
vel: Some(vel), vel: Some(vel),
ori: Some(ori),
}); });
}); });
drop(guard); drop(guard);
@ -658,6 +660,20 @@ impl<'a> PhysicsData<'a> {
// Third pass: resolve collisions for non-terrain-like entities // Third pass: resolve collisions for non-terrain-like entities
Self::resolve_et_collision(job, read, write, voxel_collider_spatial_grid, false); Self::resolve_et_collision(job, read, write, voxel_collider_spatial_grid, false);
// Update cached 'old' physics values to the current values ready for the next
// tick
prof_span!(guard, "record ori into phys_cache");
for (ori, previous_phys_cache, _) in (
&write.orientations,
&mut write.previous_phys_cache,
&read.colliders,
)
.join()
{
previous_phys_cache.ori = ori.to_quat();
}
drop(guard);
} }
fn resolve_et_collision( fn resolve_et_collision(
@ -686,7 +702,7 @@ impl<'a> PhysicsData<'a> {
read.bodies.maybe(), read.bodies.maybe(),
read.character_states.maybe(), read.character_states.maybe(),
&mut write.physics_states, &mut write.physics_states,
&mut write.pos_vel_defers, &mut write.pos_vel_ori_defers,
previous_phys_cache, previous_phys_cache,
!&read.mountings, !&read.mountings,
) )
@ -705,20 +721,22 @@ impl<'a> PhysicsData<'a> {
collider, collider,
pos, pos,
vel, vel,
_ori, ori,
body, body,
character_state, character_state,
mut physics_state, mut physics_state,
pos_vel_defer, pos_vel_ori_defer,
_previous_cache, _previous_cache,
_, _,
)| { )| {
let mut land_on_ground = None; let mut land_on_ground = None;
let mut outcomes = Vec::new(); let mut outcomes = Vec::new();
// Defer the writes of positions and velocities to allow an inner loop over // Defer the writes of positions, velocities and orientations to allow an inner
// terrain-like entities // loop over terrain-like entities
let old_vel = *vel; let old_vel = *vel;
let mut vel = *vel; let mut vel = *vel;
let old_ori = *ori;
let mut ori = *ori;
let scale = if let Collider::Voxel { .. } = collider { let scale = if let Collider::Voxel { .. } = collider {
scale.map(|s| s.0).unwrap_or(1.0) scale.map(|s| s.0).unwrap_or(1.0)
@ -1028,16 +1046,17 @@ impl<'a> PhysicsData<'a> {
// The velocity of the collider, taking into account // The velocity of the collider, taking into account
// orientation. // orientation.
let wpos_rel = (Mat4::<f32>::translation_3d(pos_other.0) let pos_rel = (Mat4::<f32>::translation_3d(Vec3::zero())
* Mat4::from(ori_other.to_quat()) * Mat4::from(ori_other.to_quat())
* Mat4::<f32>::translation_3d(voxel_collider.translation)) * Mat4::<f32>::translation_3d(voxel_collider.translation))
.inverted() .inverted()
.mul_point(wpos); .mul_point(wpos - pos_other.0);
let wpos_last = (Mat4::<f32>::translation_3d(pos_other.0) let rpos_last = (Mat4::<f32>::translation_3d(Vec3::zero())
* Mat4::from(previous_cache_other.ori) * Mat4::from(previous_cache_other.ori)
* Mat4::<f32>::translation_3d(voxel_collider.translation)) * Mat4::<f32>::translation_3d(voxel_collider.translation))
.mul_point(wpos_rel); .mul_point(pos_rel);
let vel_other = vel_other.0 + (wpos - wpos_last) / read.dt.0; let vel_other = vel_other.0
+ (wpos - (pos_other.0 + rpos_last)) / read.dt.0;
cpos.0 = transform_to.mul_point(Vec3::zero()); cpos.0 = transform_to.mul_point(Vec3::zero());
vel.0 = ori_to.mul_direction(vel.0 - vel_other); vel.0 = ori_to.mul_direction(vel.0 - vel_other);
@ -1071,6 +1090,12 @@ impl<'a> PhysicsData<'a> {
// recent terrain that collision was attempted with // recent terrain that collision was attempted with
if physics_state_delta.on_ground.is_some() { if physics_state_delta.on_ground.is_some() {
physics_state.ground_vel = vel_other; physics_state.ground_vel = vel_other;
// Rotate if on ground
ori = ori.rotated(
ori_other.to_quat()
* previous_cache_other.ori.inverse(),
);
} }
physics_state.on_ground = physics_state.on_ground =
physics_state.on_ground.or(physics_state_delta.on_ground); physics_state.on_ground.or(physics_state_delta.on_ground);
@ -1102,15 +1127,19 @@ impl<'a> PhysicsData<'a> {
); );
if tgt_pos != pos.0 { if tgt_pos != pos.0 {
pos_vel_defer.pos = Some(Pos(tgt_pos)); pos_vel_ori_defer.pos = Some(Pos(tgt_pos));
} else { } else {
pos_vel_defer.pos = None; pos_vel_ori_defer.pos = None;
} }
if vel != old_vel { if vel != old_vel {
pos_vel_defer.vel = Some(vel); pos_vel_ori_defer.vel = Some(vel);
} else { } else {
pos_vel_defer.vel = None; pos_vel_ori_defer.vel = None;
}
if ori != old_ori {
pos_vel_ori_defer.ori = Some(ori);
} else {
pos_vel_ori_defer.ori = None;
} }
(land_on_ground, outcomes) (land_on_ground, outcomes)
@ -1139,35 +1168,26 @@ 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, ori, pos_vel_ori_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.orientations,
&mut write.pos_vel_ori_defers,
&read.colliders, &read.colliders,
) )
.join() .join()
.filter(|tuple| matches!(tuple.4, Collider::Voxel { .. }) == terrain_like_entities) .filter(|tuple| matches!(tuple.5, Collider::Voxel { .. }) == terrain_like_entities)
{ {
if let Some(new_pos) = pos_vel_defer.pos.take() { if let Some(new_pos) = pos_vel_ori_defer.pos.take() {
*pos = new_pos; *pos = new_pos;
} }
if let Some(new_vel) = pos_vel_defer.vel.take() { if let Some(new_vel) = pos_vel_ori_defer.vel.take() {
*vel = new_vel; *vel = new_vel;
} }
} if let Some(new_ori) = pos_vel_ori_defer.ori.take() {
drop(guard); *ori = new_ori;
}
prof_span!(guard, "record ori into phys_cache");
for (ori, previous_phys_cache, _) in (
&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();
} }
drop(guard); drop(guard);