Skip to content

Commit c8bae14

Browse files
authored
feat: make the voxels shape use a sparse internal storage (#380)
* feat: make the voxels shape use a sparse internal storage * fix compilation of docs and examples * chore: cargo fmt
1 parent 7d81b18 commit c8bae14

22 files changed

Lines changed: 1986 additions & 1619 deletions

crates/parry2d-f64/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ dim2 = []
3636
f64 = []
3737
serde-serialize = [
3838
"serde",
39+
"serde_arrays",
3940
"nalgebra/serde-serialize",
4041
"arrayvec/serde",
4142
"bitflags/serde",
@@ -73,9 +74,10 @@ num-traits = { version = "0.2", default-features = false }
7374
slab = { version = "0.4", optional = true }
7475
arrayvec = { version = "0.7", default-features = false }
7576
simba = { version = "0.9", default-features = false }
76-
nalgebra = { version = "0.34", default-features = false, features = ["libm"] }
77+
nalgebra = { version = "0.34", default-features = false, features = ["libm", "macros"] }
7778
approx = { version = "0.5", default-features = false }
7879
serde = { version = "1.0", optional = true, features = ["derive"] }
80+
serde_arrays = { version = "0.2", optional = true }
7981
rkyv = { version = "0.7.41", optional = true }
8082
num-derive = "0.4"
8183
indexmap = { version = "2", features = ["serde"], optional = true }

crates/parry2d/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ dim2 = []
3636
f32 = []
3737
serde-serialize = [
3838
"serde",
39+
"serde_arrays",
3940
"nalgebra/serde-serialize",
4041
"arrayvec/serde",
4142
"bitflags/serde",
@@ -73,9 +74,10 @@ num-traits = { version = "0.2", default-features = false }
7374
slab = { version = "0.4", optional = true }
7475
arrayvec = { version = "0.7", default-features = false }
7576
simba = { version = "0.9", default-features = false }
76-
nalgebra = { version = "0.34", default-features = false, features = ["libm"] }
77+
nalgebra = { version = "0.34", default-features = false, features = ["libm", "macros"] }
7778
approx = { version = "0.5", default-features = false }
7879
serde = { version = "1.0", optional = true, features = ["derive"] }
80+
serde_arrays = { version = "0.2", optional = true }
7981
rkyv = { version = "0.7.41", optional = true }
8082
num-derive = "0.4"
8183
indexmap = { version = "2", features = ["serde"], optional = true }

crates/parry3d-f64/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dim3 = []
3535
f64 = []
3636
serde-serialize = [
3737
"serde",
38+
"serde_arrays",
3839
"nalgebra/serde-serialize",
3940
"bitflags/serde",
4041
"hashbrown?/serde",
@@ -73,9 +74,10 @@ num-traits = { version = "0.2", default-features = false }
7374
slab = { version = "0.4", optional = true }
7475
arrayvec = { version = "0.7", default-features = false }
7576
simba = { version = "0.9", default-features = false }
76-
nalgebra = { version = "0.34", default-features = false, features = ["libm"] }
77+
nalgebra = { version = "0.34", default-features = false, features = ["libm", "macros"] }
7778
approx = { version = "0.5", default-features = false }
7879
serde = { version = "1.0", optional = true, features = ["derive", "rc"] }
80+
serde_arrays = { version = "0.2", optional = true }
7981
rkyv = { version = "0.7.41", optional = true }
8082
num-derive = "0.4"
8183
indexmap = { version = "2", features = ["serde"], optional = true }

crates/parry3d/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dim3 = []
3535
f32 = []
3636
serde-serialize = [
3737
"serde",
38+
"serde_arrays",
3839
"nalgebra/serde-serialize",
3940
"bitflags/serde",
4041
"hashbrown?/serde",
@@ -74,9 +75,10 @@ num-traits = { version = "0.2", default-features = false }
7475
slab = { version = "0.4", optional = true }
7576
arrayvec = { version = "0.7", default-features = false }
7677
simba = { version = "0.9", default-features = false }
77-
nalgebra = { version = "0.34", default-features = false, features = ["libm"] }
78+
nalgebra = { version = "0.34", default-features = false, features = ["libm", "macros"] }
7879
approx = { version = "0.5", default-features = false }
7980
serde = { version = "1.0", optional = true, features = ["derive", "rc"] }
81+
serde_arrays = { version = "0.2", optional = true }
8082
rkyv = { version = "0.7.41", optional = true }
8183
num-derive = "0.4"
8284
indexmap = { version = "2", features = ["serde"], optional = true }

src/bounding_volume/aabb_voxels.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
use crate::bounding_volume::Aabb;
2-
use crate::math::{Isometry, Real, Translation};
3-
use crate::shape::{Cuboid, Voxels};
2+
use crate::math::{Isometry, Real};
3+
use crate::shape::Voxels;
44

55
impl Voxels {
66
/// Computes the world-space Aabb of this set of voxels, transformed by `pos`.
77
#[inline]
88
pub fn aabb(&self, pos: &Isometry<Real>) -> Aabb {
9-
let shift = Translation::from(self.domain_center());
10-
Cuboid::new(self.extents() / 2.0).aabb(&(pos * shift))
9+
self.chunk_bvh().root_aabb().transform_by(pos)
1110
}
1211

1312
/// Computes the local-space Aabb of this set of voxels.
1413
#[inline]
1514
pub fn local_aabb(&self) -> Aabb {
16-
Cuboid::new(self.extents() / 2.0)
17-
.local_aabb()
18-
.translated(&self.domain_center().coords)
15+
self.chunk_bvh().root_aabb()
1916
}
2017
}
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
use crate::bounding_volume::BoundingSphere;
2-
use crate::math::{Isometry, Real, Translation};
3-
use crate::shape::{Cuboid, Voxels};
2+
use crate::math::{Isometry, Real};
3+
use crate::shape::Voxels;
44

55
impl Voxels {
66
/// Computes the world-space bounding sphere of this set of voxels, transformed by `pos`.
77
#[inline]
88
pub fn bounding_sphere(&self, pos: &Isometry<Real>) -> BoundingSphere {
9-
let shift = Translation::from(self.domain_center().coords);
10-
Cuboid::new(self.extents() / 2.0).bounding_sphere(&(pos * shift))
9+
self.local_aabb().bounding_sphere().transform_by(pos)
1110
}
1211

1312
/// Computes the local-space bounding sphere of this set of voxels.
1413
#[inline]
1514
pub fn local_bounding_sphere(&self) -> BoundingSphere {
16-
Cuboid::new(self.extents() / 2.0)
17-
.local_bounding_sphere()
18-
.translated(&(self.domain_center().coords))
15+
self.local_aabb().bounding_sphere()
1916
}
2017
}

src/partitioning/bvh/bvh_queries.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::math::Point;
44
use crate::math::Real;
55
use crate::query::PointProjection;
66
use crate::query::{PointQuery, Ray};
7+
use crate::shape::FeatureId;
78

89
#[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
910
pub(super) struct SimdInvRay {
@@ -59,6 +60,30 @@ impl Bvh {
5960
)
6061
}
6162

63+
/// Projects a point on this BVH using the provided leaf projection function.
64+
///
65+
/// Also returns the feature the point was projected on.
66+
///
67+
/// The `primitive_check` delegates the point-projection task to an external function that
68+
/// is assumed to map a leaf index to an actual geometry to project on. The `Real` argument
69+
/// given to that closure is the distance to the closest point found so far (or is equal to
70+
/// `max_distance` if no projection was found so far).
71+
pub fn project_point_and_get_feature(
72+
&self,
73+
point: &Point<Real>,
74+
max_distance: Real,
75+
primitive_check: impl Fn(u32, Real) -> Option<(PointProjection, FeatureId)>,
76+
) -> Option<(u32, (Real, (PointProjection, FeatureId)))> {
77+
self.find_best(
78+
max_distance,
79+
|node: &BvhNode, _| node.aabb().distance_to_local_point(point, true),
80+
|primitive, _| {
81+
let proj = primitive_check(primitive, max_distance)?;
82+
Some((na::distance(&proj.0.point, point), proj))
83+
},
84+
)
85+
}
86+
6287
/// Casts a ray on this BVH using the provided leaf ray-cast function.
6388
///
6489
/// The `primitive_check` delegates the ray-casting task to an external function that

src/query/contact_manifolds/contact_manifolds_voxels_composite_shape.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub fn contact_manifolds_voxels_composite_shape<ManifoldData, ContactData>(
135135
timestamp: new_timestamp,
136136
};
137137

138-
let vox_id = vox1.linear_id;
138+
let vox_id = vox1.linear_id.flat_id() as u32;
139139
let (id1, id2) = if flipped {
140140
(leaf2, vox_id)
141141
} else {

src/query/contact_manifolds/contact_manifolds_voxels_shape.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ pub fn contact_manifolds_voxels_shape<ManifoldData, ContactData>(
171171
timestamp: new_timestamp,
172172
};
173173

174-
let vid = vox1.linear_id;
174+
let vid = vox1.linear_id.flat_id() as u32;
175175
let (id1, id2) = if flipped { (0, vid) } else { (vid, 0) };
176176
manifolds.push(ContactManifold::with_data(
177177
id1,
@@ -329,6 +329,7 @@ impl CanonicalVoxelShape {
329329
// detection).
330330
let mins = voxels.domain()[0] - Vector::repeat(1);
331331
let maxs = voxels.domain()[1];
332+
let counts = maxs - mins;
332333
let mask1 = vox.state.free_faces();
333334

334335
let adjust_canon = |axis: AxisMask, i: usize, key: &mut Point<i32>, val: i32| {
@@ -348,12 +349,21 @@ impl CanonicalVoxelShape {
348349
adjust_canon(AxisMask::Z_NEG, 2, &mut key_low, mins[2]);
349350
}
350351

352+
#[cfg(feature = "dim2")]
353+
let workspace_id = |vox: Point<i32>| {
354+
let local = vox - mins;
355+
(local.x + local.y * counts.x) as u32
356+
};
357+
358+
#[cfg(feature = "dim3")]
359+
let workspace_id = |vox: Point<i32>| {
360+
let local = vox - mins;
361+
(local.x + local.y * counts.x + local.z * counts.x * counts.y) as u32
362+
};
363+
351364
Self {
352365
range: [key_low, key_high],
353-
workspace_key: Vector2::new(
354-
voxels.linear_index(key_low),
355-
voxels.linear_index(key_high),
356-
),
366+
workspace_key: Vector2::new(workspace_id(key_low), workspace_id(key_high)),
357367
}
358368
}
359369

src/query/contact_manifolds/contact_manifolds_voxels_voxels.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ pub fn contact_manifolds_voxels_voxels<'a, ManifoldData, ContactData>(
132132
};
133133

134134
manifolds.push(ContactManifold::with_data(
135-
vox1.linear_id,
136-
vox2.linear_id,
135+
vox1.linear_id.flat_id() as u32,
136+
vox2.linear_id.flat_id() as u32,
137137
ManifoldData::default(),
138138
));
139139

0 commit comments

Comments
 (0)