mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Parallelize spatial grid construction.
This solution may or may not actually work well. An incremental solution may be better.
This commit is contained in:
parent
46cd112928
commit
cc6d904c75
@ -71,6 +71,7 @@ petgraph = { version = "0.6", optional = true }
|
|||||||
kiddo = { version = "0.1", optional = true }
|
kiddo = { version = "0.1", optional = true }
|
||||||
|
|
||||||
# Data structures
|
# Data structures
|
||||||
|
dashmap = { version = "5.4.0", features = ["rayon"] }
|
||||||
hashbrown = { version = "0.12", features = ["rayon", "serde", "nightly"] }
|
hashbrown = { version = "0.12", features = ["rayon", "serde", "nightly"] }
|
||||||
slotmap = { version = "1.0", features = ["serde"] }
|
slotmap = { version = "1.0", features = ["serde"] }
|
||||||
indexmap = { version = "1.3.0", features = ["rayon"] }
|
indexmap = { version = "1.3.0", features = ["rayon"] }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::util::SpatialGrid;
|
use crate::util::{SpatialGrid, SpatialGridRef};
|
||||||
|
|
||||||
/// Cached [`SpatialGrid`] for reuse within different ecs systems during a tick.
|
/// Cached [`SpatialGrid`] for reuse within different ecs systems during a tick.
|
||||||
/// This is used to accelerate queries on entities within a specific area.
|
/// This is used to accelerate queries on entities within a specific area.
|
||||||
@ -6,7 +6,7 @@ use crate::util::SpatialGrid;
|
|||||||
/// positions are calculated for the tick. So any position modifications outside
|
/// positions are calculated for the tick. So any position modifications outside
|
||||||
/// the physics system will not be reflected here until the next tick when the
|
/// the physics system will not be reflected here until the next tick when the
|
||||||
/// physics system runs.
|
/// physics system runs.
|
||||||
pub struct CachedSpatialGrid(pub SpatialGrid);
|
pub struct CachedSpatialGrid(pub SpatialGridRef);
|
||||||
|
|
||||||
impl Default for CachedSpatialGrid {
|
impl Default for CachedSpatialGrid {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -14,7 +14,7 @@ impl Default for CachedSpatialGrid {
|
|||||||
let lg2_large_cell_size = 6; // 64
|
let lg2_large_cell_size = 6; // 64
|
||||||
let radius_cutoff = 8;
|
let radius_cutoff = 8;
|
||||||
|
|
||||||
let spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff);
|
let spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff).into_read_only();
|
||||||
|
|
||||||
Self(spatial_grid)
|
Self(spatial_grid)
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,4 @@ pub use dir::*;
|
|||||||
pub use option::either_with;
|
pub use option::either_with;
|
||||||
pub use plane::Plane;
|
pub use plane::Plane;
|
||||||
pub use projection::Projection;
|
pub use projection::Projection;
|
||||||
pub use spatial_grid::SpatialGrid;
|
pub use spatial_grid::{SpatialGrid, SpatialGridRef};
|
||||||
|
@ -1,29 +1,36 @@
|
|||||||
|
use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
pub type MapMut = dashmap::DashMap<Vec2<i32>, Vec<specs::Entity>>;
|
||||||
|
pub type MapRef = dashmap::ReadOnlyView<Vec2<i32>, Vec<specs::Entity>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpatialGrid {
|
pub struct SpatialGridInner<Map, Radius> {
|
||||||
// Uses two scales of grids so that we can have a hard limit on how far to search in the
|
/// Uses two scales of grids so that we can have a hard limit on how far to search in the
|
||||||
// smaller grid
|
/// smaller grid
|
||||||
grid: hashbrown::HashMap<Vec2<i32>, Vec<specs::Entity>>,
|
grid: Map,
|
||||||
large_grid: hashbrown::HashMap<Vec2<i32>, Vec<specs::Entity>>,
|
large_grid: Map,
|
||||||
// Log base 2 of the cell size of the spatial grid
|
/// Log base 2 of the cell size of the spatial grid
|
||||||
lg2_cell_size: usize,
|
lg2_cell_size: usize,
|
||||||
// Log base 2 of the cell size of the large spatial grid
|
/// Log base 2 of the cell size of the large spatial grid
|
||||||
lg2_large_cell_size: usize,
|
lg2_large_cell_size: usize,
|
||||||
// Entities with a radius over this value are store in the coarser large_grid
|
/// Entities with a radius over this value are store in the coarser large_grid
|
||||||
// This is the amount of buffer space we need to add when finding the intersections with cells
|
/// This is the amount of buffer space we need to add when finding the intersections with cells
|
||||||
// in the regular grid
|
/// in the regular grid
|
||||||
radius_cutoff: u32,
|
radius_cutoff: u32,
|
||||||
// Stores the largest radius of the entities in the large_grid
|
/// Stores the largest radius of the entities in the large_grid
|
||||||
// This is the amount of buffer space we need to add when finding the intersections with cells
|
/// This is the amount of buffer space we need to add when finding the intersections with cells
|
||||||
// in the larger grid
|
/// in the larger grid
|
||||||
// note: could explore some distance field type thing for querying whether there are large
|
/// note: could explore some distance field type thing for querying whether there are large
|
||||||
// entities nearby that necessitate expanding the cells searched for collision (and querying
|
/// entities nearby that necessitate expanding the cells searched for collision (and querying
|
||||||
// how much it needs to be expanded)
|
/// how much it needs to be expanded)
|
||||||
// TODO: log this to metrics?
|
/// TODO: log this to metrics?
|
||||||
largest_large_radius: u32,
|
largest_large_radius: Radius,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SpatialGrid = SpatialGridInner<MapMut, AtomicU32>;
|
||||||
|
pub type SpatialGridRef = SpatialGridInner<MapRef, u32>;
|
||||||
|
|
||||||
impl SpatialGrid {
|
impl SpatialGrid {
|
||||||
pub fn new(lg2_cell_size: usize, lg2_large_cell_size: usize, radius_cutoff: u32) -> Self {
|
pub fn new(lg2_cell_size: usize, lg2_large_cell_size: usize, radius_cutoff: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -32,28 +39,55 @@ impl SpatialGrid {
|
|||||||
lg2_cell_size,
|
lg2_cell_size,
|
||||||
lg2_large_cell_size,
|
lg2_large_cell_size,
|
||||||
radius_cutoff,
|
radius_cutoff,
|
||||||
largest_large_radius: radius_cutoff,
|
largest_large_radius: radius_cutoff.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an entity at the provided 2d pos into the spatial grid
|
/// Add an entity at the provided 2d pos into the spatial grid
|
||||||
pub fn insert(&mut self, pos: Vec2<i32>, radius: u32, entity: specs::Entity) {
|
pub fn insert(&self, pos: Vec2<i32>, radius: u32, entity: specs::Entity) {
|
||||||
if radius <= self.radius_cutoff {
|
if radius <= self.radius_cutoff {
|
||||||
let cell = pos.map(|e| e >> self.lg2_cell_size);
|
let cell = pos.map(|e| e >> self.lg2_cell_size);
|
||||||
self.grid.entry(cell).or_default().push(entity);
|
self.grid.entry(cell).or_default().push(entity);
|
||||||
} else {
|
} else {
|
||||||
let cell = pos.map(|e| e >> self.lg2_large_cell_size);
|
let cell = pos.map(|e| e >> self.lg2_large_cell_size);
|
||||||
self.large_grid.entry(cell).or_default().push(entity);
|
self.large_grid.entry(cell).or_default().push(entity);
|
||||||
self.largest_large_radius = self.largest_large_radius.max(radius);
|
// NOTE: Relaxed ordering is sufficient, because max is a monotonic function (for the
|
||||||
|
// duration of shared write access to the map; clear takes &mut so it's okay that it's
|
||||||
|
// not monotonic). We don't need to order this operation with anything else, either,
|
||||||
|
// because all interesting map operations require unique access to Self to perform,
|
||||||
|
// which axiomatically synchronizes with the end of all prior shared borrows.
|
||||||
|
//
|
||||||
|
// TODO: Verify that intrinsics lower intelligently to a priority update on CPUs (since
|
||||||
|
// the intrinsic seems targeted at GPUs).
|
||||||
|
self.largest_large_radius.fetch_max(radius, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_read_only(self) -> SpatialGridRef {
|
||||||
|
SpatialGridInner {
|
||||||
|
grid: self.grid.into_read_only(),
|
||||||
|
large_grid: self.large_grid.into_read_only(),
|
||||||
|
lg2_cell_size: self.lg2_cell_size,
|
||||||
|
lg2_large_cell_size: self.lg2_large_cell_size,
|
||||||
|
radius_cutoff: self.radius_cutoff,
|
||||||
|
largest_large_radius: self.largest_large_radius.into_inner(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.grid.clear();
|
||||||
|
self.large_grid.clear();
|
||||||
|
self.largest_large_radius = self.radius_cutoff.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpatialGridRef {
|
||||||
/// Get an iterator over the entities overlapping the provided axis aligned
|
/// Get an iterator over the entities overlapping the provided axis aligned
|
||||||
/// bounding region.
|
/// bounding region.
|
||||||
/// NOTE: for best optimization of the iterator use
|
/// NOTE: for best optimization of the iterator use
|
||||||
/// `for_each` rather than a for loop.
|
/// `for_each` rather than a for loop.
|
||||||
pub fn in_aabr<'a>(&'a self, aabr: Aabr<i32>) -> impl Iterator<Item = specs::Entity> + 'a {
|
pub fn in_aabr<'a>(&'a self, aabr: Aabr<i32>) -> impl Iterator<Item = specs::Entity> + 'a {
|
||||||
let iter = |max_entity_radius, grid: &'a hashbrown::HashMap<_, _>, lg2_cell_size| {
|
let iter = |max_entity_radius, grid: &'a MapRef, lg2_cell_size| {
|
||||||
// Add buffer for other entity radius
|
// Add buffer for other entity radius
|
||||||
let min = aabr.min - max_entity_radius as i32;
|
let min = aabr.min - max_entity_radius as i32;
|
||||||
let max = aabr.max + max_entity_radius as i32;
|
let max = aabr.max + max_entity_radius as i32;
|
||||||
@ -100,9 +134,14 @@ impl SpatialGrid {
|
|||||||
self.in_aabr(aabr)
|
self.in_aabr(aabr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn into_inner(self) -> SpatialGrid {
|
||||||
self.grid.clear();
|
SpatialGridInner {
|
||||||
self.large_grid.clear();
|
grid: self.grid.into_inner(),
|
||||||
self.largest_large_radius = self.radius_cutoff;
|
large_grid: self.large_grid.into_inner(),
|
||||||
|
lg2_cell_size: self.lg2_cell_size,
|
||||||
|
lg2_large_cell_size: self.lg2_large_cell_size,
|
||||||
|
radius_cutoff: self.radius_cutoff,
|
||||||
|
largest_large_radius: self.largest_large_radius.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
states,
|
states,
|
||||||
terrain::{Block, BlockKind, TerrainGrid},
|
terrain::{Block, BlockKind, TerrainGrid},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
util::{Projection, SpatialGrid},
|
util::{Projection, SpatialGrid, SpatialGridRef},
|
||||||
vol::{BaseVol, ReadVol},
|
vol::{BaseVol, ReadVol},
|
||||||
};
|
};
|
||||||
use common_base::{prof_span, span};
|
use common_base::{prof_span, span};
|
||||||
@ -146,37 +146,38 @@ impl<'a> PhysicsData<'a> {
|
|||||||
/// Add/reset physics state components
|
/// Add/reset physics state components
|
||||||
fn reset(&mut self) {
|
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.entities,
|
||||||
&self.read.colliders,
|
self.read.colliders.mask(),
|
||||||
&self.write.positions,
|
self.write.positions.mask(),
|
||||||
&self.write.velocities,
|
self.write.velocities.mask(),
|
||||||
&self.write.orientations,
|
self.write.orientations.mask(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
.for_each(|(entity, _, _, _, _)| {
|
||||||
let _ = self
|
let _ = self
|
||||||
.write
|
.write
|
||||||
.physics_states
|
.physics_states
|
||||||
.entry(entity)
|
.entry(entity)
|
||||||
.map(|e| e.or_insert_with(Default::default));
|
.map(|e| e.or_insert_with(Default::default));
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maintain_pushback_cache(&mut self) {
|
fn maintain_pushback_cache(&mut self) {
|
||||||
span!(_guard, "Maintain pushback cache");
|
span!(_guard, "Maintain pushback cache");
|
||||||
// Add PreviousPhysCache for all relevant entities
|
// Add PreviousPhysCache for all relevant entities
|
||||||
for entity in (
|
(
|
||||||
&self.read.entities,
|
&self.read.entities,
|
||||||
&self.read.colliders,
|
self.read.colliders.mask(),
|
||||||
&self.write.velocities,
|
self.write.velocities.mask(),
|
||||||
&self.write.positions,
|
self.write.positions.mask(),
|
||||||
!&self.write.previous_phys_cache,
|
!self.write.previous_phys_cache.mask(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.map(|(e, _, _, _, _)| e)
|
.map(|(e, _, _, _, _)| e)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
{
|
.into_iter()
|
||||||
|
.for_each(|entity| {
|
||||||
let _ = self
|
let _ = self
|
||||||
.write
|
.write
|
||||||
.previous_phys_cache
|
.previous_phys_cache
|
||||||
@ -191,11 +192,11 @@ impl<'a> PhysicsData<'a> {
|
|||||||
pos: None,
|
pos: None,
|
||||||
ori: Quaternion::identity(),
|
ori: Quaternion::identity(),
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
// Update PreviousPhysCache
|
// Update PreviousPhysCache
|
||||||
for (_, vel, position, ori, mut phys_cache, collider, scale, cs) in (
|
(
|
||||||
&self.read.entities,
|
/* &self.read.entities, */
|
||||||
&self.write.velocities,
|
&self.write.velocities,
|
||||||
&self.write.positions,
|
&self.write.positions,
|
||||||
&self.write.orientations,
|
&self.write.orientations,
|
||||||
@ -204,8 +205,9 @@ impl<'a> PhysicsData<'a> {
|
|||||||
self.read.scales.maybe(),
|
self.read.scales.maybe(),
|
||||||
self.read.char_states.maybe(),
|
self.read.char_states.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
{
|
.for_each(
|
||||||
|
|(/* _, */ vel, position, ori, mut phys_cache, collider, scale, cs)| {
|
||||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||||
let z_limits = calc_z_limit(cs, collider);
|
let z_limits = calc_z_limit(cs, collider);
|
||||||
let (z_min, z_max) = z_limits;
|
let (z_min, z_max) = z_limits;
|
||||||
@ -220,13 +222,16 @@ impl<'a> PhysicsData<'a> {
|
|||||||
// Move center to the middle between OLD and OLD+VEL_DT
|
// Move center to the middle between OLD and OLD+VEL_DT
|
||||||
// so that we can reduce the collision_boundary.
|
// so that we can reduce the collision_boundary.
|
||||||
phys_cache.center = entity_center + phys_cache.velocity_dt / 2.0;
|
phys_cache.center = entity_center + phys_cache.velocity_dt / 2.0;
|
||||||
phys_cache.collision_boundary = radius + (phys_cache.velocity_dt / 2.0).magnitude();
|
phys_cache.collision_boundary =
|
||||||
|
radius + (phys_cache.velocity_dt / 2.0).magnitude();
|
||||||
phys_cache.scale = scale;
|
phys_cache.scale = scale;
|
||||||
phys_cache.scaled_radius = flat_radius;
|
phys_cache.scaled_radius = flat_radius;
|
||||||
|
|
||||||
let neighborhood_radius = match collider {
|
let neighborhood_radius = match collider {
|
||||||
Collider::CapsulePrism { radius, .. } => radius * scale,
|
Collider::CapsulePrism { radius, .. } => radius * scale,
|
||||||
Collider::Voxel { .. } | Collider::Volume(_) | Collider::Point => flat_radius,
|
Collider::Voxel { .. } | Collider::Volume(_) | Collider::Point => {
|
||||||
|
flat_radius
|
||||||
|
},
|
||||||
};
|
};
|
||||||
phys_cache.neighborhood_radius = neighborhood_radius;
|
phys_cache.neighborhood_radius = neighborhood_radius;
|
||||||
|
|
||||||
@ -270,7 +275,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
};
|
};
|
||||||
phys_cache.origins = origins;
|
phys_cache.origins = origins;
|
||||||
phys_cache.ori = ori;
|
phys_cache.ori = ori;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_spatial_grid(&mut self) -> SpatialGrid {
|
fn construct_spatial_grid(&mut self) -> SpatialGrid {
|
||||||
@ -292,27 +298,28 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let lg2_cell_size = 5;
|
let lg2_cell_size = 5;
|
||||||
let lg2_large_cell_size = 6;
|
let lg2_large_cell_size = 6;
|
||||||
let radius_cutoff = 8;
|
let radius_cutoff = 8;
|
||||||
let mut spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff);
|
let spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff);
|
||||||
for (entity, pos, phys_cache, _, _) in (
|
(
|
||||||
&read.entities,
|
&read.entities,
|
||||||
&write.positions,
|
&write.positions,
|
||||||
&write.previous_phys_cache,
|
&write.previous_phys_cache,
|
||||||
write.velocities.mask(),
|
write.velocities.mask(),
|
||||||
!&read.projectiles, // Not needed because they are skipped in the inner loop below
|
!read.projectiles.mask(), /* Not needed because they are skipped in the inner loop
|
||||||
|
* below */
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
{
|
.for_each(|(entity, pos, phys_cache, _, _)| {
|
||||||
// Note: to not get too fine grained we use a 2D grid for now
|
// Note: to not get too fine grained we use a 2D grid for now
|
||||||
let radius_2d = phys_cache.scaled_radius.ceil() as u32;
|
let radius_2d = phys_cache.scaled_radius.ceil() as u32;
|
||||||
let pos_2d = pos.0.xy().map(|e| e as i32);
|
let pos_2d = pos.0.xy().map(|e| e as i32);
|
||||||
const POS_TRUNCATION_ERROR: u32 = 1;
|
const POS_TRUNCATION_ERROR: u32 = 1;
|
||||||
spatial_grid.insert(pos_2d, radius_2d + POS_TRUNCATION_ERROR, entity);
|
spatial_grid.insert(pos_2d, radius_2d + POS_TRUNCATION_ERROR, entity);
|
||||||
}
|
});
|
||||||
|
|
||||||
spatial_grid
|
spatial_grid
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_pushback(&mut self, job: &mut Job<Sys>, spatial_grid: &SpatialGrid) {
|
fn apply_pushback(&mut self, job: &mut Job<Sys>, spatial_grid: &SpatialGridRef) {
|
||||||
span!(_guard, "Apply pushback");
|
span!(_guard, "Apply pushback");
|
||||||
job.cpu_stats.measure(ParMode::Rayon);
|
job.cpu_stats.measure(ParMode::Rayon);
|
||||||
let PhysicsData {
|
let PhysicsData {
|
||||||
@ -529,16 +536,16 @@ impl<'a> PhysicsData<'a> {
|
|||||||
let lg2_cell_size = 7; // 128
|
let lg2_cell_size = 7; // 128
|
||||||
let lg2_large_cell_size = 8; // 256
|
let lg2_large_cell_size = 8; // 256
|
||||||
let radius_cutoff = 64;
|
let radius_cutoff = 64;
|
||||||
let mut spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff);
|
let spatial_grid = SpatialGrid::new(lg2_cell_size, lg2_large_cell_size, radius_cutoff);
|
||||||
// TODO: give voxel colliders their own component type
|
// TODO: give voxel colliders their own component type
|
||||||
for (entity, pos, collider, ori) in (
|
(
|
||||||
&read.entities,
|
&read.entities,
|
||||||
&write.positions,
|
&write.positions,
|
||||||
&read.colliders,
|
&read.colliders,
|
||||||
&write.orientations,
|
&write.orientations,
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
{
|
.for_each(|(entity, pos, collider, ori)| {
|
||||||
let vol = match collider {
|
let vol = match collider {
|
||||||
Collider::Voxel { id } => voxel_colliders_manifest.colliders.get(id),
|
Collider::Voxel { id } => voxel_colliders_manifest.colliders.get(id),
|
||||||
Collider::Volume(vol) => Some(&**vol),
|
Collider::Volume(vol) => Some(&**vol),
|
||||||
@ -552,7 +559,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
const POS_TRUNCATION_ERROR: u32 = 1;
|
const POS_TRUNCATION_ERROR: u32 = 1;
|
||||||
spatial_grid.insert(pos_2d, radius + POS_TRUNCATION_ERROR, entity);
|
spatial_grid.insert(pos_2d, radius + POS_TRUNCATION_ERROR, entity);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
spatial_grid
|
spatial_grid
|
||||||
}
|
}
|
||||||
@ -560,7 +567,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
fn handle_movement_and_terrain(
|
fn handle_movement_and_terrain(
|
||||||
&mut self,
|
&mut self,
|
||||||
job: &mut Job<Sys>,
|
job: &mut Job<Sys>,
|
||||||
voxel_collider_spatial_grid: &SpatialGrid,
|
voxel_collider_spatial_grid: &SpatialGridRef,
|
||||||
) {
|
) {
|
||||||
let PhysicsData {
|
let PhysicsData {
|
||||||
ref read,
|
ref read,
|
||||||
@ -610,7 +617,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
&write.physics_states,
|
&write.physics_states,
|
||||||
&read.masses,
|
&read.masses,
|
||||||
&read.densities,
|
&read.densities,
|
||||||
!&read.is_ridings,
|
!read.is_ridings.mask(),
|
||||||
)
|
)
|
||||||
.par_join()
|
.par_join()
|
||||||
.for_each_init(
|
.for_each_init(
|
||||||
@ -694,19 +701,19 @@ 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 (pos, ori, previous_phys_cache, _) in (
|
(
|
||||||
&write.positions,
|
&write.positions,
|
||||||
&write.orientations,
|
&write.orientations,
|
||||||
&mut write.previous_phys_cache,
|
&mut write.previous_phys_cache,
|
||||||
&read.colliders,
|
read.colliders.mask(),
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
{
|
.for_each(|(pos, ori, previous_phys_cache, _)| {
|
||||||
// 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.pos = Some(*pos);
|
||||||
previous_phys_cache.ori = ori.to_quat();
|
previous_phys_cache.ori = ori.to_quat();
|
||||||
}
|
});
|
||||||
drop(guard);
|
drop(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +721,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
job: &mut Job<Sys>,
|
job: &mut Job<Sys>,
|
||||||
read: &PhysicsRead,
|
read: &PhysicsRead,
|
||||||
write: &mut PhysicsWrite,
|
write: &mut PhysicsWrite,
|
||||||
voxel_collider_spatial_grid: &SpatialGrid,
|
voxel_collider_spatial_grid: &SpatialGridRef,
|
||||||
terrain_like_entities: bool,
|
terrain_like_entities: bool,
|
||||||
) {
|
) {
|
||||||
let (positions, velocities, previous_phys_cache, orientations) = (
|
let (positions, velocities, previous_phys_cache, orientations) = (
|
||||||
@ -1240,17 +1247,17 @@ impl<'a> PhysicsData<'a> {
|
|||||||
write.outcomes.emitter().emit_many(outcomes);
|
write.outcomes.emitter().emit_many(outcomes);
|
||||||
|
|
||||||
prof_span!(guard, "write deferred pos and vel");
|
prof_span!(guard, "write deferred pos and vel");
|
||||||
for (_, pos, vel, ori, pos_vel_ori_defer, _) in (
|
(
|
||||||
&read.entities,
|
/* &read.entities, */
|
||||||
&mut write.positions,
|
&mut write.positions,
|
||||||
&mut write.velocities,
|
&mut write.velocities,
|
||||||
&mut write.orientations,
|
&mut write.orientations,
|
||||||
&mut write.pos_vel_ori_defers,
|
&mut write.pos_vel_ori_defers,
|
||||||
&read.colliders,
|
&read.colliders,
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
.filter(|tuple| tuple.5.is_voxel() == terrain_like_entities)
|
.filter(|tuple| tuple./*5*/4.is_voxel() == terrain_like_entities)
|
||||||
{
|
.for_each(|(/* _, */ pos, vel, ori, pos_vel_ori_defer, _)| {
|
||||||
if let Some(new_pos) = pos_vel_ori_defer.pos.take() {
|
if let Some(new_pos) = pos_vel_ori_defer.pos.take() {
|
||||||
*pos = new_pos;
|
*pos = new_pos;
|
||||||
}
|
}
|
||||||
@ -1260,7 +1267,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
if let Some(new_ori) = pos_vel_ori_defer.ori.take() {
|
if let Some(new_ori) = pos_vel_ori_defer.ori.take() {
|
||||||
*ori = new_ori;
|
*ori = new_ori;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
drop(guard);
|
drop(guard);
|
||||||
|
|
||||||
let mut event_emitter = read.event_bus.emitter();
|
let mut event_emitter = read.event_bus.emitter();
|
||||||
@ -1276,7 +1283,11 @@ impl<'a> PhysicsData<'a> {
|
|||||||
ref mut write,
|
ref mut write,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let spatial_grid = &mut write.cached_spatial_grid.0;
|
// Borrow checker dance, since transferring away from a read only view requires
|
||||||
|
// &mut self.
|
||||||
|
let mut spatial_grid = core::mem::take(&mut *write.cached_spatial_grid)
|
||||||
|
.0
|
||||||
|
.into_inner();
|
||||||
spatial_grid.clear();
|
spatial_grid.clear();
|
||||||
(
|
(
|
||||||
&read.entities,
|
&read.entities,
|
||||||
@ -1284,7 +1295,7 @@ impl<'a> PhysicsData<'a> {
|
|||||||
read.scales.maybe(),
|
read.scales.maybe(),
|
||||||
read.colliders.maybe(),
|
read.colliders.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
.for_each(|(entity, pos, scale, collider)| {
|
.for_each(|(entity, pos, scale, collider)| {
|
||||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||||
let radius_2d =
|
let radius_2d =
|
||||||
@ -1293,6 +1304,8 @@ impl<'a> PhysicsData<'a> {
|
|||||||
const POS_TRUNCATION_ERROR: u32 = 1;
|
const POS_TRUNCATION_ERROR: u32 = 1;
|
||||||
spatial_grid.insert(pos_2d, radius_2d + POS_TRUNCATION_ERROR, entity);
|
spatial_grid.insert(pos_2d, radius_2d + POS_TRUNCATION_ERROR, entity);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
write.cached_spatial_grid.0 = spatial_grid.into_read_only();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1321,10 +1334,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
// entities.
|
// entities.
|
||||||
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().into_read_only();
|
||||||
physics_data.apply_pushback(job, &spatial_grid);
|
physics_data.apply_pushback(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()
|
||||||
|
.into_read_only();
|
||||||
physics_data.handle_movement_and_terrain(job, &voxel_collider_spatial_grid);
|
physics_data.handle_movement_and_terrain(job, &voxel_collider_spatial_grid);
|
||||||
|
|
||||||
// Spatial grid used by other systems
|
// Spatial grid used by other systems
|
||||||
|
Loading…
Reference in New Issue
Block a user