mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Address Imbris's MR 1888 comments, and add changelog entry.
- Use Ori::{new,to_quat} and make the field private. - Update/capitalize/add various comments. - Implicitly drop scope guards where applicable. - Take !Copy colliders by reference instead of cloning. - s/cylinder_voxel_collision/box_voxel_collision/ - Unindent some physics code with a continue.
This commit is contained in:
parent
1e9ee3d243
commit
9304ecab3d
@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Gave weapons critical strike {chance, multiplier} stats
|
||||
- A system to add glow and reflection effects to figures (i.e: characters, armour, weapons, etc.)
|
||||
- Merchants will trade wares with players
|
||||
- Airships that can be mounted and flown, and also walked on (`/airship` admin command)
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -141,15 +141,15 @@ impl InterpolatableComponent for Ori {
|
||||
return self;
|
||||
}
|
||||
let lerp_factor = 1.0 + ((t2 - t1) / (t1 - t0)) as f32;
|
||||
let mut out = Slerp::slerp_unclamped(p0.0, p1.0, lerp_factor);
|
||||
let mut out = Slerp::slerp_unclamped(p0.to_quat(), p1.to_quat(), lerp_factor);
|
||||
if out.into_vec4().map(|x| x.is_nan()).reduce_or() {
|
||||
warn!(
|
||||
"interpolation output is nan: {}, {}, {:?}",
|
||||
t2, lerp_factor, buf
|
||||
);
|
||||
out = p1.0;
|
||||
out = p1.to_quat();
|
||||
}
|
||||
|
||||
Ori(Slerp::slerp(self.0, out, PHYSICS_VS_EXTRAPOLATION_FACTOR).normalized())
|
||||
Ori::new(Slerp::slerp(self.to_quat(), out, PHYSICS_VS_EXTRAPOLATION_FACTOR).normalized())
|
||||
}
|
||||
}
|
||||
|
@ -90,8 +90,9 @@ pub mod figuredata {
|
||||
let mut colliders = HashMap::new();
|
||||
for (_, spec) in (manifest.read().0).0.iter() {
|
||||
for bone in [&spec.bone0, &spec.bone1, &spec.bone2].iter() {
|
||||
// TODO: avoid the requirement for symlinks in "voxygen.voxel.object.", and load
|
||||
// the models from "server.voxel." instead
|
||||
// TODO: Currently both client and server load models and manifests from
|
||||
// "server.voxel.". In order to support CSG procedural airships, we probably
|
||||
// need to load them in the server and sync them as an ECS resource.
|
||||
let vox =
|
||||
cache.load::<DotVoxAsset>(&["server.voxel.", &bone.central.0].concat())?;
|
||||
let dyna = Dyna::<Cell, (), ColumnAccess>::from_vox(&vox.read().0, false);
|
||||
@ -117,7 +118,7 @@ pub mod figuredata {
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
// TODO: load this from the ECS as a resource, and maybe make it more general than ships
|
||||
// TODO: Load this from the ECS as a resource, and maybe make it more general than ships
|
||||
// (although figuring out how to keep the figure bones in sync with the terrain offsets seems
|
||||
// like a hard problem if they're not the same manifest)
|
||||
pub static ref VOXEL_COLLIDER_MANIFEST: AssetHandle<ShipSpec> = AssetExt::load_expect("server.manifests.ship_manifest");
|
||||
|
@ -9,7 +9,7 @@ use vek::{Quaternion, Vec2, Vec3};
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(into = "SerdeOri")]
|
||||
#[serde(from = "SerdeOri")]
|
||||
pub struct Ori(pub Quaternion<f32>);
|
||||
pub struct Ori(Quaternion<f32>);
|
||||
|
||||
impl Default for Ori {
|
||||
/// Returns the default orientation (no rotation; default Dir)
|
||||
|
@ -174,6 +174,7 @@ impl Body {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns flying speed if the body type can fly, otherwise None
|
||||
pub fn can_fly(&self) -> Option<f32> {
|
||||
match self {
|
||||
Body::BirdMedium(_) | Body::Dragon(_) | Body::BirdSmall(_) => Some(1.0),
|
||||
|
@ -35,7 +35,7 @@ impl Cylinder {
|
||||
pub fn from_components(
|
||||
pos: Vec3<f32>,
|
||||
scale: Option<crate::comp::Scale>,
|
||||
collider: Option<crate::comp::Collider>,
|
||||
collider: Option<&crate::comp::Collider>,
|
||||
char_state: Option<&crate::comp::CharacterState>,
|
||||
) -> Self {
|
||||
let scale = scale.map_or(1.0, |s| s.0);
|
||||
|
@ -108,7 +108,7 @@ pub struct PhysicsData<'a> {
|
||||
impl<'a> PhysicsData<'a> {
|
||||
/// Add/reset physics state components
|
||||
fn reset(&mut self) {
|
||||
span!(guard, "Add/reset physics state components");
|
||||
span!(_guard, "Add/reset physics state components");
|
||||
for (entity, _, _, _, _) in (
|
||||
&self.read.entities,
|
||||
&self.read.colliders,
|
||||
@ -124,11 +124,10 @@ impl<'a> PhysicsData<'a> {
|
||||
.entry(entity)
|
||||
.map(|e| e.or_insert_with(Default::default));
|
||||
}
|
||||
drop(guard);
|
||||
}
|
||||
|
||||
fn maintain_pushback_cache(&mut self) {
|
||||
span!(guard, "Maintain pushback cache");
|
||||
span!(_guard, "Maintain pushback cache");
|
||||
//Add PreviousPhysCache for all relevant entities
|
||||
for entity in (
|
||||
&self.read.entities,
|
||||
@ -188,11 +187,10 @@ impl<'a> PhysicsData<'a> {
|
||||
phys_cache.scale = scale;
|
||||
phys_cache.scaled_radius = flat_radius;
|
||||
}
|
||||
drop(guard);
|
||||
}
|
||||
|
||||
fn apply_pushback(&mut self, job: &mut Job<Sys>) {
|
||||
span!(guard, "Apply pushback");
|
||||
span!(_guard, "Apply pushback");
|
||||
job.cpu_stats.measure(ParMode::Rayon);
|
||||
let PhysicsData {
|
||||
ref read,
|
||||
@ -368,7 +366,6 @@ impl<'a> PhysicsData<'a> {
|
||||
write.physics_metrics.entity_entity_collision_checks =
|
||||
metrics.entity_entity_collision_checks;
|
||||
write.physics_metrics.entity_entity_collisions = metrics.entity_entity_collisions;
|
||||
drop(guard);
|
||||
}
|
||||
|
||||
fn handle_movement_and_terrain(&mut self, job: &mut Job<Sys>) {
|
||||
@ -465,7 +462,7 @@ impl<'a> PhysicsData<'a> {
|
||||
_previous_cache,
|
||||
_,
|
||||
)| {
|
||||
// defer the writes of positions and velocities to allow an inner loop over
|
||||
// Defer the writes of positions and velocities to allow an inner loop over
|
||||
// terrain-like entities
|
||||
let mut vel = *vel;
|
||||
let old_vel = vel;
|
||||
@ -525,7 +522,7 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
let mut cpos = *pos;
|
||||
let cylinder = (radius, z_min, z_max);
|
||||
cylinder_voxel_collision(
|
||||
box_voxel_collision(
|
||||
cylinder,
|
||||
&*read.terrain,
|
||||
entity,
|
||||
@ -554,7 +551,7 @@ impl<'a> PhysicsData<'a> {
|
||||
|
||||
let cylinder = (radius, z_min, z_max);
|
||||
let mut cpos = *pos;
|
||||
cylinder_voxel_collision(
|
||||
box_voxel_collision(
|
||||
cylinder,
|
||||
&*read.terrain,
|
||||
entity,
|
||||
@ -668,99 +665,99 @@ impl<'a> PhysicsData<'a> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Collider::Voxel { id } = collider_other {
|
||||
// use bounding cylinder regardless of our collider
|
||||
// TODO: extract point-terrain collision above to its own function
|
||||
let radius = collider.get_radius();
|
||||
let (z_min, z_max) = collider.get_z_limits(1.0);
|
||||
let voxel_id = if let Collider::Voxel { id } = collider_other {
|
||||
id
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
// use bounding cylinder regardless of our collider
|
||||
// TODO: extract point-terrain collision above to its own function
|
||||
let radius = collider.get_radius();
|
||||
let (z_min, z_max) = collider.get_z_limits(1.0);
|
||||
|
||||
let radius = radius.min(0.45) * scale;
|
||||
let z_min = z_min * scale;
|
||||
let z_max = z_max.clamped(1.2, 1.95) * scale;
|
||||
let radius = radius.min(0.45) * scale;
|
||||
let z_min = z_min * scale;
|
||||
let z_max = z_max.clamped(1.2, 1.95) * scale;
|
||||
|
||||
if let Some(voxel_collider) =
|
||||
VOXEL_COLLIDER_MANIFEST.read().colliders.get(&*id)
|
||||
{
|
||||
let mut physics_state_delta = physics_state.clone();
|
||||
// deliberately don't use scale yet here, because the 11.0/0.8
|
||||
// thing is in the comp::Scale for visual reasons
|
||||
let mut cpos = *pos;
|
||||
let wpos = cpos.0;
|
||||
if let Some(voxel_collider) =
|
||||
VOXEL_COLLIDER_MANIFEST.read().colliders.get(&*voxel_id)
|
||||
{
|
||||
let mut physics_state_delta = physics_state.clone();
|
||||
// deliberately don't use scale yet here, because the 11.0/0.8
|
||||
// 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
|
||||
// TODO: Cache the matrices here to avoid recomputing
|
||||
|
||||
let transform_from =
|
||||
Mat4::<f32>::translation_3d(pos_other.0 - wpos)
|
||||
* Mat4::from(ori_other.0)
|
||||
* Mat4::<f32>::translation_3d(voxel_collider.translation);
|
||||
let transform_to = transform_from.inverted();
|
||||
let ori_from = Mat4::from(ori_other.0);
|
||||
let ori_to = ori_from.inverted();
|
||||
let transform_from = Mat4::<f32>::translation_3d(pos_other.0 - wpos)
|
||||
* Mat4::from(ori_other.to_quat())
|
||||
* Mat4::<f32>::translation_3d(voxel_collider.translation);
|
||||
let transform_to = transform_from.inverted();
|
||||
let ori_from = Mat4::from(ori_other.to_quat());
|
||||
let ori_to = ori_from.inverted();
|
||||
|
||||
// The velocity of the collider, taking into account orientation.
|
||||
let wpos_rel = (Mat4::<f32>::translation_3d(pos_other.0)
|
||||
* Mat4::from(ori_other.0)
|
||||
* Mat4::<f32>::translation_3d(voxel_collider.translation))
|
||||
.inverted()
|
||||
.mul_point(wpos);
|
||||
let wpos_last = (Mat4::<f32>::translation_3d(pos_other.0)
|
||||
* Mat4::from(previous_cache_other.ori)
|
||||
* Mat4::<f32>::translation_3d(voxel_collider.translation))
|
||||
.mul_point(wpos_rel);
|
||||
let vel_other = vel_other.0 + (wpos - wpos_last) / read.dt.0;
|
||||
// The velocity of the collider, taking into account orientation.
|
||||
let wpos_rel = (Mat4::<f32>::translation_3d(pos_other.0)
|
||||
* Mat4::from(ori_other.to_quat())
|
||||
* Mat4::<f32>::translation_3d(voxel_collider.translation))
|
||||
.inverted()
|
||||
.mul_point(wpos);
|
||||
let wpos_last = (Mat4::<f32>::translation_3d(pos_other.0)
|
||||
* Mat4::from(previous_cache_other.ori)
|
||||
* Mat4::<f32>::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);
|
||||
let cylinder = (radius, z_min, z_max);
|
||||
cylinder_voxel_collision(
|
||||
cylinder,
|
||||
&voxel_collider.dyna,
|
||||
entity,
|
||||
&mut cpos,
|
||||
transform_to.mul_point(tgt_pos - wpos),
|
||||
&mut vel,
|
||||
&mut physics_state_delta,
|
||||
ori_to.mul_direction(vel_other),
|
||||
&read.dt,
|
||||
was_on_ground,
|
||||
block_snap,
|
||||
climbing,
|
||||
|entity, vel| {
|
||||
land_on_grounds
|
||||
.push((entity, Vel(ori_from.mul_direction(vel.0))))
|
||||
},
|
||||
);
|
||||
cpos.0 = transform_to.mul_point(Vec3::zero());
|
||||
vel.0 = ori_to.mul_direction(vel.0 - vel_other);
|
||||
let cylinder = (radius, z_min, z_max);
|
||||
box_voxel_collision(
|
||||
cylinder,
|
||||
&voxel_collider.dyna,
|
||||
entity,
|
||||
&mut cpos,
|
||||
transform_to.mul_point(tgt_pos - wpos),
|
||||
&mut vel,
|
||||
&mut physics_state_delta,
|
||||
ori_to.mul_direction(vel_other),
|
||||
&read.dt,
|
||||
was_on_ground,
|
||||
block_snap,
|
||||
climbing,
|
||||
|entity, vel| {
|
||||
land_on_grounds
|
||||
.push((entity, Vel(ori_from.mul_direction(vel.0))))
|
||||
},
|
||||
);
|
||||
|
||||
cpos.0 = transform_from.mul_point(cpos.0) + wpos;
|
||||
vel.0 = ori_from.mul_direction(vel.0) + vel_other;
|
||||
tgt_pos = cpos.0;
|
||||
cpos.0 = transform_from.mul_point(cpos.0) + wpos;
|
||||
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;
|
||||
}
|
||||
physics_state.on_ground |= physics_state_delta.on_ground;
|
||||
physics_state.on_ceiling |= physics_state_delta.on_ceiling;
|
||||
physics_state.on_wall = physics_state.on_wall.or_else(|| {
|
||||
physics_state_delta
|
||||
.on_wall
|
||||
.map(|dir| ori_from.mul_direction(dir))
|
||||
});
|
||||
physics_state
|
||||
.touch_entities
|
||||
.append(&mut physics_state_delta.touch_entities);
|
||||
physics_state.in_liquid = match (
|
||||
physics_state.in_liquid,
|
||||
physics_state_delta.in_liquid,
|
||||
) {
|
||||
// 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;
|
||||
}
|
||||
physics_state.on_ground |= physics_state_delta.on_ground;
|
||||
physics_state.on_ceiling |= physics_state_delta.on_ceiling;
|
||||
physics_state.on_wall = physics_state.on_wall.or_else(|| {
|
||||
physics_state_delta
|
||||
.on_wall
|
||||
.map(|dir| ori_from.mul_direction(dir))
|
||||
});
|
||||
physics_state
|
||||
.touch_entities
|
||||
.append(&mut physics_state_delta.touch_entities);
|
||||
physics_state.in_liquid =
|
||||
match (physics_state.in_liquid, physics_state_delta.in_liquid) {
|
||||
// this match computes `x <|> y <|> liftA2 max x y`
|
||||
(Some(x), Some(y)) => Some(x.max(y)),
|
||||
(x @ Some(_), _) => x,
|
||||
(_, y @ Some(_)) => y,
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -804,7 +801,7 @@ impl<'a> PhysicsData<'a> {
|
||||
for (ori, previous_phys_cache) in
|
||||
(&write.orientations, &mut write.previous_phys_cache).join()
|
||||
{
|
||||
previous_phys_cache.ori = ori.0;
|
||||
previous_phys_cache.ori = ori.to_quat();
|
||||
}
|
||||
|
||||
let mut event_emitter = read.event_bus.emitter();
|
||||
@ -845,7 +842,7 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn cylinder_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
||||
fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
||||
cylinder: (f32, f32, f32),
|
||||
terrain: &'a T,
|
||||
entity: Entity,
|
||||
|
@ -69,7 +69,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
find_dist::Cylinder::from_components(
|
||||
p.0,
|
||||
scales.get(entity).copied(),
|
||||
colliders.get(entity).cloned(),
|
||||
colliders.get(entity),
|
||||
char_states.get(entity),
|
||||
)
|
||||
})
|
||||
|
@ -250,7 +250,7 @@ impl<'a> System<'a> for Sys {
|
||||
let mut comp_sync_package = CompSyncPackage::new();
|
||||
let mut throttle = true;
|
||||
|
||||
// extrapolation depends on receiving several frames indicating that something
|
||||
// Extrapolation depends on receiving several frames indicating that something
|
||||
// has stopped in order for the extrapolated value to have
|
||||
// stopped
|
||||
const SEND_UNCHANGED_PHYSICS_DATA: bool = true;
|
||||
|
@ -1562,7 +1562,7 @@ fn under_cursor(
|
||||
let player_cylinder = Cylinder::from_components(
|
||||
player_pos,
|
||||
scales.get(player_entity).copied(),
|
||||
colliders.get(player_entity).cloned(),
|
||||
colliders.get(player_entity),
|
||||
char_states.get(player_entity),
|
||||
);
|
||||
let terrain = client.state().terrain();
|
||||
@ -1643,7 +1643,7 @@ fn under_cursor(
|
||||
let target_cylinder = Cylinder::from_components(
|
||||
p,
|
||||
scales.get(*e).copied(),
|
||||
colliders.get(*e).cloned(),
|
||||
colliders.get(*e),
|
||||
char_states.get(*e),
|
||||
);
|
||||
|
||||
@ -1706,7 +1706,7 @@ fn select_interactable(
|
||||
let player_cylinder = Cylinder::from_components(
|
||||
player_pos,
|
||||
scales.get(player_entity).copied(),
|
||||
colliders.get(player_entity).cloned(),
|
||||
colliders.get(player_entity),
|
||||
char_states.get(player_entity),
|
||||
);
|
||||
|
||||
@ -1720,7 +1720,7 @@ fn select_interactable(
|
||||
.join()
|
||||
.filter(|(e, _, _, _, _)| *e != player_entity)
|
||||
.map(|(e, p, s, c, cs)| {
|
||||
let cylinder = Cylinder::from_components(p.0, s.copied(), c.cloned(), cs);
|
||||
let cylinder = Cylinder::from_components(p.0, s.copied(), c, cs);
|
||||
(e, cylinder)
|
||||
})
|
||||
// Roughly filter out entities farther than interaction distance
|
||||
|
Loading…
Reference in New Issue
Block a user