mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
WIP fix collision
This commit is contained in:
parent
12f546a075
commit
6d4bf431a3
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2415,6 +2415,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inline_tweak"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7033e97b20277cc0d043226d1940fa7719ff08d2305d1fc7421e53066d00eb4b"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inotify"
|
name = "inotify"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -5633,6 +5642,7 @@ version = "0.9.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"inline_tweak",
|
||||||
"ordered-float 2.1.1",
|
"ordered-float 2.1.1",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
@ -31,4 +31,4 @@ slab = "0.4.2"
|
|||||||
specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control", "derive"], rev = "5a9b71035007be0e3574f35184acac1cd4530496" }
|
specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control", "derive"], rev = "5a9b71035007be0e3574f35184acac1cd4530496" }
|
||||||
|
|
||||||
# Tweak running code
|
# Tweak running code
|
||||||
# inline_tweak = { version = "1.0.8", features = ["release_tweak"] }
|
inline_tweak = { version = "1.0.8", features = ["release_tweak"] }
|
||||||
|
@ -13,7 +13,7 @@ use common::{
|
|||||||
states,
|
states,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
util::{Projection, SpatialGrid},
|
util::{Dir, Plane, Projection, SpatialGrid},
|
||||||
vol::{BaseVol, ReadVol},
|
vol::{BaseVol, ReadVol},
|
||||||
};
|
};
|
||||||
use common_base::{prof_span, span};
|
use common_base::{prof_span, span};
|
||||||
@ -27,6 +27,46 @@ use specs::{
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
enum CollisionKind {
|
||||||
|
Inelastic, // when coefficient of restitution is zero
|
||||||
|
Elastic, // when coefficient of restitution is 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collision between two objects, resulting in a change in their respective
|
||||||
|
/// trajectories.
|
||||||
|
fn collision(
|
||||||
|
(mass, vel): (&Mass, Vel),
|
||||||
|
(mass_other, vel_other): (&Mass, Vel),
|
||||||
|
collision_kind: CollisionKind, // coefficient_of_restitution: f32,
|
||||||
|
collision_normal: Dir,
|
||||||
|
) -> (Vel, Vel) {
|
||||||
|
let (m1, m2) = (mass.0, mass_other.0);
|
||||||
|
let (v1, v2) = (vel.0, vel_other.0);
|
||||||
|
// velocities projected along the collision normal
|
||||||
|
let (u1, u2) = (
|
||||||
|
v1.projected(&collision_normal),
|
||||||
|
v2.projected(&collision_normal),
|
||||||
|
);
|
||||||
|
match collision_kind {
|
||||||
|
CollisionKind::Inelastic => {
|
||||||
|
// Breaks conservation of energy as we do not account for internal heat or
|
||||||
|
// deformation
|
||||||
|
let v = (m1 * u1 + m2 * u2) / (m1 + m2);
|
||||||
|
(Vel(v1 - u1 + v), Vel(v2 - u2 + v))
|
||||||
|
// (Vel(v + vp1), Vel(v + vp2))
|
||||||
|
},
|
||||||
|
|
||||||
|
CollisionKind::Elastic => {
|
||||||
|
// combined mass
|
||||||
|
let m = m1 + m2;
|
||||||
|
(
|
||||||
|
Vel(v1 - u1 + ((m1 - m2) * u1 + 2.0 * m2 * u2) / m),
|
||||||
|
Vel(v2 - u2 + ((m2 - m1) * u2 + 2.0 * m1 * u1) / m),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The density of the fluid as a function of submersion ratio in given fluid
|
/// The density of the fluid as a function of submersion ratio in given fluid
|
||||||
/// where it is assumed that any unsubmersed part is is air.
|
/// where it is assumed that any unsubmersed part is is air.
|
||||||
// TODO: Better suited partial submersion curve?
|
// TODO: Better suited partial submersion curve?
|
||||||
@ -305,7 +345,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::nonminimal_bool)]
|
#[allow(clippy::nonminimal_bool)]
|
||||||
fn apply_pushback(&mut self, job: &mut Job<Sys>, spatial_grid: &SpatialGrid) {
|
fn collide_entities(&mut self, job: &mut Job<Sys>, spatial_grid: &SpatialGrid) {
|
||||||
span!(_guard, "Apply pushback");
|
span!(_guard, "Apply pushback");
|
||||||
job.cpu_stats.measure(ParMode::Rayon);
|
job.cpu_stats.measure(ParMode::Rayon);
|
||||||
let PhysicsData {
|
let PhysicsData {
|
||||||
@ -372,7 +412,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
|
|
||||||
let is_projectile = projectile.is_some();
|
let is_projectile = projectile.is_some();
|
||||||
|
|
||||||
let mut vel_delta = Vec3::zero();
|
// let initial_vel = vel.clone();
|
||||||
|
|
||||||
let query_center = previous_cache.center.xy();
|
let query_center = previous_cache.center.xy();
|
||||||
let query_radius = previous_cache.collision_boundary;
|
let query_radius = previous_cache.collision_boundary;
|
||||||
@ -390,6 +430,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
entity,
|
entity,
|
||||||
uid,
|
uid,
|
||||||
pos,
|
pos,
|
||||||
|
// write.velocities.get(entity),
|
||||||
previous_cache,
|
previous_cache,
|
||||||
mass,
|
mass,
|
||||||
read.colliders.get(entity),
|
read.colliders.get(entity),
|
||||||
@ -402,6 +443,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
entity_other,
|
entity_other,
|
||||||
other,
|
other,
|
||||||
pos_other,
|
pos_other,
|
||||||
|
// vel_other,
|
||||||
previous_cache_other,
|
previous_cache_other,
|
||||||
mass_other,
|
mass_other,
|
||||||
collider_other,
|
collider_other,
|
||||||
@ -457,15 +499,14 @@ impl<'a> PhysicsData<'a> {
|
|||||||
entity_entity_collisions += 1;
|
entity_entity_collisions += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't apply repulsive force to projectiles or if
|
// Don't apply repulsive force to projectiles or if we're
|
||||||
// we're
|
// colliding with a terrain-like entity, or if we are a
|
||||||
// colliding
|
// terrain-like entity
|
||||||
// with a terrain-like entity, or if we are a
|
|
||||||
// terrain-like
|
|
||||||
// entity
|
|
||||||
//
|
//
|
||||||
// Don't apply force when entity is a sticky which is on the
|
// Don't apply force when entity is a sticky which is on the
|
||||||
// ground (or on the wall)
|
// ground (or on the wall)
|
||||||
|
//
|
||||||
|
// Don't collide entities moving away from each other
|
||||||
if !(is_sticky && !is_mid_air)
|
if !(is_sticky && !is_mid_air)
|
||||||
&& diff.magnitude_squared() > 0.0
|
&& diff.magnitude_squared() > 0.0
|
||||||
&& !is_projectile
|
&& !is_projectile
|
||||||
@ -475,13 +516,48 @@ impl<'a> PhysicsData<'a> {
|
|||||||
)
|
)
|
||||||
&& !matches!(collider, Some(Collider::Voxel { .. }))
|
&& !matches!(collider, Some(Collider::Voxel { .. }))
|
||||||
{
|
{
|
||||||
let force = 400.0
|
let rel_mv_dir = Dir::from_unnormalized(
|
||||||
* (collision_dist - diff.magnitude())
|
previous_cache.velocity_dt
|
||||||
* mass_other.0
|
- previous_cache_other.velocity_dt,
|
||||||
/ (mass.0 + mass_other.0);
|
);
|
||||||
|
let dir_from_other =
|
||||||
|
Dir::from_unnormalized(pos - pos_other)
|
||||||
|
.or(rel_mv_dir);
|
||||||
|
let d = rel_mv_dir
|
||||||
|
.and_then(|rel_vel| {
|
||||||
|
Some(rel_vel.dot(*dir_from_other?))
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
vel_delta +=
|
if d < inline_tweak::tweak!(-0.01) {
|
||||||
Vec3::from(diff.normalized()) * force * step_delta;
|
// temp hack to avoid refactor
|
||||||
|
let vel_other = Vel(previous_cache_other
|
||||||
|
.velocity_dt
|
||||||
|
/ read.dt.0.max(0.001));
|
||||||
|
// Change velocity
|
||||||
|
vel.0 = collision(
|
||||||
|
(mass, *vel),
|
||||||
|
(mass_other, vel_other),
|
||||||
|
CollisionKind::Inelastic,
|
||||||
|
dir_from_other.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushback
|
||||||
|
if inline_tweak::tweak!(false) {
|
||||||
|
let speed: f32 = inline_tweak::tweak!(10.0);
|
||||||
|
let overlap = collision_dist - diff.magnitude();
|
||||||
|
// let a: f32 = inline_tweak::tweak!(-1.0);
|
||||||
|
if overlap.is_sign_positive() {
|
||||||
|
vel.0 += *dir_from_other.unwrap_or_default()
|
||||||
|
* speed
|
||||||
|
* mass_other.0
|
||||||
|
/ (mass.0 + mass_other.0)
|
||||||
|
* step_delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collided = true;
|
collided = true;
|
||||||
@ -490,8 +566,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Change velocity
|
// vel.0 = vel_;
|
||||||
vel.0 += vel_delta * read.dt.0;
|
|
||||||
|
|
||||||
// Metrics
|
// Metrics
|
||||||
PhysicsMetrics {
|
PhysicsMetrics {
|
||||||
@ -1212,7 +1287,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
physics_data.maintain_pushback_cache();
|
physics_data.maintain_pushback_cache();
|
||||||
|
|
||||||
let spatial_grid = physics_data.construct_spatial_grid();
|
let spatial_grid = physics_data.construct_spatial_grid();
|
||||||
physics_data.apply_pushback(job, &spatial_grid);
|
physics_data.collide_entities(job, &spatial_grid);
|
||||||
|
|
||||||
let voxel_collider_spatial_grid = physics_data.construct_voxel_collider_spatial_grid();
|
let voxel_collider_spatial_grid = physics_data.construct_voxel_collider_spatial_grid();
|
||||||
physics_data.handle_movement_and_terrain(job, &voxel_collider_spatial_grid);
|
physics_data.handle_movement_and_terrain(job, &voxel_collider_spatial_grid);
|
||||||
|
Loading…
Reference in New Issue
Block a user