Use previous position caches for airship collision detection

This commit is contained in:
Joshua Barretto 2021-09-17 22:34:28 +01:00
parent 9cc70e6d22
commit a76496c339
3 changed files with 29 additions and 13 deletions

View File

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- The menu map now properly handles dragging the map, zooming, and setting the waypoint when hovering icons - The menu map now properly handles dragging the map, zooming, and setting the waypoint when hovering icons
- Falling through an airship in flight should no longer be possible (although many issues with airship physics remain)
## [0.11.0] - 2021-09-11 ## [0.11.0] - 2021-09-11

View File

@ -60,6 +60,7 @@ pub struct PreviousPhysCache {
pub neighborhood_radius: f32, pub neighborhood_radius: f32,
/// relative p0 and p1 of collider's statium, None if cylinder. /// relative p0 and p1 of collider's statium, None if cylinder.
pub origins: Option<(Vec2<f32>, Vec2<f32>)>, pub origins: Option<(Vec2<f32>, Vec2<f32>)>,
pub pos: Option<Pos>,
pub ori: Quaternion<f32>, pub ori: Quaternion<f32>,
} }

View File

@ -194,6 +194,7 @@ impl<'a> PhysicsData<'a> {
scaled_radius: 0.0, scaled_radius: 0.0,
neighborhood_radius: 0.0, neighborhood_radius: 0.0,
origins: None, origins: None,
pos: None,
ori: Quaternion::identity(), ori: Quaternion::identity(),
}); });
} }
@ -691,7 +692,8 @@ impl<'a> PhysicsData<'a> {
// Update cached 'old' physics values to the current values ready for the next // Update cached 'old' physics values to the current values ready for the next
// tick // tick
prof_span!(guard, "record ori into phys_cache"); prof_span!(guard, "record ori into phys_cache");
for (ori, previous_phys_cache, _) in ( for (pos, ori, previous_phys_cache, _) in (
&write.positions,
&write.orientations, &write.orientations,
&mut write.previous_phys_cache, &mut write.previous_phys_cache,
&read.colliders, &read.colliders,
@ -700,6 +702,7 @@ impl<'a> PhysicsData<'a> {
{ {
// Note: updating ori with the rest of the cache values above was attempted but // Note: updating ori with the rest of the cache values above was attempted but
// it did not work (investigate root cause?) // it did not work (investigate root cause?)
previous_phys_cache.pos = Some(*pos);
previous_phys_cache.ori = ori.to_quat(); previous_phys_cache.ori = ori.to_quat();
} }
drop(guard); drop(guard);
@ -755,7 +758,7 @@ impl<'a> PhysicsData<'a> {
character_state, character_state,
mut physics_state, mut physics_state,
pos_vel_ori_defer, pos_vel_ori_defer,
_previous_cache, previous_cache,
_, _,
)| { )| {
let mut land_on_ground = None; let mut land_on_ground = None;
@ -1077,6 +1080,16 @@ impl<'a> PhysicsData<'a> {
// TODO: Cache the matrices here to avoid recomputing // TODO: Cache the matrices here to avoid recomputing
let transform_last_from = Mat4::<f32>::translation_3d(
previous_cache_other.pos.unwrap_or(*pos_other).0
- previous_cache.pos.unwrap_or(Pos(wpos)).0,
) * Mat4::from(
previous_cache_other.ori,
) * Mat4::<f32>::translation_3d(
voxel_collider.translation,
);
let transform_last_to = transform_last_from.inverted();
let transform_from = let transform_from =
Mat4::<f32>::translation_3d(pos_other.0 - wpos) Mat4::<f32>::translation_3d(pos_other.0 - wpos)
* Mat4::from(ori_other.to_quat()) * Mat4::from(ori_other.to_quat())
@ -1084,8 +1097,11 @@ impl<'a> PhysicsData<'a> {
voxel_collider.translation, voxel_collider.translation,
); );
let transform_to = transform_from.inverted(); let transform_to = transform_from.inverted();
let ori_last_from = Mat4::from(previous_cache_other.ori);
let ori_last_to = ori_last_from.inverted();
let ori_from = Mat4::from(ori_other.to_quat()); let ori_from = Mat4::from(ori_other.to_quat());
let ori_to = ori_from.inverted();
// The velocity of the collider, taking into account // The velocity of the collider, taking into account
// orientation. // orientation.
@ -1101,8 +1117,8 @@ impl<'a> PhysicsData<'a> {
let vel_other = vel_other.0 let vel_other = vel_other.0
+ (wpos - (pos_other.0 + rpos_last)) / read.dt.0; + (wpos - (pos_other.0 + rpos_last)) / read.dt.0;
cpos.0 = transform_to.mul_point(Vec3::zero()); cpos.0 = transform_last_to.mul_point(Vec3::zero());
vel.0 = ori_to.mul_direction(vel.0 - vel_other); vel.0 = ori_last_to.mul_direction(vel.0 - vel_other);
let cylinder = (radius, z_min, z_max); let cylinder = (radius, z_min, z_max);
box_voxel_collision( box_voxel_collision(
cylinder, cylinder,
@ -1112,7 +1128,7 @@ impl<'a> PhysicsData<'a> {
transform_to.mul_point(tgt_pos - wpos), transform_to.mul_point(tgt_pos - wpos),
&mut vel, &mut vel,
&mut physics_state_delta, &mut physics_state_delta,
ori_to.mul_direction(vel_other), ori_last_to.mul_direction(vel_other),
&read.dt, &read.dt,
was_on_ground, was_on_ground,
block_snap, block_snap,
@ -1303,7 +1319,6 @@ impl<'a> System<'a> for Sys {
} }
} }
#[warn(clippy::pedantic)]
#[allow(clippy::too_many_arguments, clippy::too_many_lines)] #[allow(clippy::too_many_arguments, clippy::too_many_lines)]
fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>( fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
cylinder: (f32, f32, f32), // effective collision cylinder cylinder: (f32, f32, f32), // effective collision cylinder
@ -1432,14 +1447,13 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
let mut pos_delta = tgt_pos - pos.0; let mut pos_delta = tgt_pos - pos.0;
// Don't jump too far at once // Don't jump too far at once
let increments = (pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3) const MAX_INCREMENTS: usize = 100; // The maximum number of collision tests per tick
.ceil() let increments = ((pos_delta.map(|e| e.abs()).reduce_partial_max() / 0.3).ceil() as usize)
.max(1.0); .clamped(1, MAX_INCREMENTS);
let old_pos = pos.0; let old_pos = pos.0;
for _ in 0..increments {
for _ in 0..increments as usize {
const MAX_ATTEMPTS: usize = 16; const MAX_ATTEMPTS: usize = 16;
pos.0 += pos_delta / increments; pos.0 += pos_delta / increments as f32;
let try_colliding_block = |pos: &Pos| { let try_colliding_block = |pos: &Pos| {
// Calculate the player's AABB // Calculate the player's AABB