diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index 33729f28ad..cddf4832f8 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -33,6 +33,7 @@ pub struct PreviousPhysCache { pub collision_boundary: f32, pub scale: f32, pub scaled_radius: f32, + pub ori: Quaternion, } impl Component for PreviousPhysCache { diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index a9097aa08e..1b74af1a55 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -170,7 +170,7 @@ impl Body { quadruped_low::Species::Lavadrake => 4.0, _ => 6.0, }, - Body::Ship(_) => 0.5, + Body::Ship(_) => 0.175, } } @@ -300,7 +300,11 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth: } * efficiency; - handle_orientation(data, update, if data.physics.on_ground { 9.0 } else { 2.0 }); + handle_orientation( + data, + update, + data.body.base_ori_rate() * if data.physics.on_ground { 0.5 } else { 0.1 }, + ); // Swim update.vel.0.z = (update.vel.0.z @@ -330,7 +334,7 @@ fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) { * BASE_FLIGHT_ACCEL * efficiency; - handle_orientation(data, update, 1.0); + handle_orientation(data, update, data.body.base_ori_rate()); } /// Checks if an input related to an attack is held. If one is, moves entity diff --git a/common/sys/src/phys.rs b/common/sys/src/phys.rs index 9c73962b31..e5577546ec 100644 --- a/common/sys/src/phys.rs +++ b/common/sys/src/phys.rs @@ -151,6 +151,7 @@ impl<'a> PhysicsData<'a> { collision_boundary: 0.0, scale: 0.0, scaled_radius: 0.0, + ori: Quaternion::identity(), }); } @@ -620,7 +621,7 @@ impl<'a> PhysicsData<'a> { _other, pos_other, vel_other, - _previous_cache_other, + previous_cache_other, _mass_other, collider_other, ori_other, @@ -678,6 +679,9 @@ impl<'a> PhysicsData<'a> { // thing is in the comp::Scale for visual reasons let mut cpos = *pos; let wpos = cpos.0; + + // TODO: Cache the matrices here to avoid recomputing + let transform_from = Mat4::::translation_3d(pos_other.0 - wpos) * Mat4::from(ori_other.0) @@ -685,8 +689,21 @@ impl<'a> PhysicsData<'a> { let transform_to = transform_from.inverted(); let ori_from = Mat4::from(ori_other.0); let ori_to = ori_from.inverted(); + + // The velocity of the collider, taking into account orientation. + let wpos_rel = (Mat4::::translation_3d(pos_other.0) + * Mat4::from(ori_other.0) + * Mat4::::translation_3d(voxel_collider.translation)) + .inverted() + .mul_point(wpos); + let wpos_last = (Mat4::::translation_3d(pos_other.0) + * Mat4::from(previous_cache_other.ori) + * Mat4::::translation_3d(voxel_collider.translation)) + .mul_point(wpos_rel); + let vel_other = vel_other.0 + (wpos - wpos_last) / read.dt.0; + cpos.0 = transform_to.mul_point(Vec3::zero()); - vel.0 = ori_to.mul_direction(vel.0 - vel_other.0); + vel.0 = ori_to.mul_direction(vel.0 - vel_other); let cylinder = (radius, z_min, z_max); cylinder_voxel_collision( cylinder, @@ -696,7 +713,7 @@ impl<'a> PhysicsData<'a> { transform_to.mul_point(tgt_pos - wpos), &mut vel, &mut physics_state_delta, - ori_to.mul_direction(vel_other.0), + ori_to.mul_direction(vel_other), &read.dt, was_on_ground, block_snap, @@ -707,13 +724,13 @@ impl<'a> PhysicsData<'a> { ); cpos.0 = transform_from.mul_point(cpos.0) + wpos; - vel.0 = ori_from.mul_direction(vel.0) + vel_other.0; + vel.0 = ori_from.mul_direction(vel.0) + vel_other; tgt_pos = cpos.0; // union in the state updates, so that the state isn't just based on // the most recent terrain that collision was attempted with if physics_state_delta.on_ground { - physics_state.ground_vel = vel_other.0; + physics_state.ground_vel = vel_other; } physics_state.on_ground |= physics_state_delta.on_ground; physics_state.on_ceiling |= physics_state_delta.on_ceiling; @@ -776,6 +793,12 @@ impl<'a> PhysicsData<'a> { } } + for (ori, previous_phys_cache) in + (&write.orientations, &mut write.previous_phys_cache).join() + { + previous_phys_cache.ori = ori.0; + } + let mut event_emitter = read.event_bus.emitter(); land_on_grounds.into_iter().for_each(|(entity, vel)| { event_emitter.emit(ServerEvent::LandOnGround { entity, vel: vel.0 });