mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
More voxel collision speedups by reducing the common cases from 5 to 3 voxel iterations
This commit is contained in:
parent
87883d9b11
commit
9fb44e5674
@ -77,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Overhauled the sceptre
|
- Overhauled the sceptre
|
||||||
- Make the /time command relative to the current day
|
- Make the /time command relative to the current day
|
||||||
- Spatial partitioning via a grid for entity versus entity collisions was added which can more than halve the total tick time at higher entity counts (> ~1000)
|
- Spatial partitioning via a grid for entity versus entity collisions was added which can more than halve the total tick time at higher entity counts (> ~1000)
|
||||||
|
- Improved efficency of entity versus terrain collisions (they now take less than half the time)
|
||||||
- The loading screen will now display random animations
|
- The loading screen will now display random animations
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5634,6 +5634,7 @@ dependencies = [
|
|||||||
"bincode",
|
"bincode",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"ordered-float 2.1.1",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
|
@ -21,6 +21,7 @@ rand = "0.8"
|
|||||||
rayon = "1.5"
|
rayon = "1.5"
|
||||||
tracing = { version = "0.1", default-features = false }
|
tracing = { version = "0.1", default-features = false }
|
||||||
vek = { version = "=0.14.1", features = ["serde"] }
|
vek = { version = "=0.14.1", features = ["serde"] }
|
||||||
|
ordered-float = { version = "2.0.1", default-features = false }
|
||||||
|
|
||||||
# Data structures
|
# Data structures
|
||||||
hashbrown = { version = "0.9", features = ["rayon", "serde", "nightly"] }
|
hashbrown = { version = "0.9", features = ["rayon", "serde", "nightly"] }
|
||||||
|
@ -1162,57 +1162,54 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
const MAX_ATTEMPTS: usize = 16;
|
const MAX_ATTEMPTS: usize = 16;
|
||||||
|
|
||||||
// While the player is colliding with the terrain...
|
// While the player is colliding with the terrain...
|
||||||
while collision_with(
|
while let Some((_block_pos, block_aabb, block_height)) =
|
||||||
pos.0,
|
(attempts < MAX_ATTEMPTS).then(|| {
|
||||||
&terrain,
|
// Calculate the player's AABB
|
||||||
block_true,
|
let player_aabb = Aabb {
|
||||||
near_iter.clone(),
|
min: pos.0 + Vec3::new(-radius, -radius, z_min),
|
||||||
radius,
|
max: pos.0 + Vec3::new(radius, radius, z_max),
|
||||||
z_range.clone(),
|
};
|
||||||
) && attempts < MAX_ATTEMPTS
|
|
||||||
{
|
|
||||||
// Calculate the player's AABB
|
|
||||||
let player_aabb = Aabb {
|
|
||||||
min: pos.0 + Vec3::new(-radius, -radius, z_min),
|
|
||||||
max: pos.0 + Vec3::new(radius, radius, z_max),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine the block that we are colliding with most (based on minimum
|
// Determine the block that we are colliding with most (based on minimum
|
||||||
// collision axis)
|
// collision axis) (if we are colliding with one)
|
||||||
let (_block_pos, block_aabb, block_height) = near_iter
|
near_iter
|
||||||
.clone()
|
.clone()
|
||||||
// Calculate the block's position in world space
|
// Calculate the block's position in world space
|
||||||
.map(|(i, j, k)| pos.0.map(|e| e.floor() as i32) + Vec3::new(i, j, k))
|
.map(|(i, j, k)| pos.0.map(|e| e.floor() as i32) + Vec3::new(i, j, k))
|
||||||
// Make sure the block is actually solid
|
// Make sure the block is actually solid
|
||||||
.filter_map(|block_pos| {
|
.filter_map(|block_pos| {
|
||||||
if let Some(block) = terrain
|
terrain
|
||||||
.get(block_pos)
|
.get(block_pos)
|
||||||
.ok()
|
.ok()
|
||||||
.filter(|block| block.is_solid())
|
.filter(|block| block.is_solid())
|
||||||
{
|
.map(|block| (block_pos, block))
|
||||||
// Calculate block AABB
|
})
|
||||||
Some((
|
// Calculate block AABB
|
||||||
|
.map(|(block_pos, block)| {
|
||||||
|
(
|
||||||
block_pos,
|
block_pos,
|
||||||
Aabb {
|
Aabb {
|
||||||
min: block_pos.map(|e| e as f32),
|
min: block_pos.map(|e| e as f32),
|
||||||
max: block_pos.map(|e| e as f32) + Vec3::new(1.0, 1.0, block.solid_height()),
|
max: block_pos.map(|e| e as f32) + Vec3::new(1.0, 1.0, block.solid_height()),
|
||||||
},
|
},
|
||||||
block.solid_height(),
|
block.solid_height(),
|
||||||
))
|
)
|
||||||
} else {
|
})
|
||||||
None
|
// Determine whether the block's AABB collides with the player's AABB
|
||||||
}
|
.filter(|(_, block_aabb, _)| block_aabb.collides_with_aabb(player_aabb))
|
||||||
})
|
// Find the maximum of the minimum collision axes (this bit is weird, trust me that it works)
|
||||||
// Determine whether the block's AABB collides with the player's AABB
|
.min_by_key(|(_, block_aabb, _)| {
|
||||||
.filter(|(_, block_aabb, _)| block_aabb.collides_with_aabb(player_aabb))
|
ordered_float::OrderedFloat((block_aabb.center() - player_aabb.center() - Vec3::unit_z() * 0.5)
|
||||||
// Find the maximum of the minimum collision axes (this bit is weird, trust me that it works)
|
.map(f32::abs)
|
||||||
.min_by_key(|(_, block_aabb, _)| {
|
.sum())
|
||||||
((block_aabb.center() - player_aabb.center() - Vec3::unit_z() * 0.5)
|
})
|
||||||
.map(|e| e.abs())
|
}).flatten()
|
||||||
.sum()
|
{
|
||||||
* 1_000_000.0) as i32
|
// Calculate the player's AABB
|
||||||
})
|
let player_aabb = Aabb {
|
||||||
.expect("Collision detected, but no colliding blocks found!");
|
min: pos.0 + Vec3::new(-radius, -radius, z_min),
|
||||||
|
max: pos.0 + Vec3::new(radius, radius, z_max),
|
||||||
|
};
|
||||||
|
|
||||||
// Find the intrusion vector of the collision
|
// Find the intrusion vector of the collision
|
||||||
let dir = player_aabb.collision_vector_with_aabb(block_aabb);
|
let dir = player_aabb.collision_vector_with_aabb(block_aabb);
|
||||||
@ -1243,12 +1240,12 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When the resolution direction is non-vertical, we must be colliding
|
// When the resolution direction is non-vertical, we must be colliding
|
||||||
// with a wall If the space above is free...
|
// with a wall If we're being pushed out horizontally...
|
||||||
if !collision_with(Vec3::new(pos.0.x, pos.0.y, (pos.0.z + 0.1).ceil()), &terrain, block_true, near_iter.clone(), radius, z_range.clone())
|
if resolve_dir.z == 0.0
|
||||||
// ...and we're being pushed out horizontally...
|
|
||||||
&& resolve_dir.z == 0.0
|
|
||||||
// ...and the vertical resolution direction is sufficiently great...
|
// ...and the vertical resolution direction is sufficiently great...
|
||||||
&& dir.z < -0.1
|
&& dir.z < -0.1
|
||||||
|
// ...and the space above is free...
|
||||||
|
&& !collision_with(Vec3::new(pos.0.x, pos.0.y, (pos.0.z + 0.1).ceil()), &terrain, block_true, near_iter.clone(), radius, z_range.clone())
|
||||||
// ...and we're falling/standing OR there is a block *directly* beneath our current origin (note: not hitbox)...
|
// ...and we're falling/standing OR there is a block *directly* beneath our current origin (note: not hitbox)...
|
||||||
// && terrain
|
// && terrain
|
||||||
// .get((pos.0 - Vec3::unit_z() * 0.1).map(|e| e.floor() as i32))
|
// .get((pos.0 - Vec3::unit_z() * 0.1).map(|e| e.floor() as i32))
|
||||||
@ -1323,18 +1320,18 @@ fn box_voxel_collision<'a, T: BaseVol<Vox = Block> + ReadVol>(
|
|||||||
physics_state.on_ground = true;
|
physics_state.on_ground = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let player_aabb = Aabb {
|
||||||
|
min: pos.0 + Vec3::new(-radius, -radius, z_range.start),
|
||||||
|
max: pos.0 + Vec3::new(radius, radius, z_range.end),
|
||||||
|
};
|
||||||
|
let player_voxel_pos = pos.0.map(|e| e.floor() as i32);
|
||||||
|
|
||||||
let dirs = [
|
let dirs = [
|
||||||
Vec3::unit_x(),
|
Vec3::unit_x(),
|
||||||
Vec3::unit_y(),
|
Vec3::unit_y(),
|
||||||
-Vec3::unit_x(),
|
-Vec3::unit_x(),
|
||||||
-Vec3::unit_y(),
|
-Vec3::unit_y(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let player_aabb = Aabb {
|
|
||||||
min: pos.0 + Vec3::new(-radius, -radius, z_range.start),
|
|
||||||
max: pos.0 + Vec3::new(radius, radius, z_range.end),
|
|
||||||
};
|
|
||||||
let player_voxel_pos = pos.0.map(|e| e.floor() as i32);
|
|
||||||
let player_wall_aabbs = dirs.map(|dir| {
|
let player_wall_aabbs = dirs.map(|dir| {
|
||||||
let pos = pos.0 + dir * 0.01;
|
let pos = pos.0 + dir * 0.01;
|
||||||
Aabb {
|
Aabb {
|
||||||
|
Loading…
Reference in New Issue
Block a user